Go to the documentation of this file.00001
00002
00003
00004
00005
00006 #ifndef __COLLECTOR_H
00007 #define __COLLECTOR_H
00008
00009 #include "rgc_utils.h"
00010 #include "xccmem.h"
00011
00025
00026
00027
00028
00029 #define INITIAL_HEAP_SIZE 2500 // 10M
00030
00031
00032
00033
00034 #define DEFAULT_MAX_RGCSTACK 32768
00035
00036 #define DEFAULT_EXPAND_SIZE_IDX 24
00037
00038 #define DEFAULT_GC_THRESHOLD 0.25
00039
00040 #define REALTIME_ALLOC_LIMIT_IDX 12
00041
00042
00043 #define GC_ACTIVATE_CUSHION 15
00044
00045 #define M_UNIT 8000
00046 #define S_UNIT 256
00047 #define AM_UNIT (M_UNIT)
00048 #define AS_UNIT (S_UNIT)
00049
00050 #define GC_GRANULARITY 2
00051
00052
00053 extern char *minmemory;
00054
00055 #if PTHREAD // the same as those in eus_thr.h
00056 typedef pthread_t thread_t;
00057 typedef pthread_mutex_t mutex_t;
00058 typedef pthread_cond_t cond_t;
00059 #define thr_exit(x) pthread_exit(x)
00060 #define thr_join(x,y,z) pthread_join(x,z)
00061 #define mutex_lock pthread_mutex_lock
00062 #define mutex_trylock pthread_mutex_trylock
00063 #define mutex_unlock pthread_mutex_unlock
00064 #define cond_wait pthread_cond_wait
00065 #define cond_signal pthread_cond_signal
00066 #define cond_broadcast pthread_cond_broadcast
00067 #define mutex_init(x,y) pthread_mutex_init(x,y)
00068 #define mutex_destroy pthread_mutex_destroy
00069 #define cond_init(x,y) pthread_cond_init(x,y)
00070 #define cond_destroy pthread_cond_destroy
00071 #endif
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 #define PHASE_NOGC 0
00083 #define PHASE_PROLOGUE 1
00084 #define PHASE_EPILOGUE 2
00085 #define PHASE_ROOT_CORE 5
00086 #define PHASE_ROOT_REM 6
00087 #define PHASE_MARK 4
00088 #define PHASE_SWEEP 3
00089
00090 extern struct _sweeping_state {
00091 struct chunk *chp;
00092 struct bcell *p;
00093 struct bcell *tail;
00094 } sweeping_state;
00095
00096 #ifdef __RETURN_BARRIER
00097 typedef struct {
00098 pointer *pointer;
00099 mutex_t lock;
00100 } rbar_t;
00101
00102 #define check_return_barrier(ctx) \
00103 { \
00104 if((ctx)->rbar.pointer){\
00105 register pointer *p, *newbase; \
00106 if((ctx)->callfp) newbase = (pointer *)((ctx)->callfp); \
00107 else newbase = (ctx)->stack; \
00108 if(newbase < (ctx)->rbar.pointer){ \
00109 mutex_lock(&(ctx)->rbar.lock); \
00110 if(newbase < (ctx)->rbar.pointer){ \
00111 \
00112 for(p = (ctx)->rbar.pointer - 1; p >= newbase; p--) { \
00113 if (*p == NULL) continue; \
00114 if (((int)(*p) & 3)) continue; \
00115 if ((ctx->stack <= (pointer *)*p) && ((pointer *)*p <= ctx->stacklimit)) \
00116 continue; \
00117 if ((pointer *)*p >= (pointer *)hmax) continue; \
00118 if ((pointer *)*p < (pointer *)hmin) continue; \
00119 pgcpush(*p); \
00120 \
00121 \
00122 } \
00123 if(newbase == (ctx)->stack) \
00124 (ctx)->rbar.pointer = NULL; \
00125 else \
00126 (ctx)->rbar.pointer = newbase; \
00127 } \
00128 mutex_unlock(&(ctx)->rbar.lock); \
00129 }\
00130 }\
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 #endif
00162
00163 typedef struct {
00164 pointer addr;
00165 unsigned int offset;
00166 } ms_entry;
00167
00168 #define TAGMASK 0x1f
00169 #define FREETAG 0x20
00170 #define GRAYTAG 0x20
00171 #define BLACKTAG 0x40
00172 #define COLORTAG 0x60
00173
00174 #ifndef __USE_MARK_BITMAP
00175 #define colored_map(p) colored_hd(p)
00176 #define blacked_map(p) blacked_hd(p)
00177 #define markon_map(p) markon_hd(p)
00178 #define markoff_map(p) markoff_hd(p)
00179 #define marked_map(p) marked_hd(p)
00180 #endif
00181 #define colored_hd(p) (p->h.bix & COLORTAG)
00182 #define blacked_hd(p) (p->h.bix & BLACKTAG)
00183 #define markon_hd(p) (p->h.bix |= BLACKTAG)
00184 #define markoff_hd(p) (p->h.bix &= TAGMASK)
00185 #define marked_hd(p) (p->h.bix & BLACKTAG)
00186
00187 #ifdef __USE_POLLING
00188 struct _mut_stat_table {
00189 unsigned int stat;
00190
00191
00192
00193
00194
00195
00196
00197 mutex_t lock;
00198 };
00199 #endif
00200
00201 struct _gc_data {
00202 ms_entry *collector_stack;
00203 ms_entry *collector_sp;
00204 ms_entry *collector_stacklimit;
00205 int gc_phase;
00206 int active_mutator_num;
00207 int gc_counter;
00208 int gc_point_sync;
00209 volatile int gc_region_sync;
00210 volatile int ri_core_phase;
00211 int mut_stat_phase;
00212 #ifdef __USE_POLLING
00213 volatile int gc_request_flag;
00214 struct _mut_stat_table mut_stat_table[MAXTHREAD];
00215 #endif
00216 mutex_t gc_state_lock;
00217 mutex_t collector_lock;
00218 cond_t ri_end_cv;
00219 cond_t gc_wakeup_cv;
00220 int gc_wakeup_cnt;
00221 int gc_cmp_cnt;
00222 int gc_net_free;
00223 };
00224
00225 extern struct _gc_data gc_data;
00226
00227 #define collector_stack gc_data.collector_stack
00228 #define collector_sp gc_data.collector_sp
00229 #define collector_stacklimit gc_data.collector_stacklimit
00230 #define gc_phase gc_data.gc_phase
00231 #define active_mutator_num gc_data.active_mutator_num
00232 #define gc_counter gc_data.gc_counter
00233 #define gc_point_sync gc_data.gc_point_sync
00234 #define gc_region_sync gc_data.gc_region_sync
00235 #define ri_core_phase gc_data.ri_core_phase
00236 #define mut_stat_phase gc_data.mut_stat_phase
00237
00238 #ifdef __USE_POLLING
00239 #define gc_request_flag gc_data.gc_request_flag
00240 #define mut_stat_table gc_data.mut_stat_table
00241 #endif
00242
00243 #define gc_state_lock gc_data.gc_state_lock
00244 #define collector_lock gc_data.collector_lock
00245 #define ri_end_cv gc_data.ri_end_cv
00246 #define gc_wakeup_cv gc_data.gc_wakeup_cv
00247 #define gc_wakeup_cnt gc_data.gc_wakeup_cnt
00248 #define gc_cmp_cnt gc_data.gc_cmp_cnt
00249 #define gc_net_free gc_data.gc_net_free
00250
00251 #define lock_collector mutex_lock(&collector_lock)
00252 #define unlock_collector mutex_unlock(&collector_lock)
00253
00254 extern mutex_t pstack_lock;
00255 extern mutex_t gcstate_lock;
00256 extern pointer pstack[];
00257 extern volatile pointer *psp;
00258 extern volatile pointer *oldpsp;
00259 extern pointer *pstacklimit;
00260
00261 #ifdef __PROFILE_GC
00262 extern int allocd_words;
00263 #endif
00264
00265 #ifdef __USE_POLLING
00266
00267 #define GC_POINT _check_gc_request()
00268 #define _check_gc_request() { \
00269 if (gc_request_flag) scan_roots(); \
00270 }
00271
00272 #define ENTER_GC_SAFE_REGION(id) enter_gc_region(id)
00273 #define EXIT_GC_SAFE_REGION(id) exit_gc_region(id)
00274 #define GC_REGION(comp_statement) \
00275 { \
00276 int _tmp_id = thr_self(); \
00277 ENTER_GC_SAFE_REGION(_tmp_id); \
00278 comp_statement \
00279 EXIT_GC_SAFE_REGION(_tmp_id); \
00280 }
00281
00282 #else
00283
00284 #define GC_POINT
00285 #define GC_REGION(cmp_statement) cmp_statement
00286
00287 #endif
00288
00289 #define pgpush(v) ( *ctx->gsp++ = ((pointer)v) )
00290 #define pgcpush(v) ( ctx->gsp < ctx->gcstacklimit ? \
00291 pgpush(v) : error(E_GCSTACKOVER) )
00292 #define pgcpop() ( *(--(ctx->gsp)) )
00293 #define ppush(v) ( *psp++ = ((pointer)v) )
00294
00295 extern int ps_sem;
00296 #define busy_sema_wait(k) { \
00297 int i; \
00298 do { \
00299 while ((i = read_volatile_int(k)) <= 0); \
00300 } while (cas_int(k, i, i - 1)); \
00301 start_access_after_write(); \
00302 }
00303 #define busy_sema_post(k) { \
00304 int i; \
00305 finish_access_before_read(); \
00306 do { \
00307 i = read_volatile_int(k); \
00308 } while (cas_int(k, i, i + 1)); \
00309 }
00310
00311 #define pointerpush(v) { \
00312 busy_sema_wait(ps_sem); \
00313 psp < pstacklimit ? ppush(v) : (pointer)error(E_PSTACKOVER); \
00314 busy_sema_post(ps_sem); \
00315 }
00316 #define pointerpop(lv) { \
00317 busy_sema_wait(ps_sem); \
00318 lv = *(--psp); \
00319 busy_sema_post(ps_sem); \
00320 }
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 #ifdef __USE_POLLING
00353
00354 #define take_care(p) \
00355 { \
00356 if(gc_phase >= PHASE_MARK){ \
00357 mutex_lock(&pstack_lock); \
00358 ASSERT((p) == NULL || !ispointer(p) || \
00359 ((unsigned)(p) >= mingcheap && ((unsigned)(p) < maxgcheap))); \
00360 pointerpush(p); \
00361 mutex_unlock(&pstack_lock); \
00362 } \
00363 }
00364
00365
00366
00367
00368
00369 #define pointer_update(l, r) \
00370 { \
00371 if(gc_phase >= PHASE_MARK){ \
00372 mutex_lock(&pstack_lock); \
00373 ASSERT((l) == NULL || !ispointer(l) || \
00374 ((unsigned)(l) >= mingcheap && ((unsigned)(l) < maxgcheap))); \
00375 pointerpush(l); \
00376 mutex_unlock(&pstack_lock); \
00377 } \
00378 (l)=(r); \
00379 }
00380
00381 #define noticeCollector(p1, p2) \
00382 { \
00383 if (gc_phase >= PHASE_MARK) { \
00384 ASSERT((p1) == NULL || !ispointer(p1) || \
00385 ((unsigned)(p1) >= mingcheap && ((unsigned)(p1) < maxgcheap))); \
00386 ASSERT((p2) == NULL || !ispointer(p2) || \
00387 ((unsigned)(p2) >= mingcheap && ((unsigned)(p2) < maxgcheap))); \
00388 mutex_lock(&pstack_lock); \
00389 pointerpush(p1); \
00390 pointerpush(p2); \
00391 mutex_unlock(&pstack_lock); \
00392 } \
00393 }
00394 #define noticeCollector1(p) take_care(p)
00395 #endif
00396
00397 #ifdef __USE_SIGNAL
00398
00399
00400 #define take_care(p){ \
00401 if((((unsigned)p) < mingcheap || ((unsigned)p >= maxgcheap)) \
00402 && (p) != 0 && ispointer(p)) \
00403 hoge(); \
00404 if(gc_phase >= PHASE_MARK){ \
00405 mutex_lock(&pstack_lock); \
00406 pointerpush(p); \
00407 mutex_unlock(&pstack_lock); \
00408 } \
00409 }
00410
00411
00412
00413
00414
00415 #endif
00416
00417
00418 typedef struct barrier_struct {
00419 pthread_mutex_t lock;
00420 int n_clients;
00421 int n_waiting;
00422 int phase;
00423 pthread_cond_t wait_cv;
00424 } *barrier_t;
00425
00426 barrier_t barrier_init(int);
00427 void barrier_reset(barrier_t, int);
00428 void barrier_wait(barrier_t);
00429 extern barrier_t startup_barrier;
00430
00431 #ifdef __USE_SIGNAL
00432 void sighandler(int);
00433 #endif
00434
00435 unsigned int allocate_heap();
00436 extern volatile long sweepheap, newheap, pastfree;
00437
00438 void notify_gc();
00439 void do_a_little_gc_work();
00440
00441 #endif