Functions | |
static __inline void | tm_type_init (tm_type *t, size_t size) |
Initialize a new tm_type of a given size. | |
static int | tm_stack_growth (char *ptr, int depth) |
Determine the direction of stack growth. | |
void | tm_init (int *argcp, char ***argvp, char ***envpp) |
API: Initialize the tm allocator. | |
Variables | |
long | tm_node_parcel_some_size = 8 |
Nodes to parcel from a tm_block per tm_alloc(). | |
long | tm_node_scan_some_size = 32 * 2 |
Words to scan per tm_alloc(). | |
long | tm_node_sweep_some_size = 8 |
Nodes to sweep per tm_alloc(). | |
long | tm_node_unmark_some_size = 8 |
Nodes to unmark per tm_alloc(). | |
long | tm_block_sweep_some_size = 2 |
Number of blocks per tm_alloc() to sweep after sweep phase. | |
int | tm_block_min_free = 4 |
Minimum number of tm_blocks to retain on block free list. | |
size_t | tm_os_alloc_max = 64 * 1024 * 1024 |
int | tm_root_scan_full = 1 |
If true, all roots are scanned atomically before moving to the SCAN phase. | |
| |
long | tm_root_scan_some_size |
Amount of roots words to scan per tm_malloc(). | |
long | tm_node_scan_some_size |
Words to scan per tm_alloc(). | |
long | tm_node_sweep_some_size |
Nodes to sweep per tm_alloc(). | |
long | tm_node_unmark_some_size |
Nodes to unmark per tm_alloc(). | |
long | tm_block_sweep_some_size |
Number of blocks per tm_alloc() to sweep after sweep phase. | |
int | tm_block_min_free |
Minimum number of tm_blocks to retain on block free list. | |
size_t | tm_os_alloc_max |
int | tm_root_scan_full |
If true, all roots are scanned atomically before moving to the SCAN phase. |
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 }
static int tm_stack_growth | ( | char * | ptr, | |
int | depth | |||
) | [static] |
Determine the direction of stack growth.
Definition at line 54 of file init.c.
Referenced by tm_init().
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 }
static __inline void tm_type_init | ( | tm_type * | t, | |
size_t | size | |||
) | [static] |
Initialize a new tm_type of a given size.
Assign a the tm_type a unique id.
Initialize tm_type's global list pointers.
Mark the tm_type as live.
Initialize the tm_types.blocks list.
Initialize the tm_type node counts.
Initialize the tm_type.color_list.
Force a new tm_block to be allocated and parceled.
Zero the tm_type descriptor.
Definition at line 1217 of file tm.c.
References tm_type::blocks, tm_type::color_list, tm_type::desc, tm_type::id, tm_type::list, tm_type::n, tm_type::parcel_from_block, tm_type::size, tm, tm_list_init(), tm_list_set_color, tm_LIVE_BLOCK, tm_LIVE_TYPE, and tm_data::type_id.
Referenced by tm_init(), and tm_type_new().
01218 { 01219 /*! Assign a the tm_type a unique id. */ 01220 t->id = ++ tm.type_id; 01221 01222 /*! Initialize tm_type's global list pointers. */ 01223 tm_list_init(&t->list); 01224 01225 /*! Mark the tm_type as live. */ 01226 tm_list_set_color(&t->list, tm_LIVE_TYPE); 01227 #if tm_name_GUARD 01228 t->name = "TYPE"; 01229 #endif 01230 t->size = size; 01231 01232 /*! Initialize the tm_types.blocks list. */ 01233 tm_list_init(&t->blocks); 01234 tm_list_set_color(&t->blocks, tm_LIVE_BLOCK); 01235 01236 /*! Initialize the tm_type node counts. */ 01237 memset(t->n, 0, sizeof(t->n)); 01238 01239 /*! Initialize the tm_type.color_list. */ 01240 { 01241 int j; 01242 01243 for ( j = 0; j < sizeof(t->color_list) / sizeof(t->color_list[0]); ++ j ) { 01244 tm_list_init(&t->color_list[j]); 01245 tm_list_set_color(&t->color_list[j], j); 01246 } 01247 } 01248 01249 /*! Force a new tm_block to be allocated and parceled. */ 01250 t->parcel_from_block = 0; 01251 01252 /*! Zero the tm_type descriptor. */ 01253 t->desc = 0; 01254 }
Minimum number of tm_blocks to retain on block free list.
Definition at line 31 of file init.c.
Referenced by _tm_block_free().
int tm_block_min_free = 4 |
Minimum number of tm_blocks to retain on block free list.
Definition at line 31 of file init.c.
Referenced by _tm_block_free().
Number of blocks per tm_alloc() to sweep after sweep phase.
Definition at line 28 of file init.c.
Referenced by _tm_block_sweep_some().
long tm_block_sweep_some_size = 2 |
Number of blocks per tm_alloc() to sweep after sweep phase.
Definition at line 28 of file init.c.
Referenced by _tm_block_sweep_some().
long tm_node_parcel_some_size = 8 |
Nodes to parcel from a tm_block per tm_alloc().
Definition at line 16 of file init.c.
Referenced by _tm_node_parcel_or_alloc().
Words to scan per tm_alloc().
Definition at line 19 of file init.c.
Referenced by _tm_alloc_type_inner().
long tm_node_scan_some_size = 32 * 2 |
Words to scan per tm_alloc().
Definition at line 19 of file init.c.
Referenced by _tm_alloc_type_inner().
Nodes to sweep per tm_alloc().
Definition at line 22 of file init.c.
Referenced by _tm_alloc_type_inner().
long tm_node_sweep_some_size = 8 |
Nodes to sweep per tm_alloc().
Definition at line 22 of file init.c.
Referenced by _tm_alloc_type_inner().
Nodes to unmark per tm_alloc().
Definition at line 25 of file init.c.
Referenced by _tm_alloc_type_inner().
long tm_node_unmark_some_size = 8 |
Nodes to unmark per tm_alloc().
Definition at line 25 of file init.c.
Referenced by _tm_alloc_type_inner().
size_t tm_os_alloc_max |
Definition at line 34 of file init.c.
Referenced by _tm_os_alloc().
size_t tm_os_alloc_max = 64 * 1024 * 1024 |
Definition at line 34 of file init.c.
Referenced by _tm_os_alloc().
If true, all roots are scanned atomically before moving to the SCAN phase.
Definition at line 37 of file init.c.
Referenced by _tm_alloc_type_inner().
int tm_root_scan_full = 1 |
If true, all roots are scanned atomically before moving to the SCAN phase.
Definition at line 37 of file init.c.
Referenced by _tm_alloc_type_inner().
Amount of roots words to scan per tm_malloc().
Definition at line 40 of file mark.c.
Referenced by _tm_root_scan_some().