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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [boehm-gc/] [stubborn.c] - Blame information for rev 12

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
/*
2
 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
3
 * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
4
 *
5
 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
6
 * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
7
 *
8
 * Permission is hereby granted to use or copy this program
9
 * for any purpose,  provided the above notices are retained on all copies.
10
 * Permission to modify the code and to distribute modified code is granted,
11
 * provided the above notices are retained, and a notice that the code was
12
 * modified is included with the above copyright notice.
13
 */
14
/* Boehm, July 31, 1995 5:02 pm PDT */
15
 
16
 
17
#include "private/gc_priv.h"
18
 
19
# ifdef STUBBORN_ALLOC
20
/* Stubborn object (hard to change, nearly immutable) allocation. */
21
 
22
extern ptr_t GC_clear_stack();  /* in misc.c, behaves like identity */
23
 
24
#define GENERAL_MALLOC(lb,k) \
25
    (GC_PTR)GC_clear_stack(GC_generic_malloc((word)lb, k))
26
 
27
/* Data structure representing immutable objects that   */
28
/* are still being initialized.                         */
29
/* This is a bit baroque in order to avoid acquiring    */
30
/* the lock twice for a typical allocation.             */
31
 
32
GC_PTR * GC_changing_list_start;
33
 
34
void GC_push_stubborn_structures GC_PROTO((void))
35
{
36
    GC_push_all((ptr_t)(&GC_changing_list_start),
37
                (ptr_t)(&GC_changing_list_start) + sizeof(GC_PTR *));
38
}
39
 
40
# ifdef THREADS
41
  VOLATILE GC_PTR * VOLATILE GC_changing_list_current;
42
# else
43
  GC_PTR * GC_changing_list_current;
44
# endif
45
        /* Points at last added element.  Also (ab)used for             */
46
        /* synchronization.  Updates and reads are assumed atomic.      */
47
 
48
GC_PTR * GC_changing_list_limit;
49
        /* Points at the last word of the buffer, which is always 0     */
50
        /* All entries in (GC_changing_list_current,                    */
51
        /* GC_changing_list_limit] are 0                                */
52
 
53
 
54
void GC_stubborn_init()
55
{
56
#   define INIT_SIZE 10
57
 
58
    GC_changing_list_start = (GC_PTR *)
59
                        GC_INTERNAL_MALLOC(
60
                                (word)(INIT_SIZE * sizeof(GC_PTR)),
61
                                PTRFREE);
62
    BZERO(GC_changing_list_start,
63
          INIT_SIZE * sizeof(GC_PTR));
64
    if (GC_changing_list_start == 0) {
65
        GC_err_printf0("Insufficient space to start up\n");
66
        ABORT("GC_stubborn_init: put of space");
67
    }
68
    GC_changing_list_current = GC_changing_list_start;
69
    GC_changing_list_limit = GC_changing_list_start + INIT_SIZE - 1;
70
    * GC_changing_list_limit = 0;
71
}
72
 
73
/* Compact and possibly grow GC_uninit_list.  The old copy is           */
74
/* left alone.  Lock must be held.                                      */
75
/* When called GC_changing_list_current == GC_changing_list_limit       */
76
/* which is one past the current element.                               */
77
/* When we finish GC_changing_list_current again points one past last   */
78
/* element.                                                             */
79
/* Invariant while this is running: GC_changing_list_current            */
80
/* points at a word containing 0.                                       */
81
/* Returns FALSE on failure.                                            */
82
GC_bool GC_compact_changing_list()
83
{
84
    register GC_PTR *p, *q;
85
    register word count = 0;
86
    word old_size = (char **)GC_changing_list_limit
87
                    - (char **)GC_changing_list_start+1;
88
                    /* The casts are needed as a workaround for an Amiga bug */
89
    register word new_size = old_size;
90
    GC_PTR * new_list;
91
 
92
    for (p = GC_changing_list_start; p < GC_changing_list_limit; p++) {
93
        if (*p != 0) count++;
94
    }
95
    if (2 * count > old_size) new_size = 2 * count;
96
    new_list = (GC_PTR *)
97
                GC_INTERNAL_MALLOC(
98
                                new_size * sizeof(GC_PTR), PTRFREE);
99
                /* PTRFREE is a lie.  But we don't want the collector to  */
100
                /* consider these.  We do want the list itself to be      */
101
                /* collectable.                                           */
102
    if (new_list == 0) return(FALSE);
103
    BZERO(new_list, new_size * sizeof(GC_PTR));
104
    q = new_list;
105
    for (p = GC_changing_list_start; p < GC_changing_list_limit; p++) {
106
        if (*p != 0) *q++ = *p;
107
    }
108
    GC_changing_list_start = new_list;
109
    GC_changing_list_limit = new_list + new_size - 1;
110
    GC_changing_list_current = q;
111
    return(TRUE);
112
}
113
 
114
/* Add p to changing list.  Clear p on failure. */
115
# define ADD_CHANGING(p) \
116
        {       \
117
            register struct hblk * h = HBLKPTR(p);      \
118
            register word index = PHT_HASH(h);  \
119
            \
120
            set_pht_entry_from_index(GC_changed_pages, index);  \
121
        }       \
122
        if (*GC_changing_list_current != 0 \
123
            && ++GC_changing_list_current == GC_changing_list_limit) { \
124
            if (!GC_compact_changing_list()) (p) = 0; \
125
        } \
126
        *GC_changing_list_current = p;
127
 
128
void GC_change_stubborn(p)
129
GC_PTR p;
130
{
131
    DCL_LOCK_STATE;
132
 
133
    DISABLE_SIGNALS();
134
    LOCK();
135
    ADD_CHANGING(p);
136
    UNLOCK();
137
    ENABLE_SIGNALS();
138
}
139
 
140
void GC_end_stubborn_change(p)
141
GC_PTR p;
142
{
143
#   ifdef THREADS
144
      register VOLATILE GC_PTR * my_current = GC_changing_list_current;
145
#   else
146
      register GC_PTR * my_current = GC_changing_list_current;
147
#   endif
148
    register GC_bool tried_quick;
149
    DCL_LOCK_STATE;
150
 
151
    if (*my_current == p) {
152
        /* Hopefully the normal case.                                   */
153
        /* Compaction could not have been running when we started.      */
154
        *my_current = 0;
155
#       ifdef THREADS
156
          if (my_current == GC_changing_list_current) {
157
            /* Compaction can't have run in the interim.        */
158
            /* We got away with the quick and dirty approach.   */
159
            return;
160
          }
161
          tried_quick = TRUE;
162
#       else
163
          return;
164
#       endif
165
    } else {
166
        tried_quick = FALSE;
167
    }
168
    DISABLE_SIGNALS();
169
    LOCK();
170
    my_current = GC_changing_list_current;
171
    for (; my_current >= GC_changing_list_start; my_current--) {
172
        if (*my_current == p) {
173
            *my_current = 0;
174
            UNLOCK();
175
            ENABLE_SIGNALS();
176
            return;
177
        }
178
    }
179
    if (!tried_quick) {
180
        GC_err_printf1("Bad arg to GC_end_stubborn_change: 0x%lx\n",
181
                       (unsigned long)p);
182
        ABORT("Bad arg to GC_end_stubborn_change");
183
    }
184
    UNLOCK();
185
    ENABLE_SIGNALS();
186
}
187
 
188
/* Allocate lb bytes of composite (pointerful) data     */
189
/* No pointer fields may be changed after a call to     */
190
/* GC_end_stubborn_change(p) where p is the value       */
191
/* returned by GC_malloc_stubborn.                      */
192
# ifdef __STDC__
193
    GC_PTR GC_malloc_stubborn(size_t lb)
194
# else
195
    GC_PTR GC_malloc_stubborn(lb)
196
    size_t lb;
197
# endif
198
{
199
register ptr_t op;
200
register ptr_t *opp;
201
register word lw;
202
ptr_t result;
203
DCL_LOCK_STATE;
204
 
205
    if( SMALL_OBJ(lb) ) {
206
#       ifdef MERGE_SIZES
207
          lw = GC_size_map[lb];
208
#       else
209
          lw = ALIGNED_WORDS(lb);
210
#       endif
211
        opp = &(GC_sobjfreelist[lw]);
212
        FASTLOCK();
213
        if( !FASTLOCK_SUCCEEDED() || (op = *opp) == 0 ) {
214
            FASTUNLOCK();
215
            result = GC_generic_malloc((word)lb, STUBBORN);
216
            goto record;
217
        }
218
        *opp = obj_link(op);
219
        obj_link(op) = 0;
220
        GC_words_allocd += lw;
221
        result = (GC_PTR) op;
222
        ADD_CHANGING(result);
223
        FASTUNLOCK();
224
        return((GC_PTR)result);
225
   } else {
226
       result = (GC_PTR)
227
                GC_generic_malloc((word)lb, STUBBORN);
228
   }
229
record:
230
   DISABLE_SIGNALS();
231
   LOCK();
232
   ADD_CHANGING(result);
233
   UNLOCK();
234
   ENABLE_SIGNALS();
235
   return((GC_PTR)GC_clear_stack(result));
236
}
237
 
238
 
239
/* Functions analogous to GC_read_dirty and GC_page_was_dirty.  */
240
/* Report pages on which stubborn objects were changed.         */
241
void GC_read_changed()
242
{
243
    register GC_PTR * p = GC_changing_list_start;
244
    register GC_PTR q;
245
    register struct hblk * h;
246
    register word index;
247
 
248
    if (p == 0) /* initializing */ return;
249
    BCOPY(GC_changed_pages, GC_prev_changed_pages,
250
          (sizeof GC_changed_pages));
251
    BZERO(GC_changed_pages, (sizeof GC_changed_pages));
252
    for (; p <= GC_changing_list_current; p++) {
253
        if ((q = *p) != 0) {
254
            h = HBLKPTR(q);
255
            index = PHT_HASH(h);
256
            set_pht_entry_from_index(GC_changed_pages, index);
257
        }
258
    }
259
}
260
 
261
GC_bool GC_page_was_changed(h)
262
struct hblk * h;
263
{
264
    register word index = PHT_HASH(h);
265
 
266
    return(get_pht_entry_from_index(GC_prev_changed_pages, index));
267
}
268
 
269
/* Remove unreachable entries from changed list. Should only be */
270
/* called with mark bits consistent and lock held.              */
271
void GC_clean_changing_list()
272
{
273
    register GC_PTR * p = GC_changing_list_start;
274
    register GC_PTR q;
275
    register ptr_t r;
276
    register unsigned long count = 0;
277
    register unsigned long dropped_count = 0;
278
 
279
    if (p == 0) /* initializing */ return;
280
    for (; p <= GC_changing_list_current; p++) {
281
        if ((q = *p) != 0) {
282
            count++;
283
            r = (ptr_t)GC_base(q);
284
            if (r == 0 || !GC_is_marked(r)) {
285
                *p = 0;
286
                dropped_count++;
287
            }
288
        }
289
    }
290
#   ifdef PRINTSTATS
291
      if (count > 0) {
292
        GC_printf2("%lu entries in changing list: reclaimed %lu\n",
293
                  (unsigned long)count, (unsigned long)dropped_count);
294
      }
295
#   endif
296
}
297
 
298
#else /* !STUBBORN_ALLOC */
299
 
300
# ifdef __STDC__
301
    GC_PTR GC_malloc_stubborn(size_t lb)
302
# else
303
    GC_PTR GC_malloc_stubborn(lb)
304
    size_t lb;
305
# endif
306
{
307
    return(GC_malloc(lb));
308
}
309
 
310
/*ARGSUSED*/
311
void GC_end_stubborn_change(p)
312
GC_PTR p;
313
{
314
}
315
 
316
/*ARGSUSED*/
317
void GC_change_stubborn(p)
318
GC_PTR p;
319
{
320
}
321
 
322
void GC_push_stubborn_structures GC_PROTO((void))
323
{
324
}
325
 
326
#endif

powered by: WebSVN 2.1.0

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