624 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			624 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
 | |
| 
 | |
| /******************************************************************
 | |
| 
 | |
|   AmigaOS-spesific routines for GC.
 | |
|   This file is normally included from os_dep.c
 | |
| 
 | |
| ******************************************************************/
 | |
| 
 | |
| 
 | |
| #if !defined(GC_AMIGA_DEF) && !defined(GC_AMIGA_SB) && !defined(GC_AMIGA_DS) && !defined(GC_AMIGA_AM)
 | |
| # include "gc_priv.h"
 | |
| # include <stdio.h>
 | |
| # include <signal.h>
 | |
| # define GC_AMIGA_DEF
 | |
| # define GC_AMIGA_SB
 | |
| # define GC_AMIGA_DS
 | |
| # define GC_AMIGA_AM
 | |
| #endif
 | |
| 
 | |
| 
 | |
| #ifdef GC_AMIGA_DEF
 | |
| 
 | |
| # ifndef __GNUC__
 | |
| #   include <exec/exec.h>
 | |
| # endif
 | |
| # include <proto/exec.h>
 | |
| # include <proto/dos.h>
 | |
| # include <dos/dosextens.h>
 | |
| # include <workbench/startup.h>
 | |
| 
 | |
| #endif
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| #ifdef GC_AMIGA_SB
 | |
| 
 | |
| /******************************************************************
 | |
|    Find the base of the stack.
 | |
| ******************************************************************/
 | |
| 
 | |
| ptr_t GC_get_stack_base()
 | |
| {
 | |
|     struct Process *proc = (struct Process*)SysBase->ThisTask;
 | |
|  
 | |
|     /* Reference: Amiga Guru Book Pages: 42,567,574 */
 | |
|     if (proc->pr_Task.tc_Node.ln_Type==NT_PROCESS
 | |
|         && proc->pr_CLI != NULL) {
 | |
| 	/* first ULONG is StackSize */
 | |
| 	/*longPtr = proc->pr_ReturnAddr;
 | |
| 	size = longPtr[0];*/
 | |
| 
 | |
| 	return (char *)proc->pr_ReturnAddr + sizeof(ULONG);
 | |
|     } else {
 | |
| 	return (char *)proc->pr_Task.tc_SPUpper;
 | |
|     }
 | |
| }
 | |
| 
 | |
| #if 0 /* old version */
 | |
| ptr_t GC_get_stack_base()
 | |
| {
 | |
|     extern struct WBStartup *_WBenchMsg;
 | |
|     extern long __base;
 | |
|     extern long __stack;
 | |
|     struct Task *task;
 | |
|     struct Process *proc;
 | |
|     struct CommandLineInterface *cli;
 | |
|     long size;
 | |
| 
 | |
|     if ((task = FindTask(0)) == 0) {
 | |
| 	GC_err_puts("Cannot find own task structure\n");
 | |
| 	ABORT("task missing");
 | |
|     }
 | |
|     proc = (struct Process *)task;
 | |
|     cli = BADDR(proc->pr_CLI);
 | |
| 
 | |
|     if (_WBenchMsg != 0 || cli == 0) {
 | |
| 	size = (char *)task->tc_SPUpper - (char *)task->tc_SPLower;
 | |
|     } else {
 | |
| 	size = cli->cli_DefaultStack * 4;
 | |
|     }
 | |
|     return (ptr_t)(__base + GC_max(size, __stack));
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| #endif
 | |
| 
 | |
| 
 | |
| #ifdef GC_AMIGA_DS
 | |
| /******************************************************************
 | |
|    Register data segments.
 | |
| ******************************************************************/
 | |
| 
 | |
|    void GC_register_data_segments()
 | |
|    {
 | |
|      struct Process	*proc;
 | |
|      struct CommandLineInterface *cli;
 | |
|      BPTR myseglist;
 | |
|      ULONG *data;
 | |
|  
 | |
|      int	num;
 | |
| 
 | |
| 
 | |
| #    ifdef __GNUC__
 | |
|         ULONG dataSegSize;
 | |
|         GC_bool found_segment = FALSE;
 | |
| 	extern char __data_size[];
 | |
| 
 | |
| 	dataSegSize=__data_size+8;
 | |
| 	/* Can`t find the Location of __data_size, because
 | |
|            it`s possible that is it, inside the segment. */
 | |
| 
 | |
| #     endif
 | |
| 
 | |
| 	proc= (struct Process*)SysBase->ThisTask;
 | |
| 
 | |
| 	/* Reference: Amiga Guru Book Pages: 538ff,565,573
 | |
| 		     and XOper.asm */
 | |
| 	if (proc->pr_Task.tc_Node.ln_Type==NT_PROCESS) {
 | |
| 	  if (proc->pr_CLI == NULL) {
 | |
| 	    myseglist = proc->pr_SegList;
 | |
| 	  } else {
 | |
| 	    /* ProcLoaded	'Loaded as a command: '*/
 | |
| 	    cli = BADDR(proc->pr_CLI);
 | |
| 	    myseglist = cli->cli_Module;
 | |
| 	  }
 | |
| 	} else {
 | |
| 	  ABORT("Not a Process.");
 | |
|  	}
 | |
| 
 | |
| 	if (myseglist == NULL) {
 | |
| 	    ABORT("Arrrgh.. can't find segments, aborting");
 | |
|  	}
 | |
| 
 | |
| 	/* xoper hunks Shell Process */
 | |
| 
 | |
| 	num=0;
 | |
|         for (data = (ULONG *)BADDR(myseglist); data != NULL;
 | |
|              data = (ULONG *)BADDR(data[0])) {
 | |
| 	  if (((ULONG) GC_register_data_segments < (ULONG) &data[1]) ||
 | |
| 	      ((ULONG) GC_register_data_segments > (ULONG) &data[1] + data[-1])) {
 | |
| #             ifdef __GNUC__
 | |
| 		if (dataSegSize == data[-1]) {
 | |
| 		  found_segment = TRUE;
 | |
| 		}
 | |
| # 	      endif
 | |
| 	      GC_add_roots_inner((char *)&data[1],
 | |
| 				 ((char *)&data[1]) + data[-1], FALSE);
 | |
|           }
 | |
|           ++num;
 | |
|         } /* for */
 | |
| # 	ifdef __GNUC__
 | |
| 	   if (!found_segment) {
 | |
| 	     ABORT("Can`t find correct Segments.\nSolution: Use an newer version of ixemul.library");
 | |
| 	   }
 | |
| # 	endif
 | |
|   }
 | |
| 
 | |
| #if 0 /* old version */
 | |
|   void GC_register_data_segments()
 | |
|   {
 | |
|     extern struct WBStartup *_WBenchMsg;
 | |
|     struct Process	*proc;
 | |
|     struct CommandLineInterface *cli;
 | |
|     BPTR myseglist;
 | |
|     ULONG *data;
 | |
| 
 | |
|     if ( _WBenchMsg != 0 ) {
 | |
| 	if ((myseglist = _WBenchMsg->sm_Segment) == 0) {
 | |
| 	    GC_err_puts("No seglist from workbench\n");
 | |
| 	    return;
 | |
| 	}
 | |
|     } else {
 | |
| 	if ((proc = (struct Process *)FindTask(0)) == 0) {
 | |
| 	    GC_err_puts("Cannot find process structure\n");
 | |
| 	    return;
 | |
| 	}
 | |
| 	if ((cli = BADDR(proc->pr_CLI)) == 0) {
 | |
| 	    GC_err_puts("No CLI\n");
 | |
| 	    return;
 | |
| 	}
 | |
| 	if ((myseglist = cli->cli_Module) == 0) {
 | |
| 	    GC_err_puts("No seglist from CLI\n");
 | |
| 	    return;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     for (data = (ULONG *)BADDR(myseglist); data != 0;
 | |
|          data = (ULONG *)BADDR(data[0])) {
 | |
| #        ifdef AMIGA_SKIP_SEG
 | |
|            if (((ULONG) GC_register_data_segments < (ULONG) &data[1]) ||
 | |
|            ((ULONG) GC_register_data_segments > (ULONG) &data[1] + data[-1])) {
 | |
| #	 else
 | |
|       	   {
 | |
| #	 endif /* AMIGA_SKIP_SEG */
 | |
|           GC_add_roots_inner((char *)&data[1],
 | |
|           		     ((char *)&data[1]) + data[-1], FALSE);
 | |
|          }
 | |
|     }
 | |
|   }
 | |
| #endif /* old version */
 | |
| 
 | |
| 
 | |
| #endif
 | |
| 
 | |
| 
 | |
| 
 | |
| #ifdef GC_AMIGA_AM
 | |
| 
 | |
| #ifndef GC_AMIGA_FASTALLOC
 | |
| 
 | |
| void *GC_amiga_allocwrapper(size_t size,void *(*AllocFunction)(size_t size2)){
 | |
| 	return (*AllocFunction)(size);
 | |
| }
 | |
| 
 | |
| void *(*GC_amiga_allocwrapper_do)(size_t size,void *(*AllocFunction)(size_t size2))
 | |
| 	=GC_amiga_allocwrapper;
 | |
| 
 | |
| #else
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| void *GC_amiga_allocwrapper_firsttime(size_t size,void *(*AllocFunction)(size_t size2));
 | |
| 
 | |
| void *(*GC_amiga_allocwrapper_do)(size_t size,void *(*AllocFunction)(size_t size2))
 | |
| 	=GC_amiga_allocwrapper_firsttime;
 | |
| 
 | |
| 
 | |
| /******************************************************************
 | |
|    Amiga-spesific routines to obtain memory, and force GC to give
 | |
|    back fast-mem whenever possible.
 | |
| 	These hacks makes gc-programs go many times faster when
 | |
|    the amiga is low on memory, and are therefore strictly necesarry.
 | |
| 
 | |
|    -Kjetil S. Matheussen, 2000.
 | |
| ******************************************************************/
 | |
| 
 | |
| 
 | |
| 
 | |
| /* List-header for all allocated memory. */
 | |
| 
 | |
| struct GC_Amiga_AllocedMemoryHeader{
 | |
| 	ULONG size;
 | |
| 	struct GC_Amiga_AllocedMemoryHeader *next;
 | |
| };
 | |
| struct GC_Amiga_AllocedMemoryHeader *GC_AMIGAMEM=(struct GC_Amiga_AllocedMemoryHeader *)(int)~(NULL);
 | |
| 
 | |
| 
 | |
| 
 | |
| /* Type of memory. Once in the execution of a program, this might change to MEMF_ANY|MEMF_CLEAR */
 | |
| 
 | |
| ULONG GC_AMIGA_MEMF = MEMF_FAST | MEMF_CLEAR;
 | |
| 
 | |
| 
 | |
| /* Prevents GC_amiga_get_mem from allocating memory if this one is TRUE. */
 | |
| #ifndef GC_AMIGA_ONLYFAST
 | |
| BOOL GC_amiga_dontalloc=FALSE;
 | |
| #endif
 | |
| 
 | |
| #ifdef GC_AMIGA_PRINTSTATS
 | |
| int succ=0,succ2=0;
 | |
| int nsucc=0,nsucc2=0;
 | |
| int nullretries=0;
 | |
| int numcollects=0;
 | |
| int chipa=0;
 | |
| int allochip=0;
 | |
| int allocfast=0;
 | |
| int cur0=0;
 | |
| int cur1=0;
 | |
| int cur10=0;
 | |
| int cur50=0;
 | |
| int cur150=0;
 | |
| int cur151=0;
 | |
| int ncur0=0;
 | |
| int ncur1=0;
 | |
| int ncur10=0;
 | |
| int ncur50=0;
 | |
| int ncur150=0;
 | |
| int ncur151=0;
 | |
| #endif
 | |
| 
 | |
| /* Free everything at program-end. */
 | |
| 
 | |
| void GC_amiga_free_all_mem(void){
 | |
| 	struct GC_Amiga_AllocedMemoryHeader *gc_am=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(GC_AMIGAMEM));
 | |
| 	struct GC_Amiga_AllocedMemoryHeader *temp;
 | |
| 
 | |
| #ifdef GC_AMIGA_PRINTSTATS
 | |
| 	printf("\n\n"
 | |
| 		"%d bytes of chip-mem, and %d bytes of fast-mem where allocated from the OS.\n",
 | |
| 		allochip,allocfast
 | |
| 	);
 | |
| 	printf(
 | |
| 		"%d bytes of chip-mem were returned from the GC_AMIGA_FASTALLOC supported allocating functions.\n",
 | |
| 		chipa
 | |
| 	);
 | |
| 	printf("\n");
 | |
| 	printf("GC_gcollect was called %d times to avoid returning NULL or start allocating with the MEMF_ANY flag.\n",numcollects);
 | |
| 	printf("%d of them was a success. (the others had to use allocation from the OS.)\n",nullretries);
 | |
| 	printf("\n");
 | |
| 	printf("Succeded forcing %d gc-allocations (%d bytes) of chip-mem to be fast-mem.\n",succ,succ2);
 | |
| 	printf("Failed forcing %d gc-allocations (%d bytes) of chip-mem to be fast-mem.\n",nsucc,nsucc2);
 | |
| 	printf("\n");
 | |
| 	printf(
 | |
| 		"Number of retries before succeding a chip->fast force:\n"
 | |
| 		"0: %d, 1: %d, 2-9: %d, 10-49: %d, 50-149: %d, >150: %d\n",
 | |
| 		cur0,cur1,cur10,cur50,cur150,cur151
 | |
| 	);
 | |
| 	printf(
 | |
| 		"Number of retries before giving up a chip->fast force:\n"
 | |
| 		"0: %d, 1: %d, 2-9: %d, 10-49: %d, 50-149: %d, >150: %d\n",
 | |
| 		ncur0,ncur1,ncur10,ncur50,ncur150,ncur151
 | |
| 	);
 | |
| #endif
 | |
| 
 | |
| 	while(gc_am!=NULL){
 | |
| 		temp=gc_am->next;
 | |
| 		FreeMem(gc_am,gc_am->size);
 | |
| 		gc_am=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(temp));
 | |
| 	}
 | |
| }
 | |
| 
 | |
| #ifndef GC_AMIGA_ONLYFAST
 | |
| 
 | |
| /* All memory with address lower than this one is chip-mem. */
 | |
| 
 | |
| char *chipmax;
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Allways set to the last size of memory tried to be allocated.
 | |
|  * Needed to ensure allocation when the size is bigger than 100000.
 | |
|  *
 | |
|  */
 | |
| size_t latestsize;
 | |
| 
 | |
| #endif
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * The actual function that is called with the GET_MEM macro.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| void *GC_amiga_get_mem(size_t size){
 | |
| 	struct GC_Amiga_AllocedMemoryHeader *gc_am;
 | |
| 
 | |
| #ifndef GC_AMIGA_ONLYFAST
 | |
| 	if(GC_amiga_dontalloc==TRUE){
 | |
| //		printf("rejected, size: %d, latestsize: %d\n",size,latestsize);
 | |
| 		return NULL;
 | |
| 	}
 | |
| 
 | |
| 	// We really don't want to use chip-mem, but if we must, then as little as possible.
 | |
| 	if(GC_AMIGA_MEMF==(MEMF_ANY|MEMF_CLEAR) && size>100000 && latestsize<50000) return NULL;
 | |
| #endif
 | |
| 
 | |
| 	gc_am=AllocMem((ULONG)(size + sizeof(struct GC_Amiga_AllocedMemoryHeader)),GC_AMIGA_MEMF);
 | |
| 	if(gc_am==NULL) return NULL;
 | |
| 
 | |
| 	gc_am->next=GC_AMIGAMEM;
 | |
| 	gc_am->size=size + sizeof(struct GC_Amiga_AllocedMemoryHeader);
 | |
| 	GC_AMIGAMEM=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(gc_am));
 | |
| 
 | |
| //	printf("Allocated %d (%d) bytes at address: %x. Latest: %d\n",size,tot,gc_am,latestsize);
 | |
| 
 | |
| #ifdef GC_AMIGA_PRINTSTATS
 | |
| 	if((char *)gc_am<chipmax){
 | |
| 		allochip+=size;
 | |
| 	}else{
 | |
| 		allocfast+=size;
 | |
| 	}
 | |
| #endif
 | |
| 
 | |
| 	return gc_am+1;
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| #ifndef GC_AMIGA_ONLYFAST
 | |
| 
 | |
| /* Tries very hard to force GC to find fast-mem to return. Done recursively
 | |
|  * to hold the rejected memory-pointers reachable from the collector in an
 | |
|  * easy way.
 | |
|  *
 | |
|  */
 | |
| #ifdef GC_AMIGA_RETRY
 | |
| void *GC_amiga_rec_alloc(size_t size,void *(*AllocFunction)(size_t size2),const int rec){
 | |
| 	void *ret;
 | |
| 
 | |
| 	ret=(*AllocFunction)(size);
 | |
| 
 | |
| #ifdef GC_AMIGA_PRINTSTATS
 | |
| 	if((char *)ret>chipmax || ret==NULL){
 | |
| 		if(ret==NULL){
 | |
| 			nsucc++;
 | |
| 			nsucc2+=size;
 | |
| 			if(rec==0) ncur0++;
 | |
| 			if(rec==1) ncur1++;
 | |
| 			if(rec>1 && rec<10) ncur10++;
 | |
| 			if(rec>=10 && rec<50) ncur50++;
 | |
| 			if(rec>=50 && rec<150) ncur150++;
 | |
| 			if(rec>=150) ncur151++;
 | |
| 		}else{
 | |
| 			succ++;
 | |
| 			succ2+=size;
 | |
| 			if(rec==0) cur0++;
 | |
| 			if(rec==1) cur1++;
 | |
| 			if(rec>1 && rec<10) cur10++;
 | |
| 			if(rec>=10 && rec<50) cur50++;
 | |
| 			if(rec>=50 && rec<150) cur150++;
 | |
| 			if(rec>=150) cur151++;
 | |
| 		}
 | |
| 	}
 | |
| #endif
 | |
| 
 | |
| 	if (((char *)ret)<=chipmax && ret!=NULL && (rec<(size>500000?9:size/5000))){
 | |
| 		ret=GC_amiga_rec_alloc(size,AllocFunction,rec+1);
 | |
| //		GC_free(ret2);
 | |
| 	}
 | |
| 
 | |
| 	return ret;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| /* The allocating-functions defined inside the amiga-blocks in gc.h is called
 | |
|  * via these functions.
 | |
|  */
 | |
| 
 | |
| 
 | |
| void *GC_amiga_allocwrapper_any(size_t size,void *(*AllocFunction)(size_t size2)){
 | |
| 	void *ret,*ret2;
 | |
| 
 | |
| 	GC_amiga_dontalloc=TRUE;	// Pretty tough thing to do, but its indeed necesarry.
 | |
| 	latestsize=size;
 | |
| 
 | |
| 	ret=(*AllocFunction)(size);
 | |
| 
 | |
| 	if(((char *)ret) <= chipmax){
 | |
| 		if(ret==NULL){
 | |
| 			//Give GC access to allocate memory.
 | |
| #ifdef GC_AMIGA_GC
 | |
| 			if(!GC_dont_gc){
 | |
| 				GC_gcollect();
 | |
| #ifdef GC_AMIGA_PRINTSTATS
 | |
| 				numcollects++;
 | |
| #endif
 | |
| 				ret=(*AllocFunction)(size);
 | |
| 			}
 | |
| #endif
 | |
| 			if(ret==NULL){
 | |
| 				GC_amiga_dontalloc=FALSE;
 | |
| 				ret=(*AllocFunction)(size);
 | |
| 				if(ret==NULL){
 | |
| 					WARN("Out of Memory!  Returning NIL!\n", 0);
 | |
| 				}
 | |
| 			}
 | |
| #ifdef GC_AMIGA_PRINTSTATS
 | |
| 			else{
 | |
| 				nullretries++;
 | |
| 			}
 | |
| 			if(ret!=NULL && (char *)ret<=chipmax) chipa+=size;
 | |
| #endif
 | |
| 		}
 | |
| #ifdef GC_AMIGA_RETRY
 | |
| 		else{
 | |
| 			/* We got chip-mem. Better try again and again and again etc., we might get fast-mem sooner or later... */
 | |
| 			/* Using gctest to check the effectiviness of doing this, does seldom give a very good result. */
 | |
| 			/* However, real programs doesn't normally rapidly allocate and deallocate. */
 | |
| //			printf("trying to force... %d bytes... ",size);
 | |
| 			if(
 | |
| 				AllocFunction!=GC_malloc_uncollectable
 | |
| #ifdef ATOMIC_UNCOLLECTABLE
 | |
| 				&& AllocFunction!=GC_malloc_atomic_uncollectable
 | |
| #endif
 | |
| 			){
 | |
| 				ret2=GC_amiga_rec_alloc(size,AllocFunction,0);
 | |
| 			}else{
 | |
| 				ret2=(*AllocFunction)(size);
 | |
| #ifdef GC_AMIGA_PRINTSTATS
 | |
| 				if((char *)ret2<chipmax || ret2==NULL){
 | |
| 					nsucc++;
 | |
| 					nsucc2+=size;
 | |
| 					ncur0++;
 | |
| 				}else{
 | |
| 					succ++;
 | |
| 					succ2+=size;
 | |
| 					cur0++;
 | |
| 				}
 | |
| #endif
 | |
| 			}
 | |
| 			if(((char *)ret2)>chipmax){
 | |
| //				printf("Succeeded.\n");
 | |
| 				GC_free(ret);
 | |
| 				ret=ret2;
 | |
| 			}else{
 | |
| 				GC_free(ret2);
 | |
| //				printf("But did not succeed.\n");
 | |
| 			}
 | |
| 		}
 | |
| #endif
 | |
| 	}
 | |
| 
 | |
| 	GC_amiga_dontalloc=FALSE;
 | |
| 
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| void (*GC_amiga_toany)(void)=NULL;
 | |
| 
 | |
| void GC_amiga_set_toany(void (*func)(void)){
 | |
| 	GC_amiga_toany=func;
 | |
| }
 | |
| 
 | |
| #endif // !GC_AMIGA_ONLYFAST
 | |
| 
 | |
| 
 | |
| void *GC_amiga_allocwrapper_fast(size_t size,void *(*AllocFunction)(size_t size2)){
 | |
| 	void *ret;
 | |
| 
 | |
| 	ret=(*AllocFunction)(size);
 | |
| 
 | |
| 	if(ret==NULL){
 | |
| 		// Enable chip-mem allocation.
 | |
| //		printf("ret==NULL\n");
 | |
| #ifdef GC_AMIGA_GC
 | |
| 		if(!GC_dont_gc){
 | |
| 			GC_gcollect();
 | |
| #ifdef GC_AMIGA_PRINTSTATS
 | |
| 			numcollects++;
 | |
| #endif
 | |
| 			ret=(*AllocFunction)(size);
 | |
| 		}
 | |
| #endif
 | |
| 		if(ret==NULL){
 | |
| #ifndef GC_AMIGA_ONLYFAST
 | |
| 			GC_AMIGA_MEMF=MEMF_ANY | MEMF_CLEAR;
 | |
| 			if(GC_amiga_toany!=NULL) (*GC_amiga_toany)();
 | |
| 			GC_amiga_allocwrapper_do=GC_amiga_allocwrapper_any;
 | |
| 			return GC_amiga_allocwrapper_any(size,AllocFunction);
 | |
| #endif
 | |
| 		}
 | |
| #ifdef GC_AMIGA_PRINTSTATS
 | |
| 		else{
 | |
| 			nullretries++;
 | |
| 		}
 | |
| #endif
 | |
| 	}
 | |
| 
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| void *GC_amiga_allocwrapper_firsttime(size_t size,void *(*AllocFunction)(size_t size2)){
 | |
| 	atexit(&GC_amiga_free_all_mem);
 | |
| 	chipmax=(char *)SysBase->MaxLocMem;		// For people still having SysBase in chip-mem, this might speed up a bit.
 | |
| 	GC_amiga_allocwrapper_do=GC_amiga_allocwrapper_fast;
 | |
| 	return GC_amiga_allocwrapper_fast(size,AllocFunction);
 | |
| }
 | |
| 
 | |
| 
 | |
| #endif //GC_AMIGA_FASTALLOC
 | |
| 
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * The wrapped realloc function.
 | |
|  *
 | |
|  */
 | |
| void *GC_amiga_realloc(void *old_object,size_t new_size_in_bytes){
 | |
| #ifndef GC_AMIGA_FASTALLOC
 | |
| 	return GC_realloc(old_object,new_size_in_bytes);
 | |
| #else
 | |
| 	void *ret;
 | |
| 	latestsize=new_size_in_bytes;
 | |
| 	ret=GC_realloc(old_object,new_size_in_bytes);
 | |
| 	if(ret==NULL && GC_AMIGA_MEMF==(MEMF_FAST | MEMF_CLEAR)){
 | |
| 		/* Out of fast-mem. */
 | |
| #ifdef GC_AMIGA_GC
 | |
| 		if(!GC_dont_gc){
 | |
| 			GC_gcollect();
 | |
| #ifdef GC_AMIGA_PRINTSTATS
 | |
| 			numcollects++;
 | |
| #endif
 | |
| 			ret=GC_realloc(old_object,new_size_in_bytes);
 | |
| 		}
 | |
| #endif
 | |
| 		if(ret==NULL){
 | |
| #ifndef GC_AMIGA_ONLYFAST
 | |
| 			GC_AMIGA_MEMF=MEMF_ANY | MEMF_CLEAR;
 | |
| 			if(GC_amiga_toany!=NULL) (*GC_amiga_toany)();
 | |
| 			GC_amiga_allocwrapper_do=GC_amiga_allocwrapper_any;
 | |
| 			ret=GC_realloc(old_object,new_size_in_bytes);
 | |
| #endif
 | |
| 		}
 | |
| #ifdef GC_AMIGA_PRINTSTATS
 | |
| 		else{
 | |
| 			nullretries++;
 | |
| 		}
 | |
| #endif
 | |
| 	}
 | |
| 	if(ret==NULL){
 | |
| 		WARN("Out of Memory!  Returning NIL!\n", 0);
 | |
| 	}
 | |
| #ifdef GC_AMIGA_PRINTSTATS
 | |
| 	if(((char *)ret)<chipmax && ret!=NULL){
 | |
| 		chipa+=new_size_in_bytes;
 | |
| 	}
 | |
| #endif
 | |
| 	return ret;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| #endif //GC_AMIGA_AM
 | |
| 
 | |
| 
 |