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