| 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 |
|
|---|