Initialization

Functions

void tm_init (int *argcp, char ***argvp, char ***envpp)
 API: Initialize the tm allocator.

Function Documentation

void tm_init ( int *  argcp,
char ***  argvp,
char ***  envpp 
)

API: Initialize the tm allocator.

This should be called from main():

 int main(int argc, char **argv, char **envp)
 {
   tm_init(&argc, &argv, &envp);
   ...
 }
 

Initialize time stat names.

Initialize tm_msg() ignore table.

Warn if already initalized.

Error if argcp and argvp are not given.

Default envpp = &environ, if not given.

Initialize possible pointer range.

Initialize root sets.

Initialize root set for the register set, using a jmpbuf struct.

Initialize roots set for the stack.

Remove anti-roots: do not scan tm's internal data structures.

Initialize root set for initialized and uninitialize (zeroed) data segments.

IMPLEMENT: Support dynamically-loaded library data segments.

Dump the tm_root sets.

Validate tm_root sets.

Initialize root marking loop.

Initialize global tm_type list.

Initialize tm_node color iterators.

Initialize page managment.

Initialize tm_block free list.

Initialize tm_type free list.

Initialize size to tm_type hash table.

Initialize block sweep iterator.

Initialize phase: start by unmarking.

Set up write barrier hooks.

Mark system as initialized.

Definition at line 77 of file init.c.

References __tm_write_barrier(), __tm_write_barrier_pure(), __tm_write_barrier_root(), _tm_block_sweep_init(), _tm_phase_init(), _tm_root_loop_init(), _tm_set_stack_ptr(), _tm_user_bss, _tm_user_data, _tm_write_barrier, _tm_write_barrier_pure, _tm_write_barrier_root, tm_data::data_mutations, tm_data::free_blocks, tm_data::free_blocks_n, tm_root::h, tm_type::hash_next, tm_data::inited, tm_data::initing, tm_data::jb, tm_root::l, tm_root::name, tm_time_stat::name, tm_data::nroots, tm_data::page_in_use, tm_data::root_datai, tm_data::roots, tm_data::stack_grows, tm_data::stack_mutations, tm_data::stack_ptrp, tm, tm_assert, tm_BLACK, tm_ECRU, tm_FREE_BLOCK, tm_GREY, tm_list_assert_layout(), tm_list_init(), tm_list_set_color, tm_LIVE_TYPE, tm_msg(), tm_msg_enable(), tm_msg_enable_all, tm_msg_enable_default, tm_phase_name, tm_ptr_h, tm_ptr_is_in_root_set(), tm_ptr_l, tm_root_add(), tm_root_remove(), tm_stack_growth(), tm_type_hash_LEN, tm_type_init(), tm_UNMARK, tm_WHITE, tm_data::ts_alloc, tm_data::ts_barrier, tm_data::ts_barrier_black, tm_data::ts_barrier_pure, tm_data::ts_barrier_root, tm_data::ts_free, tm_data::ts_gc, tm_data::ts_gc_inner, tm_data::ts_os_alloc, tm_data::ts_os_free, tm_data::ts_phase, tm_data::type_free, tm_data::type_hash, tm_data::type_reserve, tm_data::types, and X.

Referenced by tm_alloc(), tm_free(), and tm_gc_full().

00078 {
00079   int i;
00080 
00081   tm_assert(sizeof(unsigned long) == sizeof(void *));
00082 
00083   /*! Initialize time stat names. */
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   /*! Initialize tm_msg() ignore table. */
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   // tm_msg_enable("b", 1);
00109 
00110   tm_list_assert_layout();
00111 
00112   /*! Warn if already initalized. */
00113   if ( tm.inited ) {
00114     tm_msg("WARNING: tm_init() called more than once.\nf");
00115   }
00116   tm.initing ++;
00117 
00118   /*! Error if argcp and argvp are not given. */
00119   if ( ! argcp || ! argvp ) {
00120     tm_msg("WARNING: tm_init() not called from main().\n");
00121   }
00122 
00123   /*! Default envpp = &environ, if not given. */
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   /*! Initialize possible pointer range. */
00141   tm_ptr_l = (void*) ~0UL;
00142   tm_ptr_h = 0;
00143 
00144   /*! Initialize root sets. */
00145   tm.nroots = 0;
00146   tm.data_mutations = tm.stack_mutations = 0;
00147 
00148   tm.root_datai = -1;
00149 
00150   /*! Initialize root set for the register set, using a jmpbuf struct. */
00151   /* A C jmpbuf struct contains the saved registers set, hopefully. */
00152   tm_root_add("register", &tm.jb, (&tm.jb) + 1);
00153 
00154   /*! Initialize roots set for the stack. */
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   /* argvp contains a caller's auto variable. */
00170   /* Hope that we are being called from somewhere close to the bottom of the stack. */
00171     bottom_of_stack = (void*) argvp;
00172 #endif
00173 
00174     {
00175       void *l = top_of_stack;
00176       void *h = bottom_of_stack;
00177       
00178       /* Determine direction of stack growth. */
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       /* Attempt to nudge to page boundaries. */
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     /* Remember where to put the stack pointer. */
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     /* IMPLEMENT: Support for multithreading stacks. */
00208   }
00209 
00210 
00211   /*! Remove anti-roots: do not scan tm's internal data structures. */
00212   tm_root_remove("tm", &tm, &tm + 1);
00213 
00214   /*! Initialize root set for initialized and uninitialize (zeroed) data segments. */
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   /*! IMPLEMENT: Support dynamically-loaded library data segments. */
00251 
00252   /*! Dump the tm_root sets. */
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   /*! Validate tm_root sets. */
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   /*! Initialize root marking loop. */
00280   _tm_root_loop_init();
00281 
00282   /*! Initialize global tm_type list. */
00283   tm_type_init(&tm.types, 0);
00284   tm_list_set_color(&tm.types, tm_LIVE_TYPE);
00285 
00286   /*! Initialize tm_node color iterators. */
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   /*! Initialize page managment. */
00299   memset(tm.page_in_use, 0, sizeof(tm.page_in_use));
00300 
00301   /*! Initialize tm_block free list. */
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   /* Types. */
00307 
00308   /*! Initialize tm_type free list. */
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   /*! Initialize size to tm_type hash table. */
00316   for ( i = 0; i < tm_type_hash_LEN; i ++ ) {
00317     tm.type_hash[i] = 0;
00318   }
00319 
00320   /*! Initialize block sweep iterator. */
00321   _tm_block_sweep_init();
00322 
00323   /*! Initialize phase: start by unmarking. */
00324   _tm_phase_init(tm_UNMARK);
00325   
00326   /*! Set up write barrier hooks. */
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   /*! Mark system as initialized. */
00332   -- tm.initing;
00333   ++ tm.inited;
00334   tm_msg_enable("WF", 0);
00335 }

Here is the call graph for this function:

Here is the caller graph for this function:


Generated on Mon Jan 25 06:33:12 2010 for TM(tredmill) by  doxygen 1.6.1