OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [boehm-gc/] [AmigaOS.c] - Blame information for rev 721

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 721 jeremybenn
 
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
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.