Exemplo n.º 1
0
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);
        }

        return ret;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
    /* 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;
}