Annotation of OpenXM_contrib2/asir2000/gc/AmigaOS.c, Revision 1.1
1.1 ! noro 1:
! 2:
! 3: /******************************************************************
! 4:
! 5: AmigaOS-spesific routines for GC.
! 6: This file is normally included from os_dep.c
! 7:
! 8: ******************************************************************/
! 9:
! 10:
! 11: #if !defined(GC_AMIGA_DEF) && !defined(GC_AMIGA_SB) && !defined(GC_AMIGA_DS) && !defined(GC_AMIGA_AM)
! 12: # include "gc_priv.h"
! 13: # include <stdio.h>
! 14: # include <signal.h>
! 15: # define GC_AMIGA_DEF
! 16: # define GC_AMIGA_SB
! 17: # define GC_AMIGA_DS
! 18: # define GC_AMIGA_AM
! 19: #endif
! 20:
! 21:
! 22: #ifdef GC_AMIGA_DEF
! 23:
! 24: # ifndef __GNUC__
! 25: # include <exec/exec.h>
! 26: # endif
! 27: # include <proto/exec.h>
! 28: # include <proto/dos.h>
! 29: # include <dos/dosextens.h>
! 30: # include <workbench/startup.h>
! 31:
! 32: #endif
! 33:
! 34:
! 35:
! 36:
! 37: #ifdef GC_AMIGA_SB
! 38:
! 39: /******************************************************************
! 40: Find the base of the stack.
! 41: ******************************************************************/
! 42:
! 43: ptr_t GC_get_stack_base()
! 44: {
! 45: struct Process *proc = (struct Process*)SysBase->ThisTask;
! 46:
! 47: /* Reference: Amiga Guru Book Pages: 42,567,574 */
! 48: if (proc->pr_Task.tc_Node.ln_Type==NT_PROCESS
! 49: && proc->pr_CLI != NULL) {
! 50: /* first ULONG is StackSize */
! 51: /*longPtr = proc->pr_ReturnAddr;
! 52: size = longPtr[0];*/
! 53:
! 54: return (char *)proc->pr_ReturnAddr + sizeof(ULONG);
! 55: } else {
! 56: return (char *)proc->pr_Task.tc_SPUpper;
! 57: }
! 58: }
! 59:
! 60: #if 0 /* old version */
! 61: ptr_t GC_get_stack_base()
! 62: {
! 63: extern struct WBStartup *_WBenchMsg;
! 64: extern long __base;
! 65: extern long __stack;
! 66: struct Task *task;
! 67: struct Process *proc;
! 68: struct CommandLineInterface *cli;
! 69: long size;
! 70:
! 71: if ((task = FindTask(0)) == 0) {
! 72: GC_err_puts("Cannot find own task structure\n");
! 73: ABORT("task missing");
! 74: }
! 75: proc = (struct Process *)task;
! 76: cli = BADDR(proc->pr_CLI);
! 77:
! 78: if (_WBenchMsg != 0 || cli == 0) {
! 79: size = (char *)task->tc_SPUpper - (char *)task->tc_SPLower;
! 80: } else {
! 81: size = cli->cli_DefaultStack * 4;
! 82: }
! 83: return (ptr_t)(__base + GC_max(size, __stack));
! 84: }
! 85: #endif
! 86:
! 87:
! 88: #endif
! 89:
! 90:
! 91: #ifdef GC_AMIGA_DS
! 92: /******************************************************************
! 93: Register data segments.
! 94: ******************************************************************/
! 95:
! 96: void GC_register_data_segments()
! 97: {
! 98: struct Process *proc;
! 99: struct CommandLineInterface *cli;
! 100: BPTR myseglist;
! 101: ULONG *data;
! 102:
! 103: int num;
! 104:
! 105:
! 106: # ifdef __GNUC__
! 107: ULONG dataSegSize;
! 108: GC_bool found_segment = FALSE;
! 109: extern char __data_size[];
! 110:
! 111: dataSegSize=__data_size+8;
! 112: /* Can`t find the Location of __data_size, because
! 113: it`s possible that is it, inside the segment. */
! 114:
! 115: # endif
! 116:
! 117: proc= (struct Process*)SysBase->ThisTask;
! 118:
! 119: /* Reference: Amiga Guru Book Pages: 538ff,565,573
! 120: and XOper.asm */
! 121: if (proc->pr_Task.tc_Node.ln_Type==NT_PROCESS) {
! 122: if (proc->pr_CLI == NULL) {
! 123: myseglist = proc->pr_SegList;
! 124: } else {
! 125: /* ProcLoaded 'Loaded as a command: '*/
! 126: cli = BADDR(proc->pr_CLI);
! 127: myseglist = cli->cli_Module;
! 128: }
! 129: } else {
! 130: ABORT("Not a Process.");
! 131: }
! 132:
! 133: if (myseglist == NULL) {
! 134: ABORT("Arrrgh.. can't find segments, aborting");
! 135: }
! 136:
! 137: /* xoper hunks Shell Process */
! 138:
! 139: num=0;
! 140: for (data = (ULONG *)BADDR(myseglist); data != NULL;
! 141: data = (ULONG *)BADDR(data[0])) {
! 142: if (((ULONG) GC_register_data_segments < (ULONG) &data[1]) ||
! 143: ((ULONG) GC_register_data_segments > (ULONG) &data[1] + data[-1])) {
! 144: # ifdef __GNUC__
! 145: if (dataSegSize == data[-1]) {
! 146: found_segment = TRUE;
! 147: }
! 148: # endif
! 149: GC_add_roots_inner((char *)&data[1],
! 150: ((char *)&data[1]) + data[-1], FALSE);
! 151: }
! 152: ++num;
! 153: } /* for */
! 154: # ifdef __GNUC__
! 155: if (!found_segment) {
! 156: ABORT("Can`t find correct Segments.\nSolution: Use an newer version of ixemul.library");
! 157: }
! 158: # endif
! 159: }
! 160:
! 161: #if 0 /* old version */
! 162: void GC_register_data_segments()
! 163: {
! 164: extern struct WBStartup *_WBenchMsg;
! 165: struct Process *proc;
! 166: struct CommandLineInterface *cli;
! 167: BPTR myseglist;
! 168: ULONG *data;
! 169:
! 170: if ( _WBenchMsg != 0 ) {
! 171: if ((myseglist = _WBenchMsg->sm_Segment) == 0) {
! 172: GC_err_puts("No seglist from workbench\n");
! 173: return;
! 174: }
! 175: } else {
! 176: if ((proc = (struct Process *)FindTask(0)) == 0) {
! 177: GC_err_puts("Cannot find process structure\n");
! 178: return;
! 179: }
! 180: if ((cli = BADDR(proc->pr_CLI)) == 0) {
! 181: GC_err_puts("No CLI\n");
! 182: return;
! 183: }
! 184: if ((myseglist = cli->cli_Module) == 0) {
! 185: GC_err_puts("No seglist from CLI\n");
! 186: return;
! 187: }
! 188: }
! 189:
! 190: for (data = (ULONG *)BADDR(myseglist); data != 0;
! 191: data = (ULONG *)BADDR(data[0])) {
! 192: # ifdef AMIGA_SKIP_SEG
! 193: if (((ULONG) GC_register_data_segments < (ULONG) &data[1]) ||
! 194: ((ULONG) GC_register_data_segments > (ULONG) &data[1] + data[-1])) {
! 195: # else
! 196: {
! 197: # endif /* AMIGA_SKIP_SEG */
! 198: GC_add_roots_inner((char *)&data[1],
! 199: ((char *)&data[1]) + data[-1], FALSE);
! 200: }
! 201: }
! 202: }
! 203: #endif /* old version */
! 204:
! 205:
! 206: #endif
! 207:
! 208:
! 209:
! 210: #ifdef GC_AMIGA_AM
! 211:
! 212: #ifndef GC_AMIGA_FASTALLOC
! 213:
! 214: void *GC_amiga_allocwrapper(size_t size,void *(*AllocFunction)(size_t size2)){
! 215: return (*AllocFunction)(size);
! 216: }
! 217:
! 218: void *(*GC_amiga_allocwrapper_do)(size_t size,void *(*AllocFunction)(size_t size2))
! 219: =GC_amiga_allocwrapper;
! 220:
! 221: #else
! 222:
! 223:
! 224:
! 225:
! 226: void *GC_amiga_allocwrapper_firsttime(size_t size,void *(*AllocFunction)(size_t size2));
! 227:
! 228: void *(*GC_amiga_allocwrapper_do)(size_t size,void *(*AllocFunction)(size_t size2))
! 229: =GC_amiga_allocwrapper_firsttime;
! 230:
! 231:
! 232: /******************************************************************
! 233: Amiga-spesific routines to obtain memory, and force GC to give
! 234: back fast-mem whenever possible.
! 235: These hacks makes gc-programs go many times faster when
! 236: the amiga is low on memory, and are therefore strictly necesarry.
! 237:
! 238: -Kjetil S. Matheussen, 2000.
! 239: ******************************************************************/
! 240:
! 241:
! 242:
! 243: /* List-header for all allocated memory. */
! 244:
! 245: struct GC_Amiga_AllocedMemoryHeader{
! 246: ULONG size;
! 247: struct GC_Amiga_AllocedMemoryHeader *next;
! 248: };
! 249: struct GC_Amiga_AllocedMemoryHeader *GC_AMIGAMEM=(struct GC_Amiga_AllocedMemoryHeader *)(int)~(NULL);
! 250:
! 251:
! 252:
! 253: /* Type of memory. Once in the execution of a program, this might change to MEMF_ANY|MEMF_CLEAR */
! 254:
! 255: ULONG GC_AMIGA_MEMF = MEMF_FAST | MEMF_CLEAR;
! 256:
! 257:
! 258: /* Prevents GC_amiga_get_mem from allocating memory if this one is TRUE. */
! 259: #ifndef GC_AMIGA_ONLYFAST
! 260: BOOL GC_amiga_dontalloc=FALSE;
! 261: #endif
! 262:
! 263: #ifdef GC_AMIGA_PRINTSTATS
! 264: int succ=0,succ2=0;
! 265: int nsucc=0,nsucc2=0;
! 266: int nullretries=0;
! 267: int numcollects=0;
! 268: int chipa=0;
! 269: int allochip=0;
! 270: int allocfast=0;
! 271: int cur0=0;
! 272: int cur1=0;
! 273: int cur10=0;
! 274: int cur50=0;
! 275: int cur150=0;
! 276: int cur151=0;
! 277: int ncur0=0;
! 278: int ncur1=0;
! 279: int ncur10=0;
! 280: int ncur50=0;
! 281: int ncur150=0;
! 282: int ncur151=0;
! 283: #endif
! 284:
! 285: /* Free everything at program-end. */
! 286:
! 287: void GC_amiga_free_all_mem(void){
! 288: struct GC_Amiga_AllocedMemoryHeader *gc_am=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(GC_AMIGAMEM));
! 289: struct GC_Amiga_AllocedMemoryHeader *temp;
! 290:
! 291: #ifdef GC_AMIGA_PRINTSTATS
! 292: printf("\n\n"
! 293: "%d bytes of chip-mem, and %d bytes of fast-mem where allocated from the OS.\n",
! 294: allochip,allocfast
! 295: );
! 296: printf(
! 297: "%d bytes of chip-mem were returned from the GC_AMIGA_FASTALLOC supported allocating functions.\n",
! 298: chipa
! 299: );
! 300: printf("\n");
! 301: printf("GC_gcollect was called %d times to avoid returning NULL or start allocating with the MEMF_ANY flag.\n",numcollects);
! 302: printf("%d of them was a success. (the others had to use allocation from the OS.)\n",nullretries);
! 303: printf("\n");
! 304: printf("Succeded forcing %d gc-allocations (%d bytes) of chip-mem to be fast-mem.\n",succ,succ2);
! 305: printf("Failed forcing %d gc-allocations (%d bytes) of chip-mem to be fast-mem.\n",nsucc,nsucc2);
! 306: printf("\n");
! 307: printf(
! 308: "Number of retries before succeding a chip->fast force:\n"
! 309: "0: %d, 1: %d, 2-9: %d, 10-49: %d, 50-149: %d, >150: %d\n",
! 310: cur0,cur1,cur10,cur50,cur150,cur151
! 311: );
! 312: printf(
! 313: "Number of retries before giving up a chip->fast force:\n"
! 314: "0: %d, 1: %d, 2-9: %d, 10-49: %d, 50-149: %d, >150: %d\n",
! 315: ncur0,ncur1,ncur10,ncur50,ncur150,ncur151
! 316: );
! 317: #endif
! 318:
! 319: while(gc_am!=NULL){
! 320: temp=gc_am->next;
! 321: FreeMem(gc_am,gc_am->size);
! 322: gc_am=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(temp));
! 323: }
! 324: }
! 325:
! 326: #ifndef GC_AMIGA_ONLYFAST
! 327:
! 328: /* All memory with address lower than this one is chip-mem. */
! 329:
! 330: char *chipmax;
! 331:
! 332:
! 333: /*
! 334: * Allways set to the last size of memory tried to be allocated.
! 335: * Needed to ensure allocation when the size is bigger than 100000.
! 336: *
! 337: */
! 338: size_t latestsize;
! 339:
! 340: #endif
! 341:
! 342:
! 343: /*
! 344: * The actual function that is called with the GET_MEM macro.
! 345: *
! 346: */
! 347:
! 348: void *GC_amiga_get_mem(size_t size){
! 349: struct GC_Amiga_AllocedMemoryHeader *gc_am;
! 350:
! 351: #ifndef GC_AMIGA_ONLYFAST
! 352: if(GC_amiga_dontalloc==TRUE){
! 353: // printf("rejected, size: %d, latestsize: %d\n",size,latestsize);
! 354: return NULL;
! 355: }
! 356:
! 357: // We really don't want to use chip-mem, but if we must, then as little as possible.
! 358: if(GC_AMIGA_MEMF==(MEMF_ANY|MEMF_CLEAR) && size>100000 && latestsize<50000) return NULL;
! 359: #endif
! 360:
! 361: gc_am=AllocMem((ULONG)(size + sizeof(struct GC_Amiga_AllocedMemoryHeader)),GC_AMIGA_MEMF);
! 362: if(gc_am==NULL) return NULL;
! 363:
! 364: gc_am->next=GC_AMIGAMEM;
! 365: gc_am->size=size + sizeof(struct GC_Amiga_AllocedMemoryHeader);
! 366: GC_AMIGAMEM=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(gc_am));
! 367:
! 368: // printf("Allocated %d (%d) bytes at address: %x. Latest: %d\n",size,tot,gc_am,latestsize);
! 369:
! 370: #ifdef GC_AMIGA_PRINTSTATS
! 371: if((char *)gc_am<chipmax){
! 372: allochip+=size;
! 373: }else{
! 374: allocfast+=size;
! 375: }
! 376: #endif
! 377:
! 378: return gc_am+1;
! 379:
! 380: }
! 381:
! 382:
! 383:
! 384:
! 385: #ifndef GC_AMIGA_ONLYFAST
! 386:
! 387: /* Tries very hard to force GC to find fast-mem to return. Done recursively
! 388: * to hold the rejected memory-pointers reachable from the collector in an
! 389: * easy way.
! 390: *
! 391: */
! 392: #ifdef GC_AMIGA_RETRY
! 393: void *GC_amiga_rec_alloc(size_t size,void *(*AllocFunction)(size_t size2),const int rec){
! 394: void *ret;
! 395:
! 396: ret=(*AllocFunction)(size);
! 397:
! 398: #ifdef GC_AMIGA_PRINTSTATS
! 399: if((char *)ret>chipmax || ret==NULL){
! 400: if(ret==NULL){
! 401: nsucc++;
! 402: nsucc2+=size;
! 403: if(rec==0) ncur0++;
! 404: if(rec==1) ncur1++;
! 405: if(rec>1 && rec<10) ncur10++;
! 406: if(rec>=10 && rec<50) ncur50++;
! 407: if(rec>=50 && rec<150) ncur150++;
! 408: if(rec>=150) ncur151++;
! 409: }else{
! 410: succ++;
! 411: succ2+=size;
! 412: if(rec==0) cur0++;
! 413: if(rec==1) cur1++;
! 414: if(rec>1 && rec<10) cur10++;
! 415: if(rec>=10 && rec<50) cur50++;
! 416: if(rec>=50 && rec<150) cur150++;
! 417: if(rec>=150) cur151++;
! 418: }
! 419: }
! 420: #endif
! 421:
! 422: if (((char *)ret)<=chipmax && ret!=NULL && (rec<(size>500000?9:size/5000))){
! 423: ret=GC_amiga_rec_alloc(size,AllocFunction,rec+1);
! 424: // GC_free(ret2);
! 425: }
! 426:
! 427: return ret;
! 428: }
! 429: #endif
! 430:
! 431:
! 432: /* The allocating-functions defined inside the amiga-blocks in gc.h is called
! 433: * via these functions.
! 434: */
! 435:
! 436:
! 437: void *GC_amiga_allocwrapper_any(size_t size,void *(*AllocFunction)(size_t size2)){
! 438: void *ret,*ret2;
! 439:
! 440: GC_amiga_dontalloc=TRUE; // Pretty tough thing to do, but its indeed necesarry.
! 441: latestsize=size;
! 442:
! 443: ret=(*AllocFunction)(size);
! 444:
! 445: if(((char *)ret) <= chipmax){
! 446: if(ret==NULL){
! 447: //Give GC access to allocate memory.
! 448: #ifdef GC_AMIGA_GC
! 449: if(!GC_dont_gc){
! 450: GC_gcollect();
! 451: #ifdef GC_AMIGA_PRINTSTATS
! 452: numcollects++;
! 453: #endif
! 454: ret=(*AllocFunction)(size);
! 455: }
! 456: #endif
! 457: if(ret==NULL){
! 458: GC_amiga_dontalloc=FALSE;
! 459: ret=(*AllocFunction)(size);
! 460: if(ret==NULL){
! 461: WARN("Out of Memory! Returning NIL!\n", 0);
! 462: }
! 463: }
! 464: #ifdef GC_AMIGA_PRINTSTATS
! 465: else{
! 466: nullretries++;
! 467: }
! 468: if(ret!=NULL && (char *)ret<=chipmax) chipa+=size;
! 469: #endif
! 470: }
! 471: #ifdef GC_AMIGA_RETRY
! 472: else{
! 473: /* We got chip-mem. Better try again and again and again etc., we might get fast-mem sooner or later... */
! 474: /* Using gctest to check the effectiviness of doing this, does seldom give a very good result. */
! 475: /* However, real programs doesn't normally rapidly allocate and deallocate. */
! 476: // printf("trying to force... %d bytes... ",size);
! 477: if(
! 478: AllocFunction!=GC_malloc_uncollectable
! 479: #ifdef ATOMIC_UNCOLLECTABLE
! 480: && AllocFunction!=GC_malloc_atomic_uncollectable
! 481: #endif
! 482: ){
! 483: ret2=GC_amiga_rec_alloc(size,AllocFunction,0);
! 484: }else{
! 485: ret2=(*AllocFunction)(size);
! 486: #ifdef GC_AMIGA_PRINTSTATS
! 487: if((char *)ret2<chipmax || ret2==NULL){
! 488: nsucc++;
! 489: nsucc2+=size;
! 490: ncur0++;
! 491: }else{
! 492: succ++;
! 493: succ2+=size;
! 494: cur0++;
! 495: }
! 496: #endif
! 497: }
! 498: if(((char *)ret2)>chipmax){
! 499: // printf("Succeeded.\n");
! 500: GC_free(ret);
! 501: ret=ret2;
! 502: }else{
! 503: GC_free(ret2);
! 504: // printf("But did not succeed.\n");
! 505: }
! 506: }
! 507: #endif
! 508: }
! 509:
! 510: GC_amiga_dontalloc=FALSE;
! 511:
! 512: return ret;
! 513: }
! 514:
! 515:
! 516:
! 517: void (*GC_amiga_toany)(void)=NULL;
! 518:
! 519: void GC_amiga_set_toany(void (*func)(void)){
! 520: GC_amiga_toany=func;
! 521: }
! 522:
! 523: #endif // !GC_AMIGA_ONLYFAST
! 524:
! 525:
! 526: void *GC_amiga_allocwrapper_fast(size_t size,void *(*AllocFunction)(size_t size2)){
! 527: void *ret;
! 528:
! 529: ret=(*AllocFunction)(size);
! 530:
! 531: if(ret==NULL){
! 532: // Enable chip-mem allocation.
! 533: // printf("ret==NULL\n");
! 534: #ifdef GC_AMIGA_GC
! 535: if(!GC_dont_gc){
! 536: GC_gcollect();
! 537: #ifdef GC_AMIGA_PRINTSTATS
! 538: numcollects++;
! 539: #endif
! 540: ret=(*AllocFunction)(size);
! 541: }
! 542: #endif
! 543: if(ret==NULL){
! 544: #ifndef GC_AMIGA_ONLYFAST
! 545: GC_AMIGA_MEMF=MEMF_ANY | MEMF_CLEAR;
! 546: if(GC_amiga_toany!=NULL) (*GC_amiga_toany)();
! 547: GC_amiga_allocwrapper_do=GC_amiga_allocwrapper_any;
! 548: return GC_amiga_allocwrapper_any(size,AllocFunction);
! 549: #endif
! 550: }
! 551: #ifdef GC_AMIGA_PRINTSTATS
! 552: else{
! 553: nullretries++;
! 554: }
! 555: #endif
! 556: }
! 557:
! 558: return ret;
! 559: }
! 560:
! 561: void *GC_amiga_allocwrapper_firsttime(size_t size,void *(*AllocFunction)(size_t size2)){
! 562: atexit(&GC_amiga_free_all_mem);
! 563: chipmax=(char *)SysBase->MaxLocMem; // For people still having SysBase in chip-mem, this might speed up a bit.
! 564: GC_amiga_allocwrapper_do=GC_amiga_allocwrapper_fast;
! 565: return GC_amiga_allocwrapper_fast(size,AllocFunction);
! 566: }
! 567:
! 568:
! 569: #endif //GC_AMIGA_FASTALLOC
! 570:
! 571:
! 572:
! 573: /*
! 574: * The wrapped realloc function.
! 575: *
! 576: */
! 577: void *GC_amiga_realloc(void *old_object,size_t new_size_in_bytes){
! 578: #ifndef GC_AMIGA_FASTALLOC
! 579: return GC_realloc(old_object,new_size_in_bytes);
! 580: #else
! 581: void *ret;
! 582: latestsize=new_size_in_bytes;
! 583: ret=GC_realloc(old_object,new_size_in_bytes);
! 584: if(ret==NULL && GC_AMIGA_MEMF==(MEMF_FAST | MEMF_CLEAR)){
! 585: /* Out of fast-mem. */
! 586: #ifdef GC_AMIGA_GC
! 587: if(!GC_dont_gc){
! 588: GC_gcollect();
! 589: #ifdef GC_AMIGA_PRINTSTATS
! 590: numcollects++;
! 591: #endif
! 592: ret=GC_realloc(old_object,new_size_in_bytes);
! 593: }
! 594: #endif
! 595: if(ret==NULL){
! 596: #ifndef GC_AMIGA_ONLYFAST
! 597: GC_AMIGA_MEMF=MEMF_ANY | MEMF_CLEAR;
! 598: if(GC_amiga_toany!=NULL) (*GC_amiga_toany)();
! 599: GC_amiga_allocwrapper_do=GC_amiga_allocwrapper_any;
! 600: ret=GC_realloc(old_object,new_size_in_bytes);
! 601: #endif
! 602: }
! 603: #ifdef GC_AMIGA_PRINTSTATS
! 604: else{
! 605: nullretries++;
! 606: }
! 607: #endif
! 608: }
! 609: if(ret==NULL){
! 610: WARN("Out of Memory! Returning NIL!\n", 0);
! 611: }
! 612: #ifdef GC_AMIGA_PRINTSTATS
! 613: if(((char *)ret)<chipmax && ret!=NULL){
! 614: chipa+=new_size_in_bytes;
! 615: }
! 616: #endif
! 617: return ret;
! 618: #endif
! 619: }
! 620:
! 621: #endif //GC_AMIGA_AM
! 622:
! 623:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>