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