1 /*
2  * Copyright (C) 2019-2020 Paul Cercueil <paul@crapouillou.net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  */
14 
15 #include "config.h"
16 #include "lightrec-private.h"
17 #include "memmanager.h"
18 
19 #include <stdlib.h>
20 #if ENABLE_TINYMM
21 #include <tinymm.h>
22 #endif
23 
24 #ifdef ENABLE_THREADED_COMPILER
25 #include <stdatomic.h>
26 
27 static atomic_uint lightrec_bytes[MEM_TYPE_END];
28 
lightrec_register(enum mem_type type,unsigned int len)29 void lightrec_register(enum mem_type type, unsigned int len)
30 {
31 	atomic_fetch_add(&lightrec_bytes[type], len);
32 }
33 
lightrec_unregister(enum mem_type type,unsigned int len)34 void lightrec_unregister(enum mem_type type, unsigned int len)
35 {
36 	atomic_fetch_sub(&lightrec_bytes[type], len);
37 }
38 
lightrec_get_mem_usage(enum mem_type type)39 unsigned int lightrec_get_mem_usage(enum mem_type type)
40 {
41 	return atomic_load(&lightrec_bytes[type]);
42 }
43 
44 #else /* ENABLE_THREADED_COMPILER */
45 
46 static unsigned int lightrec_bytes[MEM_TYPE_END];
47 
lightrec_register(enum mem_type type,unsigned int len)48 void lightrec_register(enum mem_type type, unsigned int len)
49 {
50 	lightrec_bytes[type] += len;
51 }
52 
lightrec_unregister(enum mem_type type,unsigned int len)53 void lightrec_unregister(enum mem_type type, unsigned int len)
54 {
55 	lightrec_bytes[type] -= len;
56 }
57 
lightrec_get_mem_usage(enum mem_type type)58 unsigned int lightrec_get_mem_usage(enum mem_type type)
59 {
60 	return lightrec_bytes[type];
61 }
62 #endif /* ENABLE_THREADED_COMPILER */
63 
lightrec_get_total_mem_usage(void)64 unsigned int lightrec_get_total_mem_usage(void)
65 {
66 	unsigned int i, count;
67 
68 	for (i = 0, count = 0; i < MEM_TYPE_END; i++)
69 		count += lightrec_get_mem_usage((enum mem_type)i);
70 
71 	return count;
72 }
73 
lightrec_malloc(struct lightrec_state * state,enum mem_type type,unsigned int len)74 void * lightrec_malloc(struct lightrec_state *state,
75 		       enum mem_type type, unsigned int len)
76 {
77 	void *ptr;
78 
79 #if ENABLE_TINYMM
80 	if (type == MEM_FOR_IR)
81 		ptr = tinymm_malloc(state->tinymm, len);
82 	else
83 #endif
84 		ptr = malloc(len);
85 	if (!ptr)
86 		return NULL;
87 
88 	lightrec_register(type, len);
89 
90 	return ptr;
91 }
92 
lightrec_calloc(struct lightrec_state * state,enum mem_type type,unsigned int len)93 void * lightrec_calloc(struct lightrec_state *state,
94 		       enum mem_type type, unsigned int len)
95 {
96 	void *ptr;
97 
98 #if ENABLE_TINYMM
99 	if (type == MEM_FOR_IR)
100 		ptr = tinymm_zalloc(state->tinymm, len);
101 	else
102 #endif
103 		ptr = calloc(1, len);
104 	if (!ptr)
105 		return NULL;
106 
107 	lightrec_register(type, len);
108 
109 	return ptr;
110 }
111 
lightrec_free(struct lightrec_state * state,enum mem_type type,unsigned int len,void * ptr)112 void lightrec_free(struct lightrec_state *state,
113 		   enum mem_type type, unsigned int len, void *ptr)
114 {
115 	lightrec_unregister(type, len);
116 #if ENABLE_TINYMM
117 	if (type == MEM_FOR_IR)
118 		tinymm_free(state->tinymm, ptr);
119 	else
120 #endif
121 		free(ptr);
122 }
123 
lightrec_get_average_ipi(void)124 float lightrec_get_average_ipi(void)
125 {
126 	unsigned int code_mem = lightrec_get_mem_usage(MEM_FOR_CODE);
127 	unsigned int native_mem = lightrec_get_mem_usage(MEM_FOR_MIPS_CODE);
128 
129 	return native_mem ? (float)code_mem / (float)native_mem : 0.0f;
130 }
131