BIF_RETTYPE system_info_1()

in erts/emulator/beam/erl_bif_info.c [2424:3207]


BIF_RETTYPE system_info_1(BIF_ALIST_1)
{
    Eterm res;
    Eterm* hp;
    Eterm val;
    int i;

    if (is_tuple(BIF_ARG_1)) {
	Eterm* tp = tuple_val(BIF_ARG_1);
	Uint arity = *tp++;
	return info_1_tuple(BIF_P, tp, arityval(arity));
    } else if (BIF_ARG_1 == am_scheduler_id) {
	ErtsSchedulerData *esdp = erts_proc_sched_data(BIF_P);
	BIF_RET(make_small(esdp->no));
    } else if (BIF_ARG_1 == am_compat_rel) {
	ASSERT(erts_compat_rel > 0);
	BIF_RET(make_small(erts_compat_rel));
    } else if (BIF_ARG_1 == am_multi_scheduling) {
	{
	    int msb = erts_is_multi_scheduling_blocked();
	    BIF_RET(!msb
		    ? am_enabled
		    : (msb > 0
		       ? am_blocked
		       : am_blocked_normal));
	}
    } else if (BIF_ARG_1 == am_build_type || BIF_ARG_1 == am_emu_type) {
#if defined(DEBUG)
	ERTS_DECL_AM(debug);
	BIF_RET(AM_debug);
#elif defined(PURIFY)
	ERTS_DECL_AM(purify);
	BIF_RET(AM_purify);
#elif defined(QUANTIFY)
	ERTS_DECL_AM(quantify);
	BIF_RET(AM_quantify);
#elif defined(PURECOV)
	ERTS_DECL_AM(purecov);
	BIF_RET(AM_purecov);
#elif defined(ERTS_GCOV)
	ERTS_DECL_AM(gcov);
	BIF_RET(AM_gcov);
#elif defined(VALGRIND)
	ERTS_DECL_AM(valgrind);
	BIF_RET(AM_valgrind);
#elif defined(GPROF)
	ERTS_DECL_AM(gprof);
	BIF_RET(AM_gprof);
#elif defined(ERTS_ENABLE_LOCK_COUNT)
	ERTS_DECL_AM(lcnt);
	BIF_RET(AM_lcnt);
#elif defined(ERTS_FRMPTR)
	ERTS_DECL_AM(frmptr);
	BIF_RET(AM_frmptr);
#else
	BIF_RET(am_opt);
#endif
    } else if (BIF_ARG_1 == am_emu_flavor) {
#if defined(BEAMASM)
	ERTS_DECL_AM(jit);
	BIF_RET(AM_jit);
#else
        ERTS_DECL_AM(emu);
	BIF_RET(AM_emu);
#endif
    } else if (BIF_ARG_1 == am_time_offset) {
	switch (erts_time_offset_state()) {
	case ERTS_TIME_OFFSET_PRELIMINARY: {
	    ERTS_DECL_AM(preliminary);
	    BIF_RET(AM_preliminary);
	}
	case ERTS_TIME_OFFSET_FINAL: {
	    ERTS_DECL_AM(final);
	    BIF_RET(AM_final);
	}
	case ERTS_TIME_OFFSET_VOLATILE: {
	    ERTS_DECL_AM(volatile);
	    BIF_RET(AM_volatile);
	}
	default:
	    ERTS_INTERNAL_ERROR("Invalid time offset state");
	}
    } else if (ERTS_IS_ATOM_STR("os_monotonic_time_source", BIF_ARG_1)) {
	BIF_RET(erts_monotonic_time_source(BIF_P));
    } else if (ERTS_IS_ATOM_STR("os_system_time_source", BIF_ARG_1)) {
	BIF_RET(erts_system_time_source(BIF_P));
    } else if (ERTS_IS_ATOM_STR("time_correction", BIF_ARG_1)) {
	BIF_RET(erts_has_time_correction() ? am_true : am_false);
    } else if (ERTS_IS_ATOM_STR("start_time", BIF_ARG_1)) {
	BIF_RET(erts_get_monotonic_start_time(BIF_P));
    } else if (ERTS_IS_ATOM_STR("end_time", BIF_ARG_1)) {
	BIF_RET(erts_get_monotonic_end_time(BIF_P));
    } else if (ERTS_IS_ATOM_STR("time_warp_mode", BIF_ARG_1)) {
	switch (erts_time_warp_mode()) {
	case ERTS_NO_TIME_WARP_MODE: {
	    ERTS_DECL_AM(no_time_warp);
	    BIF_RET(AM_no_time_warp);
	}
	case ERTS_SINGLE_TIME_WARP_MODE: {
	    ERTS_DECL_AM(single_time_warp);
	    BIF_RET(AM_single_time_warp);
	}
	case ERTS_MULTI_TIME_WARP_MODE: {
	    ERTS_DECL_AM(multi_time_warp);
	    BIF_RET(AM_multi_time_warp);
	}
	default:
	    ERTS_INTERNAL_ERROR("Invalid time warp mode");
	}
    } else if (BIF_ARG_1 == am_allocated_areas) {
	res = erts_allocated_areas(NULL, NULL, BIF_P);
	BIF_RET(res);
    } else if (BIF_ARG_1 == am_hipe_architecture) {
#if defined(HIPE)
	BIF_RET(hipe_arch_name);
#else
	BIF_RET(am_undefined);
#endif
    } else if (BIF_ARG_1 == am_trace_control_word) {
	BIF_RET(db_get_trace_control_word(BIF_P));
    } else if (ERTS_IS_ATOM_STR("ets_realloc_moves", BIF_ARG_1)) {
 	BIF_RET((erts_ets_realloc_always_moves) ? am_true : am_false);
    } else if (ERTS_IS_ATOM_STR("ets_always_compress", BIF_ARG_1)) {
	BIF_RET((erts_ets_always_compress) ? am_true : am_false);
    } else if (ERTS_IS_ATOM_STR("snifs", BIF_ARG_1)) {
	Uint size = 0;
	Uint *szp;

	szp = &size;
	build_snifs_term(NULL, szp, NIL);
	hp = HAlloc(BIF_P, size);
	res = build_snifs_term(&hp, NULL, NIL);
	BIF_RET(res);
    } else if (BIF_ARG_1 == am_sequential_tracer) {
	ErtsTracer seq_tracer = erts_get_system_seq_tracer();
        val = erts_tracer_to_term(BIF_P, seq_tracer);
	hp = HAlloc(BIF_P, 3);
	res = TUPLE2(hp, am_sequential_tracer, val);
	BIF_RET(res);
    } else if (BIF_ARG_1 == am_garbage_collection){
	Uint val = (Uint) erts_atomic32_read_nob(&erts_max_gen_gcs);
	Eterm tup;
	hp = HAlloc(BIF_P, 3+2 + 3+2 + 3+2 + 3+2);

	tup = TUPLE2(hp, am_fullsweep_after, make_small(val)); hp += 3;
	res = CONS(hp, tup, NIL); hp += 2;

	tup = TUPLE2(hp, am_min_heap_size, make_small(H_MIN_SIZE)); hp += 3;
	res = CONS(hp, tup, res); hp += 2;

	tup = TUPLE2(hp, am_min_bin_vheap_size, make_small(BIN_VH_MIN_SIZE)); hp += 3;
	res = CONS(hp, tup, res); hp += 2;

	tup = TUPLE2(hp, am_max_heap_size, make_small(H_MAX_SIZE)); hp += 3;
	res = CONS(hp, tup, res); hp += 2;

	BIF_RET(res);
    } else if (BIF_ARG_1 == am_fullsweep_after){
	Uint val = (Uint) erts_atomic32_read_nob(&erts_max_gen_gcs);
	hp = HAlloc(BIF_P, 3);
	res = TUPLE2(hp, am_fullsweep_after, make_small(val));
	BIF_RET(res);
    } else if (BIF_ARG_1 == am_min_heap_size) {
	hp = HAlloc(BIF_P, 3);
	res = TUPLE2(hp, am_min_heap_size,make_small(H_MIN_SIZE));
	BIF_RET(res);
    } else if (BIF_ARG_1 == am_max_heap_size) {
        Uint sz = 0;
        erts_max_heap_size_map(H_MAX_SIZE, H_MAX_FLAGS, NULL, &sz);
	hp = HAlloc(BIF_P, sz);
	res = erts_max_heap_size_map(H_MAX_SIZE, H_MAX_FLAGS, &hp, NULL);
	BIF_RET(res);
    } else if (BIF_ARG_1 == am_min_bin_vheap_size) {
	hp = HAlloc(BIF_P, 3);
	res = TUPLE2(hp, am_min_bin_vheap_size,make_small(BIN_VH_MIN_SIZE));
	BIF_RET(res);
    } else if (BIF_ARG_1 == am_process_count) {
	BIF_RET(make_small(erts_ptab_count(&erts_proc)));
    } else if (BIF_ARG_1 == am_process_limit) {
	BIF_RET(make_small(erts_ptab_max(&erts_proc)));
    } else if (BIF_ARG_1 == am_port_count) {
	BIF_RET(make_small(erts_ptab_count(&erts_port)));
    } else if (BIF_ARG_1 == am_port_limit) {
	BIF_RET(make_small(erts_ptab_max(&erts_port)));
    } else if (BIF_ARG_1 == am_info
	       || BIF_ARG_1 == am_procs
	       || BIF_ARG_1 == am_loaded
	       || BIF_ARG_1 == am_dist) {
	erts_dsprintf_buf_t *dsbufp = erts_create_info_dsbuf(0);

	/* Need to be the only thread running... */
	erts_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
        BIF_P->scheduler_data->current_process = NULL;
	erts_thr_progress_block();

	if (BIF_ARG_1 == am_info)
	    info(ERTS_PRINT_DSBUF, (void *) dsbufp);
	else if (BIF_ARG_1 == am_procs)
	    process_info(ERTS_PRINT_DSBUF, (void *) dsbufp);
	else if (BIF_ARG_1 == am_loaded)
	    loaded(ERTS_PRINT_DSBUF, (void *) dsbufp);
	else
	    distribution_info(ERTS_PRINT_DSBUF, (void *) dsbufp);

	erts_thr_progress_unblock();
	erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
       BIF_P->scheduler_data->current_process = BIF_P;

	ASSERT(dsbufp && dsbufp->str);
	res = new_binary(BIF_P, (byte *) dsbufp->str, dsbufp->str_len);
	erts_destroy_info_dsbuf(dsbufp);
	BIF_RET(res);
    } else if (ERTS_IS_ATOM_STR("dist_ctrl", BIF_ARG_1)) {
	DistEntry *dep;
	i = 0;
        erts_rwmtx_rlock(&erts_dist_table_rwmtx);
	for (dep = erts_visible_dist_entries; dep; dep = dep->next) 
	    ++i;
	for (dep = erts_hidden_dist_entries; dep; dep = dep->next)
	    ++i;
	hp = HAlloc(BIF_P,i*(3+2));
	res = NIL;
	for (dep = erts_hidden_dist_entries; dep; dep = dep->next) {
	    Eterm tpl;
	    ASSERT(is_immed(dep->cid));
	    tpl = TUPLE2(hp, dep->sysname, dep->cid);
	    hp +=3;
	    res = CONS(hp, tpl, res);
	    hp += 2;
	}
	for (dep = erts_visible_dist_entries; dep; dep = dep->next) {
	    Eterm tpl;
	    ASSERT(is_immed(dep->cid));
	    tpl = TUPLE2(hp, dep->sysname, dep->cid);
	    hp +=3;
	    res = CONS(hp, tpl, res);
	    hp += 2;
	}
        erts_rwmtx_runlock(&erts_dist_table_rwmtx);
	BIF_RET(res);
    } else if (BIF_ARG_1 == am_system_version) {
	erts_dsprintf_buf_t *dsbufp = erts_create_tmp_dsbuf(0);
	erts_print_system_version(ERTS_PRINT_DSBUF, (void *) dsbufp, BIF_P);
	hp = HAlloc(BIF_P, dsbufp->str_len*2);
	res = buf_to_intlist(&hp, dsbufp->str, dsbufp->str_len, NIL);
	erts_destroy_tmp_dsbuf(dsbufp);
	BIF_RET(res);
    } else if (BIF_ARG_1 == am_system_architecture) {
	hp = HAlloc(BIF_P, 2*(sizeof(ERLANG_ARCHITECTURE)-1));
	BIF_RET(buf_to_intlist(&hp,
			       ERLANG_ARCHITECTURE,
			       sizeof(ERLANG_ARCHITECTURE)-1,
			       NIL));
    } 
    else if (BIF_ARG_1 == am_os_type) {
	BIF_RET(erts_get_global_literal(ERTS_LIT_OS_TYPE));
    }
    else if (BIF_ARG_1 == am_allocator) {
	BIF_RET(erts_allocator_options((void *) BIF_P));
    }
    else if (BIF_ARG_1 == am_thread_pool_size) {
	extern int erts_async_max_threads;
	int n;
	
	n = erts_async_max_threads;
	BIF_RET(make_small(n));
    }
    else if (BIF_ARG_1 == am_alloc_util_allocators) {
	BIF_RET(erts_alloc_util_allocators((void *) BIF_P));
    }
    else if (BIF_ARG_1 == am_os_version) {
	BIF_RET(erts_get_global_literal(ERTS_LIT_OS_VERSION));
    }
    else if (BIF_ARG_1 == am_version) {
	int n = sys_strlen(ERLANG_VERSION);
	hp = HAlloc(BIF_P, ((sizeof ERLANG_VERSION)-1) * 2);
	BIF_RET(buf_to_intlist(&hp, ERLANG_VERSION, n, NIL));
    }
    else if (BIF_ARG_1 == am_machine) {
	int n = sys_strlen(EMULATOR);
	hp = HAlloc(BIF_P, n*2);
	BIF_RET(buf_to_intlist(&hp, EMULATOR, n, NIL));
    }
    else if (BIF_ARG_1 == am_garbage_collection) {
	BIF_RET(am_generational);
#ifdef ERTS_OPCODE_COUNTER_SUPPORT
    } else if (BIF_ARG_1 == am_instruction_counts) {
#ifdef DEBUG
	Eterm *endp;
#endif
	Eterm *hp, **hpp;
	Uint hsz, *hszp;
	int i;

	hpp = NULL;
	hsz = 0;
	hszp = &hsz;

    bld_instruction_counts:

	res = NIL;
	for (i = num_instructions-1; i >= 0; i--) {
	    res = erts_bld_cons(hpp, hszp,
				erts_bld_tuple(hpp, hszp, 2,
					       erts_atom_put((byte *)opc[i].name,
							     sys_strlen(opc[i].name),
							     ERTS_ATOM_ENC_LATIN1,
							     1),
					       erts_bld_uint(hpp, hszp,
							     erts_instr_count[i])),
				res);
	}

	if (!hpp) {
	    hp = HAlloc(BIF_P, hsz);
	    hpp = &hp;
#ifdef DEBUG
	    endp = hp + hsz;
#endif
	    hszp = NULL;
	    goto bld_instruction_counts;
	}

	ASSERT(endp == hp);

	BIF_RET(res);
#endif /* #ifndef ERTS_OPCODE_COUNTER_SUPPORT */
    } else if (BIF_ARG_1 == am_wordsize) {
	return make_small(sizeof(Eterm));
    } else if (BIF_ARG_1 == am_endian) {
#if defined(WORDS_BIGENDIAN)
	return am_big;
#else
	return am_little;
#endif
    } else if (BIF_ARG_1 == am_heap_sizes) {
	return erts_heap_sizes(BIF_P);
    } else if (BIF_ARG_1 == am_heap_type) {
	return am_private;
    } else if (ERTS_IS_ATOM_STR("cpu_topology", BIF_ARG_1)) {
	res = erts_get_cpu_topology_term(BIF_P, am_used);
	BIF_TRAP1(erts_format_cpu_topology_trap, BIF_P, res);
    } else if (ERTS_IS_ATOM_STR("update_cpu_info", BIF_ARG_1)) {
	if (erts_update_cpu_info()) {
	    ERTS_DECL_AM(changed);
	    BIF_RET(AM_changed);
	}
	else {
	    ERTS_DECL_AM(unchanged);
	    BIF_RET(AM_unchanged);
	}
#if defined(__GNUC__) && defined(HAVE_SOLARIS_SPARC_PERFMON)
    } else if (ERTS_IS_ATOM_STR("ultrasparc_read_tick1", BIF_ARG_1)) {
	register unsigned high asm("%l0");
	register unsigned low asm("%l1");

	hp = HAlloc(BIF_P, 5);
	asm volatile (".word 0xa3410000;" /* rd %tick, %l1 */
		      ".word 0xa1347020" /* srlx  %l1, 0x20, %l0 */
		      : "=r" (high), "=r" (low));
	res = TUPLE4(hp, make_small(high >> 16),
		     make_small(high & 0xFFFF),
		     make_small(low >> 16),
		     make_small(low & 0xFFFF));
	BIF_RET(res);
    } else if (ERTS_IS_ATOM_STR("ultrasparc_read_tick2", BIF_ARG_1)) {
	register unsigned high asm("%l0");
	register unsigned low asm("%l1");

	asm volatile (".word 0xa3410000;" /* rd %tick, %l1 */
		      ".word 0xa1347020" /* srlx  %l1, 0x20, %l0 */
		      : "=r" (high), "=r" (low));
	hp = HAlloc(BIF_P, 5);
	res = TUPLE4(hp, make_small(high >> 16),
		     make_small(high & 0xFFFF),
		     make_small(low >> 16),
		     make_small(low & 0xFFFF));
	BIF_RET(res);
    } else if (ERTS_IS_ATOM_STR("ultrasparc_read_pic1", BIF_ARG_1)) {
	register unsigned high asm("%l0");
	register unsigned low asm("%l1");

	hp = HAlloc(BIF_P, 5);
	asm volatile (".word 0xa3444000;" /* rd %asr17, %l1 */
		      ".word 0xa1347020" /* srlx  %l1, 0x20, %l0 */
		      : "=r" (high), "=r" (low));
	res = TUPLE4(hp, make_small(high >> 16),
		     make_small(high & 0xFFFF),
		     make_small(low >> 16),
		     make_small(low & 0xFFFF));
	BIF_RET(res);
    } else if (ERTS_IS_ATOM_STR("ultrasparc_read_pic2", BIF_ARG_1)) {
	register unsigned high asm("%l0");
	register unsigned low asm("%l1");

	asm volatile (".word 0xa3444000;" /* rd %asr17, %l1 */
		      ".word 0xa1347020" /* srlx  %l1, 0x20, %l0 */
		      : "=r" (high), "=r" (low));
	hp = HAlloc(BIF_P, 5);
	res = TUPLE4(hp, make_small(high >> 16),
		     make_small(high & 0xFFFF),
		     make_small(low >> 16),
		     make_small(low & 0xFFFF));
	BIF_RET(res);
#endif
    } else if (BIF_ARG_1 == am_threads) {
	return am_true;
    } else if (BIF_ARG_1 == am_creation) {
        Uint hsz = 0;
        erts_bld_uint(NULL, &hsz, erts_this_node->creation);
        hp = hsz ? HAlloc(BIF_P, hsz) : NULL;
        BIF_RET(erts_bld_uint(&hp, NULL, erts_this_node->creation));
    } else if (BIF_ARG_1 == am_break_ignored) {
      extern int ignore_break;
      if (ignore_break) 
	return am_true; 
      else
	return am_false;
    }
    /* Arguments that are unusual follow ... */
    else if (ERTS_IS_ATOM_STR("logical_processors", BIF_ARG_1)) {
	int no;
	erts_get_logical_processors(&no, NULL, NULL, NULL);
	if (no > 0)
	    BIF_RET(make_small((Uint) no));
	else {
	    DECL_AM(unknown);
	    BIF_RET(AM_unknown);
	}
    }
    else if (ERTS_IS_ATOM_STR("logical_processors_online", BIF_ARG_1)) {
	int no;
	erts_get_logical_processors(NULL, &no, NULL, NULL);
	if (no > 0)
	    BIF_RET(make_small((Uint) no));
	else {
	    DECL_AM(unknown);
	    BIF_RET(AM_unknown);
	}
    }
    else if (ERTS_IS_ATOM_STR("logical_processors_available", BIF_ARG_1)) {
	int no;
	erts_get_logical_processors(NULL, NULL, &no, NULL);
	if (no > 0)
	    BIF_RET(make_small((Uint) no));
	else {
	    DECL_AM(unknown);
	    BIF_RET(AM_unknown);
	}
    }
    else if (ERTS_IS_ATOM_STR("cpu_quota", BIF_ARG_1)) {
	int no;
	erts_get_logical_processors(NULL, NULL, NULL, &no);
	if (no > 0)
	    BIF_RET(make_small((Uint) no));
	else {
	    DECL_AM(unknown);
	    BIF_RET(AM_unknown);
	}
    } else if (ERTS_IS_ATOM_STR("otp_release", BIF_ARG_1)) {
	int n = sizeof(ERLANG_OTP_RELEASE)-1;
	hp = HAlloc(BIF_P, 2*n);
	BIF_RET(buf_to_intlist(&hp, ERLANG_OTP_RELEASE, n, NIL));
    } else if (ERTS_IS_ATOM_STR("driver_version", BIF_ARG_1)) {
	char buf[42];
	int n = erts_snprintf(buf, 42, "%d.%d",
			      ERL_DRV_EXTENDED_MAJOR_VERSION,
			      ERL_DRV_EXTENDED_MINOR_VERSION);
	hp = HAlloc(BIF_P, 2*n);
	BIF_RET(buf_to_intlist(&hp, buf, n, NIL));
    } else if (ERTS_IS_ATOM_STR("nif_version", BIF_ARG_1)) {
	char buf[42];
	int n = erts_snprintf(buf, 42, "%d.%d",
			      ERL_NIF_MAJOR_VERSION,
			      ERL_NIF_MINOR_VERSION);
	hp = HAlloc(BIF_P, 2*n);
	BIF_RET(buf_to_intlist(&hp, buf, n, NIL));
    } else if (ERTS_IS_ATOM_STR("smp_support", BIF_ARG_1)) {
	BIF_RET(am_true);
    } else if (ERTS_IS_ATOM_STR("scheduler_bind_type", BIF_ARG_1)) {
	BIF_RET(erts_bound_schedulers_term(BIF_P));
    } else if (ERTS_IS_ATOM_STR("scheduler_bindings", BIF_ARG_1)) {
	BIF_RET(erts_get_schedulers_binds(BIF_P));
    } else if (ERTS_IS_ATOM_STR("constant_pool_support", BIF_ARG_1)) {
	BIF_RET(am_true);
    } else if (ERTS_IS_ATOM_STR("schedulers", BIF_ARG_1)
	       || ERTS_IS_ATOM_STR("schedulers_total", BIF_ARG_1)) {
	res = make_small(erts_no_schedulers);
	BIF_RET(res);
    } else if (ERTS_IS_ATOM_STR("schedulers_state", BIF_ARG_1)) {
	Eterm *hp;
	Uint total, online, active;
	erts_schedulers_state(&total, &online, &active,
			      NULL, NULL, NULL, NULL, NULL);
	hp = HAlloc(BIF_P, 4);
	res = TUPLE3(hp,
		     make_small(total),
		     make_small(online),
		     make_small(active));
	BIF_RET(res);
    } else if (ERTS_IS_ATOM_STR("schedulers_state", BIF_ARG_1)) {
	Eterm *hp;
	Uint total, online, active;
	erts_schedulers_state(&total, &online, &active,
			      NULL, NULL, NULL, NULL, NULL);
	hp = HAlloc(BIF_P, 4);
	res = TUPLE3(hp,
		     make_small(total),
		     make_small(online),
		     make_small(active));
	BIF_RET(res);
    } else if (ERTS_IS_ATOM_STR("all_schedulers_state", BIF_ARG_1)) {
	Eterm *hp, tpl;
	Uint sz, total, online, active,
	    dirty_cpu_total, dirty_cpu_online, dirty_cpu_active,
	    dirty_io_total, dirty_io_active;
	erts_schedulers_state(&total, &online, &active,
			      &dirty_cpu_total, &dirty_cpu_online, &dirty_cpu_active,
			      &dirty_io_total, &dirty_io_active);

	sz = 2+5;
	if (dirty_cpu_total)
	    sz += 2+5;
	if (dirty_io_total)
	    sz += 2+5;

	hp = HAlloc(BIF_P, sz);

	res = NIL;
	if (dirty_io_total) {
	    tpl = TUPLE4(hp,
			 am_dirty_io,
			 make_small(dirty_io_total),
			 make_small(dirty_io_total),
			 make_small(dirty_io_active));
	    hp += 5;
	    res = CONS(hp, tpl, res);
	    hp += 2;
	}
	if (dirty_cpu_total) {
	    tpl = TUPLE4(hp,
			 am_dirty_cpu,
			 make_small(dirty_cpu_total),
			 make_small(dirty_cpu_online),
			 make_small(dirty_cpu_active));
	    hp += 5;
	    res = CONS(hp, tpl, res);
	    hp += 2;
	}
	tpl = TUPLE4(hp,
		     am_normal,
		     make_small(total),
		     make_small(online),
		     make_small(active));
	hp += 5;
	res = CONS(hp, tpl, res);
	BIF_RET(res);
    } else if (ERTS_IS_ATOM_STR("schedulers_online", BIF_ARG_1)) {
	Uint online;
	erts_schedulers_state(NULL, &online, NULL, NULL, NULL, NULL, NULL, NULL);
	BIF_RET(make_small(online));
    } else if (ERTS_IS_ATOM_STR("schedulers_active", BIF_ARG_1)) {
	Uint active;
	erts_schedulers_state(NULL, NULL, &active, NULL, NULL, NULL, NULL, NULL);
	BIF_RET(make_small(active));
    } else if (ERTS_IS_ATOM_STR("dirty_cpu_schedulers", BIF_ARG_1)) {
	Uint dirty_cpu;
	erts_schedulers_state(NULL, NULL, NULL, &dirty_cpu, NULL, NULL, NULL, NULL);
	BIF_RET(make_small(dirty_cpu));
    } else if (ERTS_IS_ATOM_STR("dirty_cpu_schedulers_online", BIF_ARG_1)) {
	Uint dirty_cpu_onln;
	erts_schedulers_state(NULL, NULL, NULL, NULL, &dirty_cpu_onln, NULL, NULL, NULL);
	BIF_RET(make_small(dirty_cpu_onln));
    } else if (ERTS_IS_ATOM_STR("dirty_io_schedulers", BIF_ARG_1)) {
	Uint dirty_io;
	erts_schedulers_state(NULL, NULL, NULL, NULL, NULL, NULL, &dirty_io, NULL);
	BIF_RET(make_small(dirty_io));
    } else if (ERTS_IS_ATOM_STR("run_queues", BIF_ARG_1)) {
	res = make_small(erts_no_run_queues);
	BIF_RET(res);
    } else if (ERTS_IS_ATOM_STR("port_parallelism", BIF_ARG_1)) {
	res = erts_port_parallelism ? am_true : am_false;
	BIF_RET(res);
    } else if (ERTS_IS_ATOM_STR("c_compiler_used", BIF_ARG_1)) {
	Eterm *hp = NULL;
	Uint sz = 0;
	(void) c_compiler_used(NULL, &sz);
	if (sz)
	    hp = HAlloc(BIF_P, sz);
	BIF_RET(c_compiler_used(&hp, NULL));
    } else if (ERTS_IS_ATOM_STR("stop_memory_trace", BIF_ARG_1)) {
	erts_mtrace_stop();
	BIF_RET(am_true);
    } else if (ERTS_IS_ATOM_STR("context_reductions", BIF_ARG_1)) {
	BIF_RET(make_small(CONTEXT_REDS));
    } else if (ERTS_IS_ATOM_STR("kernel_poll", BIF_ARG_1)) {
#if ERTS_ENABLE_KERNEL_POLL
	BIF_RET(am_true);
#else
	BIF_RET(am_false);
#endif    
    } else if (ERTS_IS_ATOM_STR("lock_checking", BIF_ARG_1)) {
#ifdef ERTS_ENABLE_LOCK_CHECK
	BIF_RET(am_true);
#else
	BIF_RET(am_false);
#endif
    } else if (ERTS_IS_ATOM_STR("lock_counting", BIF_ARG_1)) {
#ifdef ERTS_ENABLE_LOCK_COUNT
	BIF_RET(am_true);
#else
	BIF_RET(am_false);
#endif
    } else if (ERTS_IS_ATOM_STR("debug_compiled", BIF_ARG_1)) {
#ifdef DEBUG
	BIF_RET(am_true);
#else
	BIF_RET(am_false);
#endif
    } else if (ERTS_IS_ATOM_STR("check_io", BIF_ARG_1)) {
	BIF_RET(erts_check_io_info(BIF_P));
    } else if (ERTS_IS_ATOM_STR("multi_scheduling_blockers", BIF_ARG_1)) {
	if (erts_no_schedulers == 1)
	    BIF_RET(NIL);
	else
	    BIF_RET(erts_multi_scheduling_blockers(BIF_P, 0));
    } else if (ERTS_IS_ATOM_STR("normal_multi_scheduling_blockers", BIF_ARG_1)) {
	if (erts_no_schedulers == 1)
	    BIF_RET(NIL);
	else
	    BIF_RET(erts_multi_scheduling_blockers(BIF_P, 1));
    } else if (ERTS_IS_ATOM_STR("modified_timing_level", BIF_ARG_1)) {
	BIF_RET(ERTS_USE_MODIFIED_TIMING()
		? make_small(erts_modified_timing_level)
		: am_undefined);
    } else if (ERTS_IS_ATOM_STR("port_tasks", BIF_ARG_1)) {
	BIF_RET(am_true);
    } else if (ERTS_IS_ATOM_STR("io_thread", BIF_ARG_1)) {
	BIF_RET(am_false);
    } else if (ERTS_IS_ATOM_STR("scheduling_statistics", BIF_ARG_1)) {
	BIF_RET(erts_sched_stat_term(BIF_P, 0));
    } else if (ERTS_IS_ATOM_STR("total_scheduling_statistics", BIF_ARG_1)) {
	BIF_RET(erts_sched_stat_term(BIF_P, 1));
    } else if (ERTS_IS_ATOM_STR("taints", BIF_ARG_1)) {
	BIF_RET(erts_nif_taints(BIF_P));
    } else if (ERTS_IS_ATOM_STR("reader_groups_map", BIF_ARG_1)) {
	BIF_RET(erts_get_reader_groups_map(BIF_P));
    } else if (ERTS_IS_ATOM_STR("decentralized_counter_groups_map", BIF_ARG_1)) {
	BIF_RET(erts_get_decentralized_counter_groups_map(BIF_P));
    } else if (ERTS_IS_ATOM_STR("dist_buf_busy_limit", BIF_ARG_1)) {
	Uint hsz = 0;

 	(void) erts_bld_uint(NULL, &hsz, erts_dist_buf_busy_limit);
	hp = hsz ? HAlloc(BIF_P, hsz) : NULL;
	res = erts_bld_uint(&hp, NULL, erts_dist_buf_busy_limit);
	BIF_RET(res);
    } else if (ERTS_IS_ATOM_STR("delayed_node_table_gc", BIF_ARG_1)) {
	Uint hsz = 0;
	Uint dntgc = erts_delayed_node_table_gc();
	if (dntgc == ERTS_NODE_TAB_DELAY_GC_INFINITY)
	    BIF_RET(am_infinity);
 	(void) erts_bld_uint(NULL, &hsz, dntgc);
	hp = hsz ? HAlloc(BIF_P, hsz) : NULL;
	res = erts_bld_uint(&hp, NULL, dntgc);
	BIF_RET(res);
    } else if (ERTS_IS_ATOM_STR("ethread_info", BIF_ARG_1)) {
	BIF_RET(erts_get_ethread_info(BIF_P));
    }
    else if (ERTS_IS_ATOM_STR("ethread_used_tse", BIF_ARG_1)) {
        Uint64 no = (Uint64) ethr_no_used_tse();
        Uint hsz = 0;
        erts_bld_uint64(NULL, &hsz, no);
        hp = hsz ? HAlloc(BIF_P, hsz) : NULL;
        res = erts_bld_uint64(&hp, NULL, no);
        BIF_RET(res);
    }
    else if (ERTS_IS_ATOM_STR("emu_args", BIF_ARG_1)) {
	BIF_RET(erts_get_emu_args(BIF_P));
    }
    else if (ERTS_IS_ATOM_STR("beam_jump_table", BIF_ARG_1)) {
	BIF_RET(erts_beam_jump_table() ? am_true : am_false);
    }
    else if (ERTS_IS_ATOM_STR("dynamic_trace", BIF_ARG_1)) {
#if defined(USE_DTRACE)
	DECL_AM(dtrace);
	BIF_RET(AM_dtrace);
#elif defined(USE_SYSTEMTAP)
	DECL_AM(systemtap);
	BIF_RET(AM_systemtap);
#elif defined(USE_LTTNG)
	DECL_AM(lttng);
	BIF_RET(AM_lttng);
#else
	BIF_RET(am_none);
#endif
    }	    
    else if (ERTS_IS_ATOM_STR("dynamic_trace_probes", BIF_ARG_1)) {
#if defined(USE_VM_PROBES)
	BIF_RET(am_true);
#else
	BIF_RET(am_false);
#endif	
    }
    else if (ERTS_IS_ATOM_STR("thread_progress", BIF_ARG_1)) {
	erts_thr_progress_dbg_print_state();
	BIF_RET(am_true);
    }
    else if (BIF_ARG_1 == am_message_queue_data) {
	switch (erts_default_spo_flags & (SPO_ON_HEAP_MSGQ|SPO_OFF_HEAP_MSGQ)) {
	case SPO_OFF_HEAP_MSGQ:
	    BIF_RET(am_off_heap);
	case SPO_ON_HEAP_MSGQ:
	    BIF_RET(am_on_heap);
	default:
	    ERTS_INTERNAL_ERROR("Inconsistent message queue management state");
	    BIF_RET(am_error);
	}
    }
    else if (ERTS_IS_ATOM_STR("compile_info",BIF_ARG_1)) {
	Uint  sz;
	Eterm res = NIL, tup, text;
	Eterm *hp = HAlloc(BIF_P, 3*(2 + 3) + /* three 2-tuples and three cons */
		2*(sys_strlen(erts_build_flags_CONFIG_H) +
		   sys_strlen(erts_build_flags_CFLAGS) +
		   sys_strlen(erts_build_flags_LDFLAGS)));

	sz   = sys_strlen(erts_build_flags_CONFIG_H);
	text = buf_to_intlist(&hp, erts_build_flags_CONFIG_H, sz, NIL);
	tup  = TUPLE2(hp, am_config_h, text); hp += 3;
	res  = CONS(hp, tup, res); hp += 2;

	sz   = sys_strlen(erts_build_flags_CFLAGS);
	text = buf_to_intlist(&hp, erts_build_flags_CFLAGS, sz, NIL);
	tup  = TUPLE2(hp, am_cflags, text); hp += 3;
	res  = CONS(hp, tup, res); hp += 2;

	sz   = sys_strlen(erts_build_flags_LDFLAGS);
	text = buf_to_intlist(&hp, erts_build_flags_LDFLAGS, sz, NIL);
	tup  = TUPLE2(hp, am_ldflags, text); hp += 3;
	res  = CONS(hp, tup, res); hp += 2;

	BIF_RET(res);
    }
    else if (ERTS_IS_ATOM_STR("ets_limit",BIF_ARG_1)) {
        BIF_RET(make_small(erts_db_get_max_tabs()));
    }
    else if (ERTS_IS_ATOM_STR("ets_count",BIF_ARG_1)) {
        BIF_RET(make_small(erts_ets_table_count()));
    }
    else if (ERTS_IS_ATOM_STR("atom_limit",BIF_ARG_1)) {
        BIF_RET(make_small(erts_get_atom_limit()));
    }
    else if (ERTS_IS_ATOM_STR("atom_count",BIF_ARG_1)) {
        BIF_RET(make_small(atom_table_size()));
    }
    else if (ERTS_IS_ATOM_STR("tolerant_timeofday",BIF_ARG_1)) {
	if (erts_has_time_correction()
	    && erts_time_offset_state() == ERTS_TIME_OFFSET_FINAL) {
	    BIF_RET(am_enabled);
	}
	BIF_RET(am_disabled);
    }
    else if (ERTS_IS_ATOM_STR("eager_check_io",BIF_ARG_1)) {
	BIF_RET(am_true);
    }
    else if (ERTS_IS_ATOM_STR("literal_test",BIF_ARG_1)) {
#ifdef ERTS_HAVE_IS_IN_LITERAL_RANGE
#ifdef ARCH_64
	DECL_AM(range);
	BIF_RET(AM_range);
#else /* ARCH_32 */
	DECL_AM(range_bitmask);
	BIF_RET(AM_range_bitmask);
#endif /* ARCH_32 */
#else  /* ! ERTS_HAVE_IS_IN_LITERAL_RANGE */
	DECL_AM(tag);
	BIF_RET(AM_tag);
#endif
    } else if (ERTS_IS_ATOM_STR("system_logger", BIF_ARG_1)) {
        BIF_RET(erts_get_system_logger());
    }

    BIF_ERROR(BIF_P, BADARG);
}