BIF_RETTYPE bit_size_1(BIF_ALIST_1) { Uint low_bits; Uint bytesize; Uint high_bits; if (is_binary(BIF_ARG_1)) { bytesize = binary_size(BIF_ARG_1); high_bits = bytesize >> ((sizeof(Uint) * 8)-3); low_bits = (bytesize << 3) + binary_bitsize(BIF_ARG_1); if (high_bits == 0) { if (IS_USMALL(0,low_bits)) { BIF_RET(make_small(low_bits)); } else { Eterm* hp = HAlloc(BIF_P, BIG_UINT_HEAP_SIZE); BIF_RET(uint_to_big(low_bits, hp)); } } else { Uint sz = BIG_UINT_HEAP_SIZE+1; Eterm* hp = HAlloc(BIF_P, sz); hp[0] = make_pos_bignum_header(sz-1); BIG_DIGIT(hp,0) = low_bits; BIG_DIGIT(hp,1) = high_bits; BIF_RET(make_big(hp)); } } else {
BIF_RETTYPE prepare_loading_2(BIF_ALIST_2) { byte* temp_alloc = NULL; byte* code; Uint sz; Binary* magic; Eterm reason; Eterm* hp; Eterm res; if (is_not_atom(BIF_ARG_1)) { error: erts_free_aligned_binary_bytes(temp_alloc); BIF_ERROR(BIF_P, BADARG); } if ((code = erts_get_aligned_binary_bytes(BIF_ARG_2, &temp_alloc)) == NULL) { goto error; } magic = erts_alloc_loader_state(); sz = binary_size(BIF_ARG_2); reason = erts_prepare_loading(magic, BIF_P, BIF_P->group_leader, &BIF_ARG_1, code, sz); erts_free_aligned_binary_bytes(temp_alloc); if (reason != NIL) { hp = HAlloc(BIF_P, 3); res = TUPLE2(hp, am_error, reason); BIF_RET(res); } hp = HAlloc(BIF_P, PROC_BIN_SIZE); res = erts_mk_magic_binary_term(&hp, &MSO(BIF_P), magic); erts_refc_dec(&magic->refc, 1); BIF_RET(res); }
static Eterm pd_hash_get_keys(Process *p, Eterm value) { Eterm *hp; Eterm res = NIL; ProcDict *pd = p->dictionary; unsigned int i, num; Eterm tmp, tmp2; if (pd == NULL) { return res; } num = HASH_RANGE(pd); for (i = 0; i < num; ++i) { tmp = ARRAY_GET(pd, i); if (is_boxed(tmp)) { ASSERT(is_tuple(tmp)); if (EQ(tuple_val(tmp)[2], value)) { hp = HAlloc(p, 2); res = CONS(hp, tuple_val(tmp)[1], res); } } else if (is_list(tmp)) { while (tmp != NIL) { tmp2 = TCAR(tmp); if (EQ(tuple_val(tmp2)[2], value)) { hp = HAlloc(p, 2); res = CONS(hp, tuple_val(tmp2)[1], res); } tmp = TCDR(tmp); } } } return res; }
BIF_RETTYPE abs_1(BIF_ALIST_1) { Eterm res; Sint i0, i; Eterm* hp; /* integer arguments */ if (is_small(BIF_ARG_1)) { i0 = signed_val(BIF_ARG_1); i = ERTS_SMALL_ABS(i0); if (i0 == MIN_SMALL) { hp = HAlloc(BIF_P, BIG_UINT_HEAP_SIZE); BIF_RET(uint_to_big(i, hp)); } else { BIF_RET(make_small(i)); } } else if (is_big(BIF_ARG_1)) { if (!big_sign(BIF_ARG_1)) { BIF_RET(BIF_ARG_1); } else { int sz = big_arity(BIF_ARG_1) + 1; Uint* x; hp = HAlloc(BIF_P, sz); /* See note at beginning of file */ sz--; res = make_big(hp); x = big_val(BIF_ARG_1); *hp++ = make_pos_bignum_header(sz); x++; /* skip thing */ while(sz--) *hp++ = *x++; BIF_RET(res); } } else if (is_float(BIF_ARG_1)) { FloatDef f; GET_DOUBLE(BIF_ARG_1, f); if (f.fd < 0.0) { hp = HAlloc(BIF_P, FLOAT_SIZE_OBJECT); f.fd = fabs(f.fd); res = make_float(hp); PUT_DOUBLE(f, hp); BIF_RET(res); } else BIF_RET(BIF_ARG_1); } BIF_ERROR(BIF_P, BADARG); }
BIF_RETTYPE append_2(BIF_ALIST_2) { Eterm list; Eterm copy; Eterm last; size_t need; Eterm* hp; int i; if ((i = list_length(BIF_ARG_1)) < 0) { BIF_ERROR(BIF_P, BADARG); } if (i == 0) { BIF_RET(BIF_ARG_2); } else if (is_nil(BIF_ARG_2)) { BIF_RET(BIF_ARG_1); } need = 2*i; hp = HAlloc(BIF_P, need); list = BIF_ARG_1; copy = last = CONS(hp, CAR(list_val(list)), make_list(hp+2)); list = CDR(list_val(list)); hp += 2; i--; while(i--) { Eterm* listp = list_val(list); last = CONS(hp, CAR(listp), make_list(hp+2)); list = CDR(listp); hp += 2; } CDR(list_val(last)) = BIF_ARG_2; BIF_RET(copy); }
BIF_RETTYPE float_1(BIF_ALIST_1) { Eterm res; Eterm* hp; FloatDef f; /* check args */ if (is_not_integer(BIF_ARG_1)) { if (is_float(BIF_ARG_1)) { BIF_RET(BIF_ARG_1); } else { badarg: BIF_ERROR(BIF_P, BADARG); } } if (is_small(BIF_ARG_1)) { Sint i = signed_val(BIF_ARG_1); f.fd = i; /* use "C"'s auto casting */ } else if (big_to_double(BIF_ARG_1, &f.fd) < 0) { goto badarg; } hp = HAlloc(BIF_P, FLOAT_SIZE_OBJECT); res = make_float(hp); PUT_DOUBLE(f, hp); BIF_RET(res); }
BIF_RETTYPE hipe_bifs_shared_gc_info_0(BIF_ALIST_0) { #ifdef __BENCHMARK__ #if !(defined(BM_COUNTERS)) Uint minor_global_gc = 0; Uint major_global_gc = 0; #endif #ifndef BM_HEAP_SIZES Uint max_used_global_heap = 0; Uint max_allocated_global_heap = 0; #endif Eterm *hp; Uint tmp_used_heap = 0; Uint tmp_allocated_heap = 0; hp = HAlloc(BIF_P, 7); BIF_RET(TUPLE6(hp, make_small((uint)minor_global_gc), make_small((uint)major_global_gc), make_small(tmp_used_heap), make_small(tmp_allocated_heap), make_small(max_used_global_heap), make_small(max_allocated_global_heap))); #else BIF_RET(am_false); #endif }
Eterm reverse_1(ErlProcess* p, Eterm* reg, UInt live) { UInt n = 0; Eterm list = reg[0]; //debug("lists:reverse/1\n"); //debug_term(list); //debug("\n"); while(is_list(list)) { n++; list = CDR(list_val(list)); } Eterm* hp = HAlloc(p, 2*n, live); Eterm result = NIL; list = reg[0]; while(is_list(list)) { Eterm* pair = list_val(list); result = CONS(hp, CAR(pair), result); list = CDR(pair); hp += 2; } return result; }
Eterm erts_preloaded(Process* p) { Eterm previous; int j; int need; Eterm mod; Eterm* hp; char* name; const Preload *preload = sys_preloaded(); j = 0; while (preload[j].name != NULL) { j++; } previous = NIL; need = 2*j; hp = HAlloc(p, need); j = 0; while ((name = preload[j].name) != NULL) { mod = am_atom_put(name, sys_strlen(name)); previous = CONS(hp, mod, previous); hp += 2; j++; } return previous; }
BIF_RETTYPE loaded_0(BIF_ALIST_0) { ErtsCodeIndex code_ix = erts_active_code_ix(); Module* modp; Eterm previous = NIL; Eterm* hp; int i; int j = 0; for (i = 0; i < module_code_size(code_ix); i++) { if ((modp = module_code(i, code_ix)) != NULL && ((modp->curr.code_length != 0) || (modp->old.code_length != 0))) { j++; } } if (j > 0) { hp = HAlloc(BIF_P, j*2); for (i = 0; i < module_code_size(code_ix); i++) { if ((modp=module_code(i,code_ix)) != NULL && ((modp->curr.code_length != 0) || (modp->old.code_length != 0))) { previous = CONS(hp, make_atom(modp->module), previous); hp += 2; } } } BIF_RET(previous); }
BIF_RETTYPE port_get_data_1(BIF_ALIST_1) { /* * This is not a signal. See comment above. */ Eterm res; erts_aint_t data; Port* prt; prt = data_lookup_port(BIF_P, BIF_ARG_1); if (!prt) BIF_ERROR(BIF_P, BADARG); data = erts_smp_atomic_read_ddrb(&prt->data); if (data == (erts_aint_t)NULL) BIF_ERROR(BIF_P, BADARG); /* Port terminated by racing thread */ if ((data & 0x3) != 0) { res = (Eterm) (UWord) data; ASSERT(is_immed(res)); } else { ErtsPortDataHeap *pdhp = (ErtsPortDataHeap *) data; Eterm *hp = HAlloc(BIF_P, pdhp->hsize); res = copy_struct(pdhp->data, pdhp->hsize, &hp, &MSO(BIF_P)); } BIF_RET(res); }
BIF_RETTYPE loaded_0(BIF_ALIST_0) { Eterm previous = NIL; Eterm* hp; int i; int j = 0; for (i = 0; i < module_code_size(); i++) { if (module_code(i) != NULL && ((module_code(i)->code_length != 0) || (module_code(i)->old_code_length != 0))) { j++; } } if (j > 0) { hp = HAlloc(BIF_P, j*2); for (i = 0; i < module_code_size(); i++) { if (module_code(i) != NULL && ((module_code(i)->code_length != 0) || (module_code(i)->old_code_length != 0))) { previous = CONS(hp, make_atom(module_code(i)->module), previous); hp += 2; } } } BIF_RET(previous); }
BIF_RETTYPE hipe_bifs_message_info_0(BIF_ALIST_0) { #ifdef __BENCHMARK__ Eterm *hp; #ifndef BM_COUNTERS unsigned long messages_sent = 0; unsigned long messages_copied = 0; unsigned long messages_ego = 0; #endif #ifndef BM_MESSAGE_SIZES unsigned long words_sent = 0; unsigned long words_copied = 0; unsigned long words_prealloc = 0; #endif hp = HAlloc(BIF_P, 7); BIF_RET(TUPLE6(hp, make_small(messages_sent), make_small(messages_copied), make_small(messages_ego), make_small(words_sent), make_small(words_copied), make_small(words_prealloc))); #else BIF_RET(am_false); #endif }
static int http_request_erl(void* arg, const http_atom_t* meth, const char* meth_ptr, int meth_len, const PacketHttpURI* uri, int major, int minor) { struct packet_callback_args* pca = (struct packet_callback_args*) arg; Eterm meth_term, uri_term, ver_term; Uint sz = 0; Uint* szp = &sz; Eterm* hp; Eterm** hpp = NULL; /* {http_request,Meth,Uri,Version} */ for (;;) { meth_term = (meth!=NULL) ? meth->atom : http_bld_string(pca, hpp, szp, meth_ptr, meth_len); uri_term = http_bld_uri(pca, hpp, szp, uri); ver_term = erts_bld_tuple(hpp, szp, 2, make_small(major), make_small(minor)); pca->res = erts_bld_tuple(hpp, szp, 4, am_http_request, meth_term, uri_term, ver_term); if (hpp != NULL) break; hpp = &hp; hp = HAlloc(pca->p, sz); szp = NULL; } return 1; }
BIF_RETTYPE hipe_bifs_gc_info_0(BIF_ALIST_0) { #ifdef __BENCHMARK__ #ifndef BM_COUNTERS Uint minor_gc = 0; Uint major_gc = 0; #endif #ifndef BM_HEAP_SIZES Uint max_used_heap = 0; Uint max_allocated_heap = 0; #endif Eterm *hp; Uint used_heap = (BIF_P->htop - BIF_P->heap) + (OLD_HTOP(BIF_P) - OLD_HEAP(BIF_P)) + MBUF_SIZE(BIF_P); Uint alloc_heap = (BIF_P->hend - BIF_P->heap) + (OLD_HEND(BIF_P) - OLD_HEAP(BIF_P)) + MBUF_SIZE(BIF_P); hp = HAlloc(BIF_P, 7); BIF_RET(TUPLE6(hp, make_small((Uint)minor_gc), make_small((Uint)major_gc), make_small((Uint)used_heap), make_small((Uint)alloc_heap), make_small(max_used_heap), make_small(max_allocated_heap))); #else BIF_RET(am_false); #endif }
static Eterm math_call_1(Process* p, double (*func)(double), Eterm arg1) { FloatDef a1; Eterm res; Eterm* hp; ERTS_FP_CHECK_INIT(p); if (is_float(arg1)) { GET_DOUBLE(arg1, a1); } else if (is_small(arg1)) { a1.fd = signed_val(arg1); } else if (is_big(arg1)) { if (big_to_double(arg1, &a1.fd) < 0) { badarith: p->freason = BADARITH; return THE_NON_VALUE; } } else { p->freason = BADARG; return THE_NON_VALUE; } a1.fd = (*func)(a1.fd); ERTS_FP_ERROR_THOROUGH(p, a1.fd, goto badarith); hp = HAlloc(p, FLOAT_SIZE_OBJECT); res = make_float(hp); PUT_DOUBLE(a1, hp); return res; }
Eterm hipe_build_stacktrace(Process *p, struct StackTrace *s) { int depth, i; Uint heap_size; Eterm *hp, *hp_end, mfa, m, f, head, *next_p, next; const void *ra; unsigned int a; depth = s->depth; if (depth < 1) return NIL; heap_size = 6 * depth; /* each [{M,F,A}|_] is 2+4 == 6 words */ hp = HAlloc(p, heap_size); hp_end = hp + heap_size; head = NIL; next_p = &head; for (i = 0; i < depth; ++i) { ra = (const void*)s->trace[i]; if (!hipe_find_mfa_from_ra(ra, &m, &f, &a)) continue; mfa = TUPLE3(hp, m, f, make_small(a)); hp += 4; next = CONS(hp, mfa, NIL); *next_p = next; next_p = &CDR(list_val(next)); hp += 2; } HRelease(p, hp_end, hp); return head; }
static Eterm pd_hash_get_all(Process *p, ProcDict *pd) { Eterm* hp; Eterm res = NIL; Eterm tmp, tmp2; unsigned int i; unsigned int num; if (pd == NULL) { return res; } num = HASH_RANGE(pd); hp = HAlloc(p, pd->numElements * 2); for (i = 0; i < num; ++i) { tmp = ARRAY_GET(pd, i); if (is_boxed(tmp)) { ASSERT(is_tuple(tmp)); res = CONS(hp, tmp, res); hp += 2; } else if (is_list(tmp)) { while (tmp != NIL) { tmp2 = TCAR(tmp); res = CONS(hp, tmp2, res); hp += 2; tmp = TCDR(tmp); } } } return res; }
static Eterm load_nif_error(Process* p, const char* atom, const char* format, ...) { erts_dsprintf_buf_t* dsbufp = erts_create_tmp_dsbuf(0); Eterm ret; Eterm* hp; Eterm** hpp = NULL; Uint sz = 0; Uint* szp = &sz; va_list arglist; va_start(arglist, format); erts_vdsprintf(dsbufp, format, arglist); va_end(arglist); for (;;) { Eterm txt = erts_bld_string_n(hpp, &sz, dsbufp->str, dsbufp->str_len); ret = erts_bld_tuple(hpp, szp, 2, am_error, erts_bld_tuple(hpp, szp, 2, mkatom(atom), txt)); if (hpp != NULL) { break; } hp = HAlloc(p,sz); hpp = &hp; szp = NULL; } erts_destroy_tmp_dsbuf(dsbufp); return ret; }
Eterm erts_get_node_and_dist_references(struct process *proc) { Uint *hp; Uint size; Eterm res; #ifdef DEBUG Uint *endp; #endif erts_smp_proc_unlock(proc, ERTS_PROC_LOCK_MAIN); erts_smp_block_system(0); /* No need to lock any thing since we are alone... */ if (references_atoms_need_init) { INIT_AM(heap); INIT_AM(link); INIT_AM(monitor); INIT_AM(process); INIT_AM(port); INIT_AM(ets); INIT_AM(binary); INIT_AM(match_spec); INIT_AM(control); INIT_AM(dist); INIT_AM(node); INIT_AM(dist_references); INIT_AM(node_references); INIT_AM(timer); INIT_AM(system); #ifdef HYBRID INIT_AM(processes); #endif references_atoms_need_init = 0; } setup_reference_table(); /* Get term size */ size = 0; (void) reference_table_term(NULL, &size); hp = HAlloc(proc, size); #ifdef DEBUG ASSERT(size > 0); endp = hp + size; #endif /* Write term */ res = reference_table_term(&hp, NULL); ASSERT(endp == hp); delete_reference_table(); erts_smp_release_system(); erts_smp_proc_lock(proc, ERTS_PROC_LOCK_MAIN); return res; }
static Eterm build_load_error(Process *p, int code) { int need = load_error_need(code); Eterm *hp = NULL; ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(p)); if (need) { hp = HAlloc(p,need); } return build_load_error_hp(hp,code); }
static void os_getenv_foreach(Process *process, Eterm *result, Eterm key, Eterm value) { Eterm kvp_term, *hp; hp = HAlloc(process, 5); kvp_term = TUPLE2(hp, key, value); hp += 3; (*result) = CONS(hp, kvp_term, (*result)); }
/* return a timestamp */ BIF_RETTYPE os_timestamp_0(BIF_ALIST_0) { Uint megasec, sec, microsec; Eterm* hp; get_sys_now(&megasec, &sec, µsec); hp = HAlloc(BIF_P, 4); BIF_RET(TUPLE3(hp, make_small(megasec), make_small(sec), make_small(microsec))); }
static Eterm alloc_trap_data(Process* c_p) { Binary* mbp = erts_create_magic_binary(sizeof(TrapData), cleanup_trap_data); Eterm* hp; hp = HAlloc(c_p, ERTS_MAGIC_REF_THING_SIZE); return erts_mk_magic_ref(&hp, &MSO(c_p), mbp); }
BIF_RETTYPE os_getpid_0(BIF_ALIST_0) { char pid_string[21]; /* enough for a 64 bit number */ int n; Eterm* hp; sys_get_pid(pid_string, sizeof(pid_string)); /* In sys.c */ n = sys_strlen(pid_string); hp = HAlloc(BIF_P, n*2); BIF_RET(buf_to_intlist(&hp, pid_string, n, NIL)); }
BIF_RETTYPE registered_0(BIF_ALIST_0) { int i; Eterm res; Uint need; Eterm* hp; HashBucket **bucket; #ifdef ERTS_SMP ErtsProcLocks proc_locks = ERTS_PROC_LOCK_MAIN; ERTS_SMP_CHK_HAVE_ONLY_MAIN_PROC_LOCK(BIF_P); reg_safe_read_lock(BIF_P, &proc_locks); if (!proc_locks) erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); #endif bucket = process_reg.bucket; /* work out how much heap we need & maybe garb, by scanning through the registered process table */ need = 0; for (i = 0; i < process_reg.size; i++) { HashBucket *b = bucket[i]; while (b != NULL) { need += 2; b = b->next; } } if (need == 0) { reg_read_unlock(); BIF_RET(NIL); } hp = HAlloc(BIF_P, need); /* scan through again and make the list */ res = NIL; for (i = 0; i < process_reg.size; i++) { HashBucket *b = bucket[i]; while (b != NULL) { RegProc *reg = (RegProc *) b; res = CONS(hp, reg->name, res); hp += 2; b = b->next; } } reg_read_unlock(); BIF_RET(res); }
int erts_is_time_break(Process *p, BeamInstr *pc, Eterm *retval) { Uint i, ix; bp_time_hash_t hash; Uint size; Eterm *hp, t; bp_data_time_item_t *item = NULL; BpDataTime *bdt = (BpDataTime *) is_break(pc, (BeamInstr) BeamOp(op_i_time_breakpoint)); if (bdt) { if (retval) { /* collect all hashes to one hash */ bp_hash_init(&hash, 64); /* foreach threadspecific hash */ for (i = 0; i < bdt->n; i++) { bp_data_time_item_t *sitem; /* foreach hash bucket not NIL*/ for(ix = 0; ix < bdt->hash[i].n; ix++) { item = &(bdt->hash[i].item[ix]); if (item->pid != NIL) { sitem = bp_hash_get(&hash, item); if (sitem) { BP_TIME_ADD(sitem, item); } else { bp_hash_put(&hash, item); } } } } /* *retval should be NIL or term from previous bif in export entry */ if (hash.used > 0) { size = (5 + 2)*hash.used; hp = HAlloc(p, size); for(ix = 0; ix < hash.n; ix++) { item = &(hash.item[ix]); if (item->pid != NIL) { t = TUPLE4(hp, item->pid, make_small(item->count), make_small(item->s_time), make_small(item->us_time)); hp += 5; *retval = CONS(hp, t, *retval); hp += 2; } } } bp_hash_delete(&hash); } return !0; } return 0; }
Eterm os_getpid_0(Process* p) { char pid_string[21]; /* enough for a 64 bit number */ int n; Eterm* hp; sys_get_pid(pid_string); /* In sys.c */ n = sys_strlen(pid_string); hp = HAlloc(p, n*2); BIF_RET(buf_to_intlist(&hp, pid_string, n, NIL)); }
Eterm os_getenv_1(Process* p, Eterm key) { Eterm str; int len, res; char *key_str, *val; char buf[1024]; size_t val_size = sizeof(buf); len = is_string(key); if (!len) { BIF_ERROR(p, BADARG); } /* Leave at least one byte in buf for value */ key_str = len < sizeof(buf)-2 ? &buf[0] : erts_alloc(ERTS_ALC_T_TMP, len+1); if (intlist_to_buf(key, key_str, len) != len) erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__); key_str[len] = '\0'; if (key_str != &buf[0]) val = &buf[0]; else { val_size -= len + 1; val = &buf[len + 1]; } res = erts_sys_getenv(key_str, val, &val_size); if (res < 0) { no_var: str = am_false; } else { Eterm* hp; if (res > 0) { val = erts_alloc(ERTS_ALC_T_TMP, val_size); while (1) { res = erts_sys_getenv(key_str, val, &val_size); if (res == 0) break; else if (res < 0) goto no_var; else val = erts_realloc(ERTS_ALC_T_TMP, val, val_size); } } if (val_size) hp = HAlloc(p, val_size*2); str = buf_to_intlist(&hp, val, val_size, NIL); } if (key_str != &buf[0]) erts_free(ERTS_ALC_T_TMP, key_str); if (val < &buf[0] || &buf[sizeof(buf)-1] < val) erts_free(ERTS_ALC_T_TMP, val); BIF_RET(str); }
static ERTS_INLINE Eterm unique_monotonic_integer_bif(Process *c_p, int positive) { Uint64 raw; Uint hsz; Eterm *hp; raw = get_raw_unique_monotonic_integer(); hsz = get_unique_monotonic_integer_heap_size(raw, positive); hp = hsz ? HAlloc(c_p, hsz) : NULL; return make_unique_monotonic_integer_value(hp, hsz, raw, positive); }