Browse Source

added gc handling for pages not being allocated on requested align (close #493)

Nicolas Cannasse 3 years ago
parent
commit
21ede72a8a
1 changed files with 35 additions and 0 deletions
  1. 35 0
      src/gc.c

+ 35 - 0
src/gc.c

@@ -923,6 +923,14 @@ void *sys_alloc_align( int size, int align );
 void sys_free_align( void *ptr, int size );
 void sys_free_align( void *ptr, int size );
 #elif !defined(HL_WIN)
 #elif !defined(HL_WIN)
 static void *base_addr = (void*)0x40000000;
 static void *base_addr = (void*)0x40000000;
+typedef struct _pextra pextra;
+struct _pextra {
+	void *page_ptr;
+	void *base_ptr;
+	pextra *next;
+};
+static pextra *extra_pages = NULL;
+#define EXTRA_SIZE (GC_PAGE_SIZE + (4<<10))
 #endif
 #endif
 
 
 static void *gc_alloc_page_memory( int size ) {
 static void *gc_alloc_page_memory( int size ) {
@@ -948,6 +956,7 @@ static void *gc_alloc_page_memory( int size ) {
 #elif defined(HL_CONSOLE)
 #elif defined(HL_CONSOLE)
 	return sys_alloc_align(size, GC_PAGE_SIZE);
 	return sys_alloc_align(size, GC_PAGE_SIZE);
 #else
 #else
+	static int recursions = 0;
 	int i = 0;
 	int i = 0;
 	while( gc_will_collide(base_addr,size) ) {
 	while( gc_will_collide(base_addr,size) ) {
 		base_addr = (char*)base_addr + GC_PAGE_SIZE;
 		base_addr = (char*)base_addr + GC_PAGE_SIZE;
@@ -961,6 +970,17 @@ static void *gc_alloc_page_memory( int size ) {
 		return NULL;
 		return NULL;
 	if( ((int_val)ptr) & (GC_PAGE_SIZE-1) ) {
 	if( ((int_val)ptr) & (GC_PAGE_SIZE-1) ) {
 		munmap(ptr,size);
 		munmap(ptr,size);
+		if( recursions >= 5 ) {
+			ptr = mmap(base_addr,size+EXTRA_SIZE,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
+			int offset = (int)((int_val)ptr) & (GC_PAGE_SIZE-1);
+			void *aligned = (char*)ptr + (GC_PAGE_SIZE - offset);
+			pextra *inf = (pextra*)(offset > (EXTRA_SIZE>>1) ? ((char*)ptr + EXTRA_SIZE - sizeof(pextra)) : (char*)ptr);
+			inf->page_ptr = aligned;
+			inf->base_ptr = ptr;
+			inf->next = extra_pages;
+			extra_pages = inf;
+			return aligned;
+		}
 		void *tmp;
 		void *tmp;
 		int tmp_size = (int)((int_val)ptr - (int_val)base_addr);
 		int tmp_size = (int)((int_val)ptr - (int_val)base_addr);
 		if( tmp_size > 0 ) {
 		if( tmp_size > 0 ) {
@@ -971,7 +991,9 @@ static void *gc_alloc_page_memory( int size ) {
 			tmp = NULL;
 			tmp = NULL;
 		}
 		}
 		if( tmp ) tmp = mmap(tmp,tmp_size,PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
 		if( tmp ) tmp = mmap(tmp,tmp_size,PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
+		recursions++
 		ptr = gc_alloc_page_memory(size);
 		ptr = gc_alloc_page_memory(size);
+		recursions--;
 		if( tmp ) munmap(tmp,tmp_size);
 		if( tmp ) munmap(tmp,tmp_size);
 		return ptr;
 		return ptr;
 	}
 	}
@@ -986,6 +1008,19 @@ static void gc_free_page_memory( void *ptr, int size ) {
 #elif defined(HL_CONSOLE)
 #elif defined(HL_CONSOLE)
 	sys_free_align(ptr,size);
 	sys_free_align(ptr,size);
 #else
 #else
+	pextra *e = extra_pages, *prev = NULL;
+	while( e ) {
+		if( e->page_ptr == ptr ) {
+			if( prev )
+				prev->next = e->next;
+			else
+				extra_pages = e->next;
+			munmap(e->base_ptr, size + EXTRA_SIZE);
+			return;
+		}
+		prev = e;
+		e = e->next;
+	}
 	munmap(ptr,size);
 	munmap(ptr,size);
 #endif
 #endif
 }
 }