00001
00002
00003
00004
00005
00006
00007
00008 #include "tm.h"
00009 #include "internal.h"
00010
00011
00012
00013
00014
00015
00016 long tm_node_parcel_some_size = 8;
00017
00018
00019 long tm_node_scan_some_size = 32 * 2;
00020
00021
00022 long tm_node_sweep_some_size = 8;
00023
00024
00025 long tm_node_unmark_some_size = 8;
00026
00027
00028 long tm_block_sweep_some_size = 2;
00029
00030
00031 int tm_block_min_free = 4;
00032
00033
00034 size_t tm_os_alloc_max = 64 * 1024 * 1024;
00035
00036
00037 int tm_root_scan_full = 1;
00038
00039
00040
00041
00042
00043
00044
00045
00046 static __inline
00047 void tm_type_init(tm_type *t, size_t size);
00048
00049
00050
00051
00052
00053 static
00054 int tm_stack_growth(char *ptr, int depth)
00055 {
00056 char *top_of_stack = (char*) &top_of_stack;
00057 if ( depth ) {
00058 return tm_stack_growth(ptr, depth - 1);
00059 }
00060 return top_of_stack - ptr;
00061 }
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 void tm_init(int *argcp, char ***argvp, char ***envpp)
00078 {
00079 int i;
00080
00081 tm_assert(sizeof(unsigned long) == sizeof(void *));
00082
00083
00084 tm.ts_os_alloc.name = "tm_os_alloc";
00085 tm.ts_os_free.name = "tm_os_free";
00086 tm.ts_alloc.name = "tm_alloc";
00087 tm.ts_free.name = "tm_free";
00088 tm.ts_gc.name = "gc";
00089 tm.ts_gc_inner.name = "gc_inner";
00090 tm.ts_barrier.name = "tm_barrier";
00091 tm.ts_barrier_pure.name = "tm_barrier_p";
00092 tm.ts_barrier_root.name = "tm_barrier_r";
00093 tm.ts_barrier_black.name = "tm_barrier B";
00094
00095 for ( i = 0; i < (sizeof(tm.ts_phase) / sizeof(tm.ts_phase[0])); ++ i ) {
00096 tm.ts_phase[i].name = tm_phase_name[i];
00097 }
00098
00099
00100 if ( tm_msg_enable_all ) {
00101 tm_msg_enable("\1", 1);
00102 } else {
00103 tm_msg_enable(tm_msg_enable_default, 1);
00104 tm_msg_enable(" \t\n\r", 1);
00105 }
00106
00107 tm_msg_enable("WF", 1);
00108
00109
00110 tm_list_assert_layout();
00111
00112
00113 if ( tm.inited ) {
00114 tm_msg("WARNING: tm_init() called more than once.\nf");
00115 }
00116 tm.initing ++;
00117
00118
00119 if ( ! argcp || ! argvp ) {
00120 tm_msg("WARNING: tm_init() not called from main().\n");
00121 }
00122
00123
00124 if ( ! envpp ) {
00125 extern char **environ;
00126 tm_msg("WARNING: tm_init(): not passed &envp.\n");
00127 envpp = (char ***) &environ;
00128 }
00129
00130 #if 0
00131 #define P(X) tm_msg(" %s = %ld\n", #X, (long) X);
00132 P(sizeof(tm_list));
00133 P(sizeof(tm_node));
00134 P(sizeof(tm_block));
00135 P(sizeof(tm_type));
00136 P(sizeof(struct tm_data));
00137 #undef P
00138 #endif
00139
00140
00141 tm_ptr_l = (void*) ~0UL;
00142 tm_ptr_h = 0;
00143
00144
00145 tm.nroots = 0;
00146 tm.data_mutations = tm.stack_mutations = 0;
00147
00148 tm.root_datai = -1;
00149
00150
00151
00152 tm_root_add("register", &tm.jb, (&tm.jb) + 1);
00153
00154
00155
00156 {
00157 void *bottom_of_stack, *top_of_stack = (void*) &i;
00158
00159 #ifndef tm_ENVIRON_0_ALLOCATED_ON_STACK
00160 #define tm_ENVIRON_0_ALLOCATED_ON_STACK 1
00161 #endif
00162
00163 #if tm_ENVIRON_0_ALLOCATED_ON_STACK
00164 {
00165 extern char **environ;
00166 bottom_of_stack = (void*) environ[0];
00167 }
00168 #else
00169
00170
00171 bottom_of_stack = (void*) argvp;
00172 #endif
00173
00174 {
00175 void *l = top_of_stack;
00176 void *h = bottom_of_stack;
00177
00178
00179 if ( tm_stack_growth((char*) &l, 5) < 0 ) {
00180 tm.stack_grows = -1;
00181 } else {
00182 void *t = l;
00183 l = h;
00184 h = t;
00185 tm.stack_grows = 1;
00186 }
00187
00188
00189 {
00190 size_t stack_page_size = 4096;
00191 l = (void*) ((unsigned long) (l) - ((unsigned long) (l) % stack_page_size));
00192 h = (void*) ((unsigned long) (h) + (stack_page_size - ((unsigned long) (h) % stack_page_size)));
00193 }
00194
00195 i = tm_root_add("stack", l, h);
00196 }
00197
00198
00199 if ( tm.stack_grows < 0 ) {
00200 tm.stack_ptrp = (void**) &tm.roots[i].l;
00201 } else {
00202 tm.stack_ptrp = (void**) &tm.roots[i].h;
00203 }
00204
00205 tm.root_datai = i + 1;
00206
00207
00208 }
00209
00210
00211
00212 tm_root_remove("tm", &tm, &tm + 1);
00213
00214
00215 #ifdef __win32__
00216 {
00217 extern int _data_start__, _data_end__, _bss_start__, _bss_end__;
00218
00219 tm_root_add("initialized data", &_data_start__, &_data_end__);
00220 tm_root_add("uninitialized data", &_bss_start__, &_bss_end__);
00221
00222 }
00223 #define tm_roots_data_segs
00224 #endif
00225
00226 #ifdef __linux__
00227 {
00228 extern int __data_start, __bss_start, _end;
00229
00230 #if 0
00231 fprintf(stderr, "__data_start = %d\n", __data_start);
00232 fprintf(stderr, "__bss_start = %d\n", __bss_start);
00233 fprintf(stderr, "_end = %d\n", _end);
00234 #endif
00235
00236 #if 1
00237 tm_assert(&__data_start < &__bss_start && &__bss_start < &_end);
00238 tm_root_add("initialized data", &__data_start, &__bss_start);
00239 tm_root_add("uninitialized data", &__bss_start, &_end);
00240 #endif
00241 }
00242 #define tm_roots_data_segs
00243 #endif
00244
00245 #ifndef tm_roots_data_segs
00246 #error must specify how to find the data segment(s) for root marking.
00247 #endif
00248
00249
00250
00251
00252
00253 tm_msg_enable("R", 1);
00254
00255 tm_msg("R ROOTS {\n");
00256 for ( i = 0; tm.roots[i].name; ++ i ) {
00257 if ( tm.roots[i].l != tm.roots[i].h ) {
00258 tm_msg("R \t [%p,%p] %s %d\n",
00259 tm.roots[i].l,
00260 tm.roots[i].h,
00261 tm.roots[i].name,
00262 i);
00263 }
00264 }
00265 tm_msg("R }\n");
00266
00267 tm_msg_enable("R", 0);
00268
00269
00270 {
00271 extern int _tm_user_bss[], _tm_user_data[];
00272
00273 tm_assert(tm_ptr_is_in_root_set(_tm_user_bss), ": _tm_user_bss = %p", _tm_user_bss);
00274 tm_assert(tm_ptr_is_in_root_set(_tm_user_data), ": _tm_user_data = %p", _tm_user_data);
00275 _tm_set_stack_ptr(&i);
00276 tm_assert(tm_ptr_is_in_root_set(&i), ": &i = %p", &i);
00277 }
00278
00279
00280 _tm_root_loop_init();
00281
00282
00283 tm_type_init(&tm.types, 0);
00284 tm_list_set_color(&tm.types, tm_LIVE_TYPE);
00285
00286
00287 #define X(C) \
00288 tm.node_color_iter[C].color = C; \
00289 tm_node_LOOP_INIT(C)
00290
00291 X(tm_WHITE);
00292 X(tm_ECRU);
00293 X(tm_GREY);
00294 X(tm_BLACK);
00295
00296 #undef X
00297
00298
00299 memset(tm.page_in_use, 0, sizeof(tm.page_in_use));
00300
00301
00302 tm_list_init(&tm.free_blocks);
00303 tm_list_set_color(&tm.free_blocks, tm_FREE_BLOCK);
00304 tm.free_blocks_n = 0;
00305
00306
00307
00308
00309 for ( i = 0; i < sizeof(tm.type_reserve)/sizeof(tm.type_reserve[0]); ++ i ) {
00310 tm_type *t = &tm.type_reserve[i];
00311 t->hash_next = (void*) tm.type_free;
00312 tm.type_free = t;
00313 }
00314
00315
00316 for ( i = 0; i < tm_type_hash_LEN; i ++ ) {
00317 tm.type_hash[i] = 0;
00318 }
00319
00320
00321 _tm_block_sweep_init();
00322
00323
00324 _tm_phase_init(tm_UNMARK);
00325
00326
00327 _tm_write_barrier = __tm_write_barrier;
00328 _tm_write_barrier_pure = __tm_write_barrier_pure;
00329 _tm_write_barrier_root = __tm_write_barrier_root;
00330
00331
00332 -- tm.initing;
00333 ++ tm.inited;
00334 tm_msg_enable("WF", 0);
00335 }
00336
00337
00338
00339
00340
00341
00342