zen_memory.c 4.1 KB
Newer Older
1
#include <errno.h>
2
#include <stdlib.h>
3
4
#include <jutils.h>

5
6
7
#include <zenroom.h>
#include <umm_malloc.h>

Jaromil's avatar
Jaromil committed
8
9
extern void *umm_info(void*);

10
void *zen_memalign(const size_t size, const size_t align) {
11
	void *mem = NULL;
12
13
14
	// preserve const values as they seem to be overwritten by calls
	size_t vsize = size;
	size_t valign = align;
Jaromil's avatar
Jaromil committed
15
16
17
18
19
20
21
22
23
24
// TODO: Round up to the next highest power of 2
// uint32_t v = valign; // compute the next highest power of 2 of 32-bit v
// v--;
// v |= v >> 1;
// v |= v >> 2;
// v |= v >> 4;
// v |= v >> 8;
// v |= v >> 16;
// v++;
// // from https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
25
	(void)valign;
26
# if defined(_WIN32)
27
	mem = __mingw_aligned_malloc(vsize, valign);
28
	if(!mem) {
29
		error(0, "error in %u byte aligned memory allocation of %u bytes.",
Jaromil's avatar
Jaromil committed
30
		      align, size);
31
		return NULL; }
32
33
# elif defined(__EMSCRIPTEN__)
	mem = malloc(vsize);
34
35
# else
	int res;
36
	res = posix_memalign(&mem, valign, vsize);
37
	if(res == ENOMEM) {
38
		error(0, "insufficient memory to allocate %u bytes.", size);
39
40
		return NULL; }
	if(res == EINVAL) {
41
		error(0, "invalid memory alignment at %u bytes.",align);
42
43
44
45
46
		return NULL; }
# endif
	return(mem);
}

47
48
49
// global memory manager saved here
// TODO: this is not reentrant (see also umm_malloc.c)
static zen_mem_t *zen_mem;
50
51

// Global HEAP pointer in the STACK
52
53
54
55
56
57
58
59
60
61
62
63
64
zen_mem_t *umm_memory_init(size_t S) {
	zen_mem_t *mem = malloc(sizeof(zen_mem_t));
	mem->heap = zen_memalign(S, 8);
	mem->heap_size = S;
	mem->malloc = umm_malloc;
	mem->realloc = umm_realloc;
	mem->free = umm_free;
	mem->sys_malloc = malloc;
	mem->sys_realloc = realloc;
	mem->sys_free = free;
	umm_init(mem->heap, mem->heap_size);
	zen_mem = mem;
	return mem;
65
66
67
	// pointers saved in umm_malloc.c (stack)
}

68
69
70
71
72
73
74
75
76
77
78
79
zen_mem_t *libc_memory_init() {
	zen_mem_t *mem = malloc(sizeof(zen_mem_t));
	mem->heap = NULL;
	mem->heap_size = 0;
	mem->malloc = malloc;
	mem->realloc = realloc;
	mem->free = free;
	mem->sys_malloc = malloc;
	mem->sys_realloc = realloc;
	mem->sys_free = free;
	zen_mem = mem;
	return mem;
80
}
81
82
83
84
85
86
87

void *zen_memory_alloc(size_t size) { return (*zen_mem->malloc)(size); }
void *zen_memory_realloc(void *ptr, size_t size) { return (*zen_mem->realloc)(ptr, size); }
void  zen_memory_free(void *ptr) { (*zen_mem->free)(ptr); }
void *system_alloc(size_t size) { return (*zen_mem->sys_malloc)(size); }
void *system_realloc(void *ptr, size_t size) { return (*zen_mem->sys_realloc)(ptr, size); }
void  system_free(void *ptr) { (*zen_mem->sys_free)(ptr); }
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102



/**
 * Implementation of the memory allocator for the Lua state.
 *
 * See: http://www.lua.org/manual/5.3/manual.html#lua_Alloc
 *
 * @param ud User Data Pointer
 * @param ptr Pointer to the memory block being allocated/reallocated/freed.
 * @param osize The original size of the memory block.
 * @param nsize The new size of the memory block.
 *
 * @return void* A pointer to the memory block.
 */
103
104
void *zen_memory_manager(void *ud, void *ptr, size_t osize, size_t nsize) {
	zen_mem_t *mem = (zen_mem_t*)ud;
105
	if(!mem) return NULL;
106
107
108
109
110
111
112
	if(ptr == NULL) {
		// When ptr is NULL, osize encodes the kind of object that Lua
		// is allocating. osize is any of LUA_TSTRING, LUA_TTABLE,
		// LUA_TFUNCTION, LUA_TUSERDATA, or LUA_TTHREAD when (and only
		// when) Lua is creating a new object of that type. When osize
		// is some other value, Lua is allocating memory for something
		// else.
113
114
115
116
117
118
		if(nsize!=0) {
			void *ret = (*mem->malloc)(nsize);
			if(ret) return ret;
			error(NULL,"Malloc out of memory, requested %u B",nsize);
			return NULL;
		} else return NULL;
119
120
121
122
123
124
125
126

	} else {
		// When ptr is not NULL, osize is the size of the block
		// pointed by ptr, that is, the size given when it was
		// allocated or reallocated.
		if(nsize==0) {
			// When nsize is zero, the allocator must behave like free
			// and return NULL.
127
			(*mem->free)(ptr);
128
129
130
131
132
133
134
			return NULL; }

		// When nsize is not zero, the allocator must behave like
		// realloc. The allocator returns NULL if and only if it
		// cannot fulfill the request. Lua assumes that the allocator
		// never fails when osize >= nsize.
		if(osize >= nsize) { // shrink
135
			return (*mem->realloc)(ptr, nsize);
136
		} else { // extend
137
			return (*mem->realloc)(ptr, nsize);
138
139
		}
	}
140
}