1091
1088
BIF_RETTYPE hibernate_3(BIF_ALIST_3)
1094
* hibernate/3 is implemented as an instruction; therefore
1095
* this function will never be called.
1091
* hibernate/3 is usually translated to an instruction; therefore
1092
* this function is only called from HiPE or when the call could not
1097
BIF_ERROR(BIF_P, BADARG);
1097
if (erts_hibernate(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3, reg)) {
1099
* If hibernate succeeded, TRAP. The process will be suspended
1100
* if status is P_WAITING or continue (if any message was in the queue).
1102
BIF_TRAP_CODE_PTR_(BIF_P, BIF_P->i);
1104
return THE_NON_VALUE;
1100
1107
/**********************************************************************/
1102
BIF_RETTYPE get_stacktrace_0(Process* p)
1109
BIF_RETTYPE get_stacktrace_0(BIF_ALIST_0)
1104
Eterm t = build_stacktrace(p, p->ftrace);
1111
Eterm t = build_stacktrace(BIF_P, BIF_P->ftrace);
1123
1130
* in the stacktrace.
1126
BIF_RETTYPE error_2(Process* p, Eterm value, Eterm args)
1133
BIF_RETTYPE error_2(BIF_ALIST_2)
1128
Eterm* hp = HAlloc(p, 3);
1135
Eterm* hp = HAlloc(BIF_P, 3);
1130
p->fvalue = TUPLE2(hp, value, args);
1131
BIF_ERROR(p, EXC_ERROR_2);
1137
BIF_P->fvalue = TUPLE2(hp, BIF_ARG_1, BIF_ARG_2);
1138
BIF_ERROR(BIF_P, EXC_ERROR_2);
1134
1141
/**********************************************************************/
1151
1158
* It is useful in stub functions for NIFs.
1154
BIF_RETTYPE nif_error_2(Process* p, Eterm value, Eterm args)
1161
BIF_RETTYPE nif_error_2(BIF_ALIST_2)
1156
Eterm* hp = HAlloc(p, 3);
1163
Eterm* hp = HAlloc(BIF_P, 3);
1158
p->fvalue = TUPLE2(hp, value, args);
1159
BIF_ERROR(p, EXC_ERROR_2);
1165
BIF_P->fvalue = TUPLE2(hp, BIF_ARG_1, BIF_ARG_2);
1166
BIF_ERROR(BIF_P, EXC_ERROR_2);
1162
1169
/**********************************************************************/
1175
1182
* If there is an error in the argument format,
1176
1183
* return the atom 'badarg' instead.
1179
raise_3(Process *c_p, Eterm class, Eterm value, Eterm stacktrace) {
1185
BIF_RETTYPE raise_3(BIF_ALIST_3)
1187
Process *c_p = BIF_P;
1188
Eterm class = BIF_ARG_1;
1189
Eterm value = BIF_ARG_2;
1190
Eterm stacktrace = BIF_ARG_3;
1181
1192
Eterm l, *hp, *hp_end, *tp;
1182
1193
int depth, cnt;
1184
1196
struct StackTrace *s;
1186
1198
if (class == am_error) {
1187
1199
c_p->fvalue = value;
1188
1200
reason = EXC_ERROR;
1198
1210
/* Check syntax of stacktrace, and count depth.
1199
1211
* Accept anything that can be returned from erlang:get_stacktrace/0,
1200
1212
* as well as a 2-tuple with a fun as first element that the
1201
* error_handler may need to give us.
1213
* error_handler may need to give us. Also allow old-style
1203
1216
for (l = stacktrace, depth = 0;
1205
1218
l = CDR(list_val(l)), depth++) {
1206
1219
Eterm t = CAR(list_val(l));
1220
Eterm location = NIL;
1208
1222
if (is_not_tuple(t)) goto error;
1209
1223
tp = tuple_val(t);
1210
arity = arityval(tp[0]);
1211
if ((arity == 3) && is_atom(tp[1]) && is_atom(tp[2])) continue;
1212
if ((arity == 2) && is_fun(tp[1])) continue;
1224
switch (arityval(tp[0])) {
1227
if (is_fun(tp[1])) {
1236
* {Fun,Args,Location}
1239
if (is_fun(tp[1])) {
1241
} else if (is_atom(tp[1]) && is_atom(tp[2])) {
1248
if (!(is_atom(tp[1]) && is_atom(tp[2]))) {
1256
if (is_not_list(location) && is_not_nil(location)) {
1215
1260
if (is_not_nil(l)) goto error;
1217
1262
/* Create stacktrace and store */
1218
if (depth <= erts_backtrace_depth) {
1263
if (erts_backtrace_depth < depth) {
1264
depth = erts_backtrace_depth;
1271
/* No need to copy the stacktrace */
1220
1273
c_p->ftrace = stacktrace;
1222
cnt = depth = erts_backtrace_depth;
1225
1276
tp = &c_p->ftrace;
1226
1277
sz = (offsetof(struct StackTrace, trace) + sizeof(Eterm) - 1)
1227
1278
/ sizeof(Eterm);
1228
hp = HAlloc(c_p, sz + 2*(cnt + 1));
1229
hp_end = hp + sz + 2*(cnt + 1);
1279
hp = HAlloc(c_p, sz + (2+6)*(cnt + 1));
1280
hp_end = hp + sz + (2+6)*(cnt + 1);
1230
1281
s = (struct StackTrace *) hp;
1231
1282
s->header = make_neg_bignum_header(sz - 1);
1232
1283
s->freason = reason;
1234
1285
s->current = NULL;
1238
1291
/* Copy list up to depth */
1239
1292
for (cnt = 0, l = stacktrace;
1241
1294
cnt++, l = CDR(list_val(l))) {
1242
1299
ASSERT(*tp == NIL);
1243
*tp = CONS(hp, CAR(list_val(l)), *tp);
1300
t = CAR(list_val(l));
1302
arity = arityval(tpp[0]);
1304
t = TUPLE3(hp, tpp[1], tpp[2], NIL);
1306
} else if (arity == 3 && is_atom(tpp[1])) {
1307
t = TUPLE4(hp, tpp[1], tpp[2], tpp[3], NIL);
1310
*tp = CONS(hp, t, *tp);
1244
1311
tp = &CDR(list_val(*tp));
2159
2235
/**********************************************************************/
2160
2236
/* return the size of an I/O list */
2239
accumulate(Eterm acc, Uint size)
2241
if (is_non_value(acc)) {
2243
* There is no pre-existing accumulator. Allocate a
2244
* bignum buffer with one extra word to be used if
2245
* the bignum grows in the future.
2247
Eterm* hp = (Eterm *) erts_alloc(ERTS_ALC_T_TEMP_TERM,
2248
(BIG_UINT_HEAP_SIZE+1) *
2250
return uint_to_big(size, hp);
2256
* Add 'size' to 'acc' in place. There is always one
2257
* extra word allocated in case the bignum grows by one word.
2260
need_heap = BIG_NEED_SIZE(BIG_SIZE(big));
2261
acc = big_plus_small(acc, size, big);
2262
if (BIG_NEED_SIZE(big_size(acc)) > need_heap) {
2264
* The extra word has been consumed. Grow the
2265
* allocation by one word.
2267
big = (Eterm *) erts_realloc(ERTS_ALC_T_TEMP_TERM,
2269
(need_heap+1) * sizeof(Eterm));
2270
acc = make_big(big);
2277
consolidate(Process* p, Eterm acc, Uint size)
2281
if (is_non_value(acc)) {
2282
return erts_make_integer(size, p);
2288
acc = accumulate(acc, size);
2290
sz = BIG_NEED_SIZE(BIG_SIZE(big));
2296
erts_free(ERTS_ALC_T_TEMP_TERM, (void *) big_val(acc));
2162
2301
BIF_RETTYPE iolist_size_1(BIF_ALIST_1)
2164
Sint size = io_list_len(BIF_ARG_1);
2167
BIF_ERROR(BIF_P, BADARG);
2168
} else if (IS_USMALL(0, (Uint) size)) {
2169
BIF_RET(make_small(size));
2171
Eterm* hp = HAlloc(BIF_P, BIG_UINT_HEAP_SIZE);
2172
BIF_RET(uint_to_big(size, hp));
2308
Eterm acc = THE_NON_VALUE;
2314
while (!ESTACK_ISEMPTY(s)) {
2315
obj = ESTACK_POP(s);
2319
objp = list_val(obj);
2326
acc = accumulate(acc, (Uint) -1);
2329
} else if (is_binary(hd) && binary_bitsize(hd) == 0) {
2330
cur_size = binary_size(hd);
2331
if ((new_size = size + cur_size) >= size) {
2334
acc = accumulate(acc, size);
2337
} else if (is_list(hd)) {
2338
ESTACK_PUSH(s, obj);
2341
} else if (is_not_nil(hd)) {
2347
} else if (is_binary(obj) && binary_bitsize(obj) == 0) {
2348
cur_size = binary_size(obj);
2349
if ((new_size = size + cur_size) >= size) {
2352
acc = accumulate(acc, size);
2355
} else if (is_not_nil(obj)) {
2358
} else if (is_binary(obj) && binary_bitsize(obj) == 0) {
2359
cur_size = binary_size(obj);
2360
if ((new_size = size + cur_size) >= size) {
2363
acc = accumulate(acc, size);
2366
} else if (is_not_nil(obj)) {
2372
BIF_RET(consolidate(BIF_P, acc, size));
2376
BIF_ERROR(BIF_P, BADARG);
2177
2379
/**********************************************************************/
2179
2381
/* return the N'th element of a tuple */
3180
3385
BIF_RET(TUPLE2(hp, res1, res2));
3388
/* convert calendar:universaltime_to_seconds/1 */
3390
BIF_RETTYPE universaltime_to_posixtime_1(BIF_ALIST_1)
3392
Sint year, month, day;
3393
Sint hour, minute, second;
3399
if (!time_to_parts(BIF_ARG_1, &year, &month, &day,
3400
&hour, &minute, &second))
3401
BIF_ERROR(BIF_P, BADARG);
3403
if (!univ_to_seconds(year, month, day, hour, minute, second, &seconds)) {
3404
BIF_ERROR(BIF_P, BADARG);
3407
erts_bld_sint64(NULL, &hsz, seconds);
3408
hp = HAlloc(BIF_P, hsz);
3409
BIF_RET(erts_bld_sint64(&hp, NULL, seconds));
3412
/* convert calendar:seconds_to_universaltime/1 */
3414
BIF_RETTYPE posixtime_to_universaltime_1(BIF_ALIST_1)
3416
Sint year, month, day;
3417
Sint hour, minute, second;
3423
if (!term_to_Sint64(BIF_ARG_1, &time)) {
3424
BIF_ERROR(BIF_P, BADARG);
3427
if (!seconds_to_univ(time, &year, &month, &day,
3428
&hour, &minute, &second)) {
3429
BIF_ERROR(BIF_P, BADARG);
3432
hp = HAlloc(BIF_P, 4+4+3);
3433
res1 = TUPLE3(hp,make_small(year),make_small(month),
3436
res2 = TUPLE3(hp,make_small(hour),make_small(minute),
3437
make_small(second));
3439
BIF_RET(TUPLE2(hp, res1, res2));
3183
3443
/**********************************************************************/
3206
3466
BIF_ERROR(BIF_P, BADARG);
3209
rp = erts_pid2proc_not_running(BIF_P, ERTS_PROC_LOCK_MAIN,
3469
if (BIF_P->id == BIF_ARG_1)
3473
rp = erts_pid2proc_suspend(BIF_P, ERTS_PROC_LOCK_MAIN,
3210
3474
BIF_ARG_1, ERTS_PROC_LOCK_MAIN);
3213
if (rp == ERTS_PROC_LOCK_BUSY)
3214
ERTS_BIF_YIELD1(bif_export[BIF_garbage_collect_1], BIF_P, BIF_ARG_1);
3475
if (rp == ERTS_PROC_LOCK_BUSY)
3476
ERTS_BIF_YIELD1(bif_export[BIF_garbage_collect_1], BIF_P, BIF_ARG_1);
3478
rp = erts_pid2proc(BIF_P, 0, BIF_ARG_1, 0);
3216
3484
/* The GC cost is taken for the process executing this BIF. */
3218
3486
FLAGS(rp) |= F_NEED_FULLSWEEP;
3219
3487
reds = erts_garbage_collect(rp, 0, rp->arg_reg, rp->arity);
3491
erts_resume(rp, ERTS_PROC_LOCK_MAIN);
3222
3492
erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_MAIN);
3224
3496
BIF_RET2(am_true, reds);
3270
3543
erts_smp_mtx_lock(&ports_snapshot_mtx); /* One snapshot at a time */
3272
erts_smp_atomic_set(&erts_dead_ports_ptr, (long) (port_buf + erts_max_ports));
3274
next_ss = erts_smp_atomic_inctest(&erts_ports_snapshot);
3276
if (erts_smp_atomic_read(&erts_ports_alive) > 0) {
3278
for (i = erts_max_ports-1; i >= 0; i--) {
3279
Port* prt = &erts_port[i];
3280
erts_smp_port_state_lock(prt);
3281
if (!(prt->status & ERTS_PORT_SFLGS_DEAD)
3282
&& prt->snapshot != next_ss) {
3283
ASSERT(prt->snapshot == next_ss - 1);
3285
prt->snapshot = next_ss; /* Consumed by this snapshot */
3287
erts_smp_port_state_unlock(prt);
3545
erts_smp_atomic_set_nob(&erts_dead_ports_ptr,
3546
(erts_aint_t) (port_buf + erts_max_ports));
3548
next_ss = erts_smp_atomic32_inc_read_relb(&erts_ports_snapshot);
3550
for (i = erts_max_ports-1; i >= 0; i--) {
3551
Port* prt = &erts_port[i];
3552
erts_smp_port_state_lock(prt);
3553
if (!(prt->status & ERTS_PORT_SFLGS_DEAD)
3554
&& prt->snapshot != next_ss) {
3555
ASSERT(prt->snapshot == next_ss - 1);
3557
prt->snapshot = next_ss; /* Consumed by this snapshot */
3559
erts_smp_port_state_unlock(prt);
3291
dead_ports = (Eterm*)erts_smp_atomic_xchg(&erts_dead_ports_ptr,
3562
dead_ports = (Eterm*)erts_smp_atomic_xchg_nob(&erts_dead_ports_ptr,
3563
(erts_aint_t) NULL);
3293
3564
erts_smp_mtx_unlock(&ports_snapshot_mtx);
3295
3566
ASSERT(pp <= dead_ports);
3350
3621
erts_dsprintf_buf_t *dsbufp = erts_create_tmp_dsbuf(64);
3351
3622
pres = erts_dsprintf(dsbufp, "%.*T\n", INT_MAX, BIF_ARG_1);
3353
erl_exit(1, "Failed to convert term to string: %d (s)\n",
3624
erl_exit(1, "Failed to convert term to string: %d (%s)\n",
3354
3625
-pres, erl_errno_id(-pres));
3355
3626
hp = HAlloc(BIF_P, 2*dsbufp->str_len); /* we need length * 2 heap words */
3356
3627
res = buf_to_intlist(&hp, dsbufp->str, dsbufp->str_len, NIL);
3468
3744
erts_dsprintf_buf_t *dsbufp = erts_create_tmp_dsbuf(64);
3469
3745
pres = erts_dsprintf(dsbufp, "%T", term);
3471
erl_exit(1, "Failed to convert term to list: %d (s)\n",
3747
erl_exit(1, "Failed to convert term to list: %d (%s)\n",
3472
3748
-pres, erl_errno_id(-pres));
3473
3749
hp = HAlloc(p, 2*dsbufp->str_len); /* we need length * 2 heap words */
3474
3750
res = buf_to_intlist(&hp, dsbufp->str, dsbufp->str_len, NIL);
3808
4087
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
3809
erts_smp_block_system(0);
4088
erts_smp_thr_progress_block();
3811
4090
H_MIN_SIZE = erts_next_heap_size(n, 0);
3813
erts_smp_release_system();
4092
erts_smp_thr_progress_unblock();
3814
4093
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
3816
4095
BIF_RET(make_small(oval));
3824
4103
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
3825
erts_smp_block_system(0);
4104
erts_smp_thr_progress_block();
3827
4106
BIN_VH_MIN_SIZE = erts_next_heap_size(n, 0);
3829
erts_smp_release_system();
4108
erts_smp_thr_progress_unblock();
3830
4109
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
3832
4111
BIF_RET(make_small(oval));
3900
4179
if (is_value(res))
3902
4181
} else if (ERTS_IS_ATOM_STR("cpu_topology", BIF_ARG_1)) {
4182
erts_send_warning_to_logger_str(
4183
BIF_P->group_leader,
4184
"A call to erlang:system_flag(cpu_topology, _) was made.\n"
4185
"The cpu_topology argument is deprecated and scheduled\n"
4186
"for removal in erts-5.10/OTP-R16. For more information\n"
4187
"see the erlang:system_flag/2 documentation.\n");
3903
4188
BIF_TRAP1(set_cpu_topology_trap, BIF_P, BIF_ARG_2);
3904
4189
} else if (ERTS_IS_ATOM_STR("scheduler_bind_type", BIF_ARG_1)) {
4190
erts_send_warning_to_logger_str(
4191
BIF_P->group_leader,
4192
"A call to erlang:system_flag(scheduler_bind_type, _) was\n"
4193
"made. The scheduler_bind_type argument is deprecated and\n"
4194
"scheduled for removal in erts-5.10/OTP-R16. For more\n"
4195
"information see the erlang:system_flag/2 documentation.\n");
3905
4196
return erts_bind_schedulers(BIF_P, BIF_ARG_2);
4088
4379
erts_bif_prep_await_proc_exit_data_trap(Process *c_p, Eterm pid, Eterm ret)
4090
4381
if (skip_current_msgq(c_p)) {
4092
ERTS_BIF_PREP_TRAP3(unused, await_proc_exit_trap, c_p, pid, am_data, ret);
4382
ERTS_BIF_PREP_TRAP3_NO_RET(await_proc_exit_trap, c_p, pid, am_data, ret);