/* this routine links the time cells into a free list at the start and sets the time queue as empty */ void erts_init_time(void) { int i, itime; /* system dependent init; must be done before do_time_init() if timer thread is enabled */ itime = erts_init_time_sup(); #ifdef TIW_ITIME_IS_CONSTANT if (itime != TIW_ITIME) { erl_exit(ERTS_ABORT_EXIT, "timer resolution mismatch %d != %d", itime, TIW_ITIME); } #else tiw_itime = itime; #endif erts_smp_mtx_init(&tiw_lock, "timer_wheel"); tiw = (ErlTimer**) erts_alloc(ERTS_ALC_T_TIMER_WHEEL, TIW_SIZE * sizeof(ErlTimer*)); for(i = 0; i < TIW_SIZE; i++) tiw[i] = NULL; do_time_init(); tiw_pos = tiw_nto = 0; tiw_min_ptr = NULL; tiw_min = 0; }
int erts_init_time_sup(void) { erts_smp_mtx_init(&erts_timeofday_mtx, "timeofday"); last_emu_time.tv_sec = 0; last_emu_time.tv_usec = 0; #ifndef SYS_CLOCK_RESOLUTION clock_resolution = sys_init_time(); #else (void) sys_init_time(); #endif sys_gettimeofday(&inittv); #ifdef HAVE_GETHRTIME sys_init_hrtime(); #endif init_tolerant_timeofday(); init_erts_deliver_time(&inittv); gtv = inittv; then.tv_sec = then.tv_usec = 0; erts_get_emu_time(&erts_first_emu_time); return CLOCK_RESOLUTION; }
void erts_bp_init(void) { erts_smp_atomic32_init_nob(&erts_active_bp_index, 0); erts_smp_atomic32_init_nob(&erts_staging_bp_index, 1); #ifdef ERTS_DIRTY_SCHEDULERS erts_smp_mtx_init(&erts_dirty_bp_ix_mtx, "dirty_break_point_index", NIL, ERTS_LOCK_FLAGS_PROPERTY_STATIC | ERTS_LOCK_FLAGS_CATEGORY_DEBUG); #endif }
void erts_beam_bif_load_init(void) { erts_smp_mtx_init(&release_literal_areas.mtx, "release_literal_areas"); release_literal_areas.first = NULL; release_literal_areas.last = NULL; erts_smp_atomic_init_nob(&erts_copy_literal_area__, (erts_aint_t) NULL); init_purge_state(); }
void erts_code_ix_init(void) { /* We start emulator by initializing preloaded modules * single threaded with active and staging set both to zero. * Preloading is finished by a commit that will set things straight. */ erts_smp_atomic32_init_nob(&the_active_code_index, 0); erts_smp_atomic32_init_nob(&the_staging_code_index, 0); erts_smp_mtx_init(&the_code_ix_queue_lock, "code_ix_queue"); CIX_TRACE("init"); }
void erts_code_ix_init(void) { /* We start emulator by initializing preloaded modules * single threaded with active and staging set both to zero. * Preloading is finished by a commit that will set things straight. */ erts_smp_atomic32_init_nob(&the_active_code_index, 0); erts_smp_atomic32_init_nob(&the_staging_code_index, 0); erts_smp_mtx_init(&code_write_permission_mtx, "code_write_permission"); #ifdef ERTS_ENABLE_LOCK_CHECK erts_tsd_key_create(&has_code_write_permission, "erts_has_code_write_permission"); #endif CIX_TRACE("init"); }
void init_export_table(void) { int i; erts_smp_mtx_init(&export_staging_lock, "export_tab"); erts_smp_atomic_init_nob(&total_entries_bytes, 0); export_tables = erts_alloc(ERTS_ALC_T_EXPORT_TABLE, sizeof(IndexTable)*ERTS_NUM_CODE_IX); for (i=0; i<ERTS_NUM_CODE_IX; i++) { erts_index_init(ERTS_ALC_T_EXPORT_TABLE, &export_tables[i], "export_list", EXPORT_INITIAL_SIZE, EXPORT_LIMIT, fun); } }
/* ** Init a pre allocated or static hash structure ** and allocate buckets. NOT SAFE */ SafeHash* safe_hash_init(ErtsAlcType_t type, SafeHash* h, char* name, int size, SafeHashFunctions fun) { int i, bytes; size = align_up_pow2(size); bytes = size * sizeof(SafeHashBucket*); h->type = type; h->tab = (SafeHashBucket**) erts_alloc(h->type, bytes); sys_memzero(h->tab, bytes); h->name = name; h->fun = fun; set_size(h,size); erts_smp_atomic_init(&h->is_rehashing, 0); erts_smp_atomic_init(&h->nitems, 0); for (i=0; i<SAFE_HASH_LOCK_CNT; i++) { erts_smp_mtx_init(&h->lock_vec[i].mtx,"safe_hash"); } return h; }
/* this routine links the time cells into a free list at the start and sets the time queue as empty */ void erts_init_time(void) { int i; /* system dependent init; must be done before do_time_init() if timer thread is enabled */ itime = erts_init_time_sup(); erts_smp_mtx_init(&tiw_lock, "timer_wheel"); tiw = (ErlTimer**) erts_alloc(ERTS_ALC_T_TIMER_WHEEL, TIW_SIZE * sizeof(ErlTimer*)); for(i = 0; i < TIW_SIZE; i++) tiw[i] = NULL; do_time_init(); tiw_pos = tiw_nto = 0; tiw_min_ptr = NULL; tiw_min = 0; }
static void init_purge_state(void) { purge_state.module = THE_NON_VALUE; erts_smp_mtx_init(&purge_state.mtx, "purge_state"); purge_state.pending_purge_lambda = erts_export_put(am_erts_code_purger, am_pending_purge_lambda, 3); purge_state.sprocs = &purge_state.def_sprocs[0]; purge_state.sp_size = sizeof(purge_state.def_sprocs); purge_state.sp_size /= sizeof(purge_state.def_sprocs[0]); purge_state.sp_ix = 0; purge_state.funs = &purge_state.def_funs[0]; purge_state.fe_size = sizeof(purge_state.def_funs); purge_state.fe_size /= sizeof(purge_state.def_funs[0]); purge_state.fe_ix = 0; purge_state.saved_old.code_hdr = 0; }
void erts_init_node_tables(void) { HashFunctions f; f.hash = (H_FUN) dist_table_hash; f.cmp = (HCMP_FUN) dist_table_cmp; f.alloc = (HALLOC_FUN) dist_table_alloc; f.free = (HFREE_FUN) dist_table_free; erts_this_dist_entry = erts_alloc(ERTS_ALC_T_DIST_ENTRY, sizeof(DistEntry)); dist_entries = 1; hash_init(ERTS_ALC_T_DIST_TABLE, &erts_dist_table, "dist_table", 11, f); erts_hidden_dist_entries = NULL; erts_visible_dist_entries = NULL; erts_not_connected_dist_entries = NULL; erts_no_of_hidden_dist_entries = 0; erts_no_of_visible_dist_entries = 0; erts_no_of_not_connected_dist_entries = 0; erts_this_dist_entry->next = NULL; erts_this_dist_entry->prev = NULL; erts_refc_init(&erts_this_dist_entry->refc, 1); /* erts_this_node */ erts_this_dist_entry->sysname = am_Noname; erts_this_dist_entry->cid = NIL; erts_this_dist_entry->node_links = NULL; erts_this_dist_entry->nlinks = NULL; erts_this_dist_entry->monitors = NULL; erts_this_dist_entry->status = 0; erts_this_dist_entry->flags = 0; erts_this_dist_entry->cache = NULL; erts_this_dist_entry->version = 0; (void) hash_put(&erts_dist_table, (void *) erts_this_dist_entry); f.hash = (H_FUN) node_table_hash; f.cmp = (HCMP_FUN) node_table_cmp; f.alloc = (HALLOC_FUN) node_table_alloc; f.free = (HFREE_FUN) node_table_free; hash_init(ERTS_ALC_T_NODE_TABLE, &erts_node_table, "node_table", 11, f); erts_this_node = erts_alloc(ERTS_ALC_T_NODE_ENTRY, sizeof(ErlNode)); node_entries = 1; erts_refc_init(&erts_this_node->refc, 1); /* The system itself */ erts_this_node->sysname = am_Noname; erts_this_node->creation = 0; erts_this_node->dist_entry = erts_this_dist_entry; (void) hash_put(&erts_node_table, (void *) erts_this_node); #ifdef ERTS_SMP { int i; for (i = 0; i < ERTS_NO_OF_DIST_ENTRY_MUTEXES; i++) { #ifdef ERTS_ENABLE_LOCK_COUNT erts_smp_mtx_init_x(&dist_entry_mutexes[i], "dist_entry", make_small(i)); #else erts_smp_mtx_init(&dist_entry_mutexes[i], "dist_entry"); #endif /*ERTS_ENABLE_LOCK_COUNT*/ } erts_this_dist_entry->mtxp = &dist_entry_mutexes[0]; erts_smp_mtx_init(&erts_node_table_mtx, "node_table"); erts_smp_mtx_init(&erts_dist_table_mtx, "dist_table"); } #endif references_atoms_need_init = 1; }
void sys_init_time(ErtsSysInitTimeResult *init_resp) { #if defined(ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT) int major, minor, build, vsn; #endif #if defined(ERTS_MACH_CLOCKS) mach_clocks_init(); #endif #if !defined(ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT) init_resp->have_os_monotonic_time = 0; #else /* defined(ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT) */ #ifdef ERTS_HAVE_CORRECTED_OS_MONOTONIC_TIME init_resp->have_corrected_os_monotonic_time = 1; #else init_resp->have_corrected_os_monotonic_time = 0; #endif init_resp->os_monotonic_time_info.resolution = (Uint64) 1000*1000*1000; #if defined(HAVE_CLOCK_GETRES) && defined(MONOTONIC_CLOCK_ID) { struct timespec ts; if (clock_getres(MONOTONIC_CLOCK_ID, &ts) == 0) { if (ts.tv_sec == 0 && ts.tv_nsec != 0) init_resp->os_monotonic_time_info.resolution /= ts.tv_nsec; else if (ts.tv_sec >= 1) init_resp->os_monotonic_time_info.resolution = 1; } } #elif defined(ERTS_HAVE_MACH_CLOCK_GETRES) && defined(MONOTONIC_CLOCK_ID) init_resp->os_monotonic_time_info.resolution = mach_clock_getres(&internal_state.r.o.mach.clock.monotonic); #endif #ifdef MONOTONIC_CLOCK_ID_STR init_resp->os_monotonic_time_info.clock_id = MONOTONIC_CLOCK_ID_STR; #else init_resp->os_monotonic_time_info.clock_id = NULL; #endif init_resp->os_monotonic_time_info.locked_use = 0; #if defined(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME) init_resp->os_monotonic_time_info.func = "clock_gettime"; #elif defined(OS_MONOTONIC_TIME_USING_MACH_CLOCK_GET_TIME) init_resp->os_monotonic_time_info.func = "clock_get_time"; #elif defined(OS_MONOTONIC_TIME_USING_GETHRTIME) init_resp->os_monotonic_time_info.func = "gethrtime"; #elif defined(OS_MONOTONIC_TIME_USING_TIMES) init_resp->os_monotonic_time_info.func = "times"; #else # error Unknown erts_os_monotonic_time() implementation #endif init_resp->have_os_monotonic_time = 1; os_version(&major, &minor, &build); vsn = ERTS_MK_VSN_INT(major, minor, build); #if defined(__linux__) && defined(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME) if (vsn >= ERTS_MK_VSN_INT(2, 6, 33)) { erts_sys_time_data__.r.o.os_monotonic_time = clock_gettime_monotonic; #if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME) erts_sys_time_data__.r.o.os_times = clock_gettime_times; #endif } else { /* * Linux versions prior to 2.6.33 have a * known bug that sometimes cause the NTP * adjusted monotonic clock to take small * steps backwards. Use raw monotonic clock * if it is present; otherwise, fall back * on locked verification of values. */ init_resp->have_corrected_os_monotonic_time = 0; #if defined(HAVE_CLOCK_GETTIME_MONOTONIC_RAW) /* We know that CLOCK_MONOTONIC_RAW is defined, but we don't know if we got a kernel that supports it. Support for CLOCK_MONOTONIC_RAW appeared in kernel 2.6.28... */ if (vsn >= ERTS_MK_VSN_INT(2, 6, 28)) { erts_sys_time_data__.r.o.os_monotonic_time = clock_gettime_monotonic_raw; #if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME) erts_sys_time_data__.r.o.os_times = clock_gettime_times_raw; #endif init_resp->os_monotonic_time_info.clock_id = "CLOCK_MONOTONIC_RAW"; } else #endif /* defined(HAVE_CLOCK_GETTIME_MONOTONIC_RAW) */ { erts_sys_time_data__.r.o.os_monotonic_time = clock_gettime_monotonic_verified; #if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME) erts_sys_time_data__.r.o.os_times = clock_gettime_times_verified; #endif erts_smp_mtx_init(&internal_state.w.f.mtx, "os_monotonic_time"); internal_state.w.f.last_delivered = clock_gettime_monotonic(); init_resp->os_monotonic_time_info.locked_use = 1; } } #else /* !(defined(__linux__) && defined(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME)) */ { char flavor[1024]; os_flavor(flavor, sizeof(flavor)); if (sys_strcmp(flavor, "sunos") == 0) { /* * Don't trust hrtime on multi processors * on SunOS prior to SunOS 5.8 */ if (vsn < ERTS_MK_VSN_INT(5, 8, 0)) { #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF) if (sysconf(_SC_NPROCESSORS_CONF) > 1) #endif init_resp->have_os_monotonic_time = 0; } } } #endif /* !(defined(__linux__) && defined(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME)) */ #endif /* defined(ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT) */ #ifdef ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT init_resp->os_monotonic_time_unit = ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT; #endif init_resp->sys_clock_resolution = SYS_CLOCK_RESOLUTION; /* * This (erts_sys_time_data__.r.o.ticks_per_sec) is only for * times() (CLK_TCK), the resolution is always one millisecond.. */ if ((erts_sys_time_data__.r.o.ticks_per_sec = TICKS_PER_SEC()) < 0) erl_exit(ERTS_ABORT_EXIT, "Can't get clock ticks/sec\n"); #if defined(OS_MONOTONIC_TIME_USING_TIMES) #if ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT # error Time unit is supposed to be determined at runtime... #endif { ErtsMonotonicTime resolution = erts_sys_time_data__.r.o.ticks_per_sec; ErtsMonotonicTime time_unit = resolution; int shift = 0; while (time_unit < 1000*1000) { time_unit <<= 1; shift++; } init_resp->os_monotonic_time_info.resolution = resolution; init_resp->os_monotonic_time_unit = time_unit; init_resp->os_monotonic_time_info.extended = 1; internal_state.r.o.times_shift = shift; erts_init_os_monotonic_time_extender(&internal_state.wr.m.os_mtime_xtnd, get_tick_count, (1 << 29) / resolution); } #endif /* defined(OS_MONOTONIC_TIME_USING_TIMES) */ #ifdef WALL_CLOCK_ID_STR init_resp->os_system_time_info.clock_id = WALL_CLOCK_ID_STR; #else init_resp->os_system_time_info.clock_id = NULL; #endif init_resp->os_system_time_info.locked_use = 0; init_resp->os_system_time_info.resolution = (Uint64) 1000*1000*1000; #if defined(HAVE_CLOCK_GETRES) && defined(WALL_CLOCK_ID) { struct timespec ts; if (clock_getres(WALL_CLOCK_ID, &ts) == 0) { if (ts.tv_sec == 0 && ts.tv_nsec != 0) init_resp->os_system_time_info.resolution /= ts.tv_nsec; else if (ts.tv_sec >= 1) init_resp->os_system_time_info.resolution = 1; } } #elif defined(ERTS_HAVE_MACH_CLOCK_GETRES) && defined(WALL_CLOCK_ID) init_resp->os_system_time_info.resolution = mach_clock_getres(&internal_state.r.o.mach.clock.wall); #endif #if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME) init_resp->os_system_time_info.func = "clock_gettime"; #elif defined(OS_SYSTEM_TIME_USING_MACH_CLOCK_GET_TIME) init_resp->os_system_time_info.func = "clock_get_time"; #elif defined(OS_SYSTEM_TIME_GETTIMEOFDAY) init_resp->os_system_time_info.func = "gettimeofday"; init_resp->os_system_time_info.resolution = 1000*1000; init_resp->os_system_time_info.clock_id = NULL; #else # error Missing erts_os_system_time() implementation #endif }