107
make_link_list(Process *p, ErlLink *ls)
145
returns a list of records..
146
-record(erl_monitor, {
147
type, % MON_ORIGIN or MON_TARGET (1 or 3)
149
pid, % Process or nodename
150
name % registered name or []
154
static void do_calc_mon_size(ErtsMonitor *mon, void *vpsz)
157
*psz += IS_CONST(mon->ref) ? 0 : NC_HEAP_SIZE(mon->ref);
158
*psz += IS_CONST(mon->pid) ? 0 : NC_HEAP_SIZE(mon->pid);
159
*psz += 8; /* CONS + 5-tuple */
169
static void do_make_one_mon_element(ErtsMonitor *mon, void * vpmlc)
171
MonListContext *pmlc = vpmlc;
173
Eterm r = (IS_CONST(mon->ref)
175
: STORE_NC(&(pmlc->hp), &MSO(pmlc->p).externals, mon->ref));
176
Eterm p = (IS_CONST(mon->pid)
178
: STORE_NC(&(pmlc->hp), &MSO(pmlc->p).externals, mon->pid));
179
tup = TUPLE5(pmlc->hp, pmlc->tag, make_small(mon->type), r, p, mon->name);
181
pmlc->res = CONS(pmlc->hp, tup, pmlc->res);
186
make_monitor_list(Process *p, ErtsMonitor *root)
188
DECL_AM(erl_monitor);
192
erts_doforall_monitors(root, &do_calc_mon_size, &sz);
197
mlc.hp = HAlloc(p,sz);
199
mlc.tag = AM_erl_monitor;
200
erts_doforall_monitors(root, &do_make_one_mon_element, &mlc);
206
returns a list of records..
208
type, % LINK_NODE or LINK_PID (1 or 3)
209
pid, % Process or nodename
210
targets % List of erl_link's or nil
214
static void do_calc_lnk_size(ErtsLink *lnk, void *vpsz)
217
*psz += IS_CONST(lnk->pid) ? 0 : NC_HEAP_SIZE(lnk->pid);
218
if (lnk->type != LINK_NODE && lnk->root != NULL) {
219
/* Node links use this pointer as ref counter... */
220
erts_doforall_links(lnk->root,&do_calc_lnk_size,vpsz);
222
*psz += 7; /* CONS + 4-tuple */
232
static void do_make_one_lnk_element(ErtsLink *lnk, void * vpllc)
234
LnkListContext *pllc = vpllc;
236
Eterm old_res, targets = NIL;
237
Eterm p = (IS_CONST(lnk->pid)
239
: STORE_NC(&(pllc->hp), &MSO(pllc->p).externals, lnk->pid));
240
if (lnk->type == LINK_NODE) {
241
targets = make_small(ERTS_LINK_ROOT_AS_UINT(lnk));
242
} else if (lnk->root != NULL) {
245
erts_doforall_links(lnk->root,&do_make_one_lnk_element, vpllc);
249
tup = TUPLE4(pllc->hp, pllc->tag, make_small(lnk->type), p, targets);
251
pllc->res = CONS(pllc->hp, tup, pllc->res);
256
make_link_list(Process *p, ErtsLink *root, Eterm tail)
109
258
DECL_AM(erl_link);
119
for(l = ls, s = 0; l; l = l->next) {
120
s += IS_CONST(l->item) ? 0 : NC_HEAP_SIZE(l->item);
121
s += IS_CONST(l->data) ? 0 : NC_HEAP_SIZE(l->data);
122
s += IS_CONST(l->ref) ? 0 : NC_HEAP_SIZE(l->ref);
123
s += 2 /* 1 cons cell */ + 6 /* 1 five-tuple */;
135
for(l = ls, res = NIL; l; l = l->next) {
136
Eterm i = (IS_CONST(l->item)
138
: STORE_NC(&hp, &MSO(p).externals, l->item));
139
Eterm d = (IS_CONST(l->data)
141
: STORE_NC(&hp, &MSO(p).externals, l->data));
142
Eterm r = (IS_CONST(l->ref)
144
: STORE_NC(&hp, &MSO(p).externals, l->ref));
145
tup = TUPLE5(hp, AM_erl_link, make_small(l->type), i, d, r);
147
res = CONS(hp, tup, res);
262
erts_doforall_links(root, &do_calc_lnk_size, &sz);
267
llc.hp = HAlloc(p,sz);
269
llc.tag = AM_erl_link;
270
erts_doforall_links(root, &do_make_one_lnk_element, &llc);
159
erts_get_system_version(int *lenp)
275
erts_print_system_version(int to, void *arg, Process *c_p)
277
return erts_print(to, arg, erts_system_version
279
, erts_get_no_schedulers()
161
281
#ifdef USE_THREADS
162
static char sbuf[sizeof(erts_system_version) + 20];
164
sprintf(sbuf, erts_system_version, erts_async_max_threads);
166
*lenp = sys_strlen(sbuf);
171
*lenp = sizeof(erts_system_version) - 1;
173
return erts_system_version;
282
, erts_async_max_threads
284
#ifdef ERTS_ENABLE_KERNEL_POLL
285
, erts_use_kernel_poll ? "true" : "false"
291
process_info_aux(Process *BIF_P, Process *rp, Eterm rpid, Eterm item);
178
294
process_info_1(Process* p, Eterm pid)
387
erts_smp_proc_unlock(rp,
389
? ERTS_PROC_LOCKS_ALL
390
: (ERTS_PROC_LOCKS_ALL & ~ERTS_PROC_LOCK_MAIN)));
405
} MonitorInfoCollection;
407
#define INIT_MONITOR_INFOS(MIC) do { \
409
(MIC).mi_i = (MIC).mi_max = 0; \
414
#define EXTEND_MONITOR_INFOS(MICP) \
416
if ((MICP)->mi_i >= (MICP)->mi_max) { \
417
(MICP)->mi = ((MICP)->mi ? erts_realloc(ERTS_ALC_T_TMP, \
419
((MICP)->mi_max+MI_INC) \
420
* sizeof(MonitorInfo)) \
421
: erts_alloc(ERTS_ALC_T_TMP, \
422
MI_INC*sizeof(MonitorInfo))); \
423
(MICP)->mi_max += MI_INC; \
426
#define DESTROY_MONITOR_INFOS(MIC) \
428
if ((MIC).mi != NULL) { \
429
erts_free(ERTS_ALC_T_TMP, (void *) (MIC).mi); \
433
static void collect_one_link(ErtsLink *lnk, void *vmicp)
435
MonitorInfoCollection *micp = vmicp;
436
EXTEND_MONITOR_INFOS(micp);
437
if (!(lnk->type == LINK_PID)) {
440
micp->mi[micp->mi_i].entity = lnk->pid;
441
micp->sz += 2 + NC_HEAP_SIZE(lnk->pid);
445
static void collect_one_origin_monitor(ErtsMonitor *mon, void *vmicp)
447
MonitorInfoCollection *micp = vmicp;
449
if (mon->type != MON_ORIGIN) {
452
EXTEND_MONITOR_INFOS(micp);
453
if (is_atom(mon->pid)) { /* external by name */
454
micp->mi[micp->mi_i].entity = mon->name;
455
micp->mi[micp->mi_i].node = mon->pid;
456
micp->sz += 3; /* need one 2-tuple */
457
} else if (is_external_pid(mon->pid)) { /* external by pid */
458
micp->mi[micp->mi_i].entity = mon->pid;
459
micp->mi[micp->mi_i].node = NIL;
460
micp->sz += NC_HEAP_SIZE(mon->pid);
461
} else if (!is_nil(mon->name)) { /* internal by name */
462
micp->mi[micp->mi_i].entity = mon->name;
463
micp->mi[micp->mi_i].node = erts_this_dist_entry->sysname;
464
micp->sz += 3; /* need one 2-tuple */
465
} else { /* internal by pid */
466
micp->mi[micp->mi_i].entity = mon->pid;
467
micp->mi[micp->mi_i].node = NIL;
468
/* no additional heap space needed */
471
micp->sz += 2 + 3; /* For a cons cell and a 2-tuple */
474
static void collect_one_target_monitor(ErtsMonitor *mon, void *vmicp)
476
MonitorInfoCollection *micp = vmicp;
478
if (mon->type != MON_TARGET) {
482
EXTEND_MONITOR_INFOS(micp);
484
micp->mi[micp->mi_i].node = NIL;
485
micp->mi[micp->mi_i].entity = mon->pid;
486
micp->sz += (NC_HEAP_SIZE(mon->pid) + 2 /* cons */);
491
static void one_link_size(ErtsLink *lnk, void *vpu)
494
*pu += ERTS_LINK_SIZE*sizeof(Uint);
495
if(!IS_CONST(lnk->pid))
496
*pu += NC_HEAP_SIZE(lnk->pid)*sizeof(Uint);
497
if (lnk->type != LINK_NODE && lnk->root != NULL) {
498
erts_doforall_links(lnk->root,&one_link_size,vpu);
501
static void one_mon_size(ErtsMonitor *mon, void *vpu)
504
*pu += ERTS_MONITOR_SIZE*sizeof(Uint);
505
if(!IS_CONST(mon->pid))
506
*pu += NC_HEAP_SIZE(mon->pid)*sizeof(Uint);
507
if(!IS_CONST(mon->ref))
508
*pu += NC_HEAP_SIZE(mon->ref)*sizeof(Uint);
254
511
BIF_RETTYPE process_info_2(BIF_ALIST_2)
256
Eterm item, term, list;
261
516
Eterm pid = BIF_ARG_1;
263
519
if (is_external_pid(pid)
264
520
&& external_pid_dist_entry(pid) == erts_this_dist_entry)
272
528
if (is_not_atom(BIF_ARG_2))
273
529
BIF_ERROR(BIF_P, BADARG);
277
rp = process_tab[internal_pid_index(BIF_ARG_1)];
279
/* if the process is not active return undefined */
280
if (INVALID_PID(rp, BIF_ARG_1)) {
281
BIF_RET(am_undefined);
532
info_locks = ERTS_PROC_LOCK_MAIN;
535
case am_internal_status:
536
flags = ERTS_P2P_FLG_ALLOW_OTHER_X;
539
info_locks = ERTS_PROC_LOCK_STATUS;
542
case am_message_queue_len:
543
info_locks |= ERTS_PROC_LOCK_MSGQ;
547
case am_monitored_by:
548
info_locks = ERTS_PROC_LOCK_LINK;
551
info_locks |= ERTS_PROC_LOCK_LINK|ERTS_PROC_LOCK_MSGQ;
557
rp = erts_pid2proc_opt(BIF_P, ERTS_PROC_LOCK_MAIN, pid, info_locks, flags);
558
if (rp || BIF_ARG_2 == am_internal_status)
559
res = process_info_aux(BIF_P, rp, pid, BIF_ARG_2);
561
res = am_undefined; /* if the process is not active return undefined */
566
info_locks &= ~ERTS_PROC_LOCK_MAIN;
567
if (rp && info_locks)
568
erts_smp_proc_unlock(rp, info_locks);
575
process_info_aux(Process *BIF_P, Process *rp, Eterm rpid, Eterm item)
580
/* internal_status is a little special... */
581
ASSERT(rp || item == am_internal_status);
285
583
if (item == am_registered_name) {
286
584
if (rp->reg != NULL) {
326
624
rp->initial[INITIAL_FUN],
327
625
make_small(rp->initial[INITIAL_ARI]));
329
} else if (item == am_status ) {
627
} else if (item == am_status || item == am_internal_status) {
628
res = erts_process_status(BIF_P, ERTS_PROC_LOCK_MAIN, rp, rpid);
629
if (res == am_undefined)
330
631
hp = HAlloc(BIF_P, 3);
331
switch (rp->status) {
350
632
} else if (item == am_messages) {
636
ERTS_SMP_MSGQ_MV_INQ2PRIVQ(rp);
357
640
hp = HAlloc(BIF_P, 3);
364
size += size_object(ERL_MESSAGE_TERM(mp));
642
Eterm* ma = (Eterm *) erts_alloc(ERTS_ALC_T_TMP, n*sizeof(Eterm));
646
for (mp = rp->msg.first; mp != NULL; mp = mp->next) {
649
* Hybrid: Almost all messages already are in the message area.
651
if (NO_COPY(ERL_MESSAGE_TERM(mp)) || rp == BIF_P) {
652
/* Constant, already in message area, or same process. */
653
ma[i] = ERL_MESSAGE_TERM(mp);
655
ma[i] = copy_object(ERL_MESSAGE_TERM(mp), BIF_P);
368
hp = HAlloc(BIF_P, 3 + size + 2*n);
369
hp += 2*n; /* skip the list !!! */
371
res = make_list(cons); /* first cons cell */
372
/* Build with back-pointers (as cons whould have done) */
659
* We must copy the message if it belongs to another process.
375
661
if (rp == BIF_P) {
376
cons[0] = ERL_MESSAGE_TERM(mp);
662
#if defined(ERTS_SMP) && !defined(HEAP_FRAG_ELIM_TEST)
664
erts_move_msg_mbuf_to_proc_mbufs(BIF_P, mp);
667
ma[i] = ERL_MESSAGE_TERM(mp);
378
cons[0] = copy_object(ERL_MESSAGE_TERM(mp), BIF_P);
669
ma[i] = copy_object(ERL_MESSAGE_TERM(mp), BIF_P);
380
cons -= 2; /* next cell */
381
cons[3] = make_list(cons); /* write tail */
674
hp = HAlloc(BIF_P, 3+2*n);
675
for (i = n-1; i >= 0; i--) {
676
res = CONS(hp, ma[i], res);
679
erts_free(ERTS_ALC_T_TMP, (void *) ma);
386
681
} else if (item == am_message_queue_len) {
387
682
hp = HAlloc(BIF_P, 3);
683
ERTS_SMP_MSGQ_MV_INQ2PRIVQ(rp);
388
684
res = make_small(rp->msg.len);
389
685
} else if (item == am_links) {
686
MonitorInfoCollection mic;
394
for (lnk = rp->links; lnk; lnk = lnk->next) {
395
if (lnk->type == LNK_LINK) {
396
sz += NC_HEAP_SIZE(lnk->item);
400
hp = HAlloc(BIF_P, 3 + sz);
690
INIT_MONITOR_INFOS(mic);
692
erts_doforall_links(rp->nlinks,&collect_one_link,&mic);
694
hp = HAlloc(BIF_P, 3 + mic.sz);
402
for (lnk = rp->links; lnk; lnk = lnk->next) {
403
if (lnk->type == LNK_LINK) {
404
item = STORE_NC(&hp, &MSO(BIF_P).externals, lnk->item);
405
res = CONS(hp, item, res);
696
for (i = 0; i < mic.mi_i; i++) {
697
item = STORE_NC(&hp, &MSO(BIF_P).externals, mic.mi[i].entity);
698
res = CONS(hp, item, res);
701
DESTROY_MONITOR_INFOS(mic);
409
703
} else if (item == am_monitors) {
422
/* lnk->item is the monitor link origin end */
423
for (lnk = rp->links; lnk; lnk = lnk->next) {
424
if (mi_i >= mi_max) {
425
mi = (mi ? erts_realloc(ERTS_ALC_T_TMP,
427
(mi_max+MI_INC)*sizeof(*mi))
428
: erts_alloc(ERTS_ALC_T_TMP, MI_INC*sizeof(*mi)));
431
if (lnk->type == LNK_LINK1 && rp->id == lnk->item) {
433
if (is_atom(lnk->data)) {
434
/* Dist monitor by name. */
437
ASSERT(is_node_name_atom(lnk->data));
438
dep = erts_sysname_to_connected_dist_entry(lnk->data);
441
lnkp = find_link_by_ref(&dep->links, lnk->ref);
442
mi[mi_i].entity = (*lnkp)->data;
443
mi[mi_i].node = lnk->data;
445
/* Will need an additional 2-tuple. */
447
} else if (is_internal_pid(lnk->data)) {
448
Process *p = pid2proc(lnk->data);
451
lnkp = find_link_by_ref(&p->links, lnk->ref);
454
if (is_atom((*lnkp)->data)) { /* Local monitor by name. */
455
mi[mi_i].entity = (*lnkp)->data;
456
mi[mi_i].node = erts_this_dist_entry->sysname;
457
/* Will need an additional 2-tuple. */
461
mi[mi_i].entity = lnk->data;
464
ASSERT(is_external_pid(lnk->data));
465
mi[mi_i].entity = lnk->data;
466
sz += NC_HEAP_SIZE(lnk->data);
469
sz += 2 + 3; /* For a cons cell and a 2-tuple */
472
hp = HAlloc(BIF_P, 3 + sz);
704
MonitorInfoCollection mic;
707
INIT_MONITOR_INFOS(mic);
708
erts_doforall_monitors(rp->monitors,&collect_one_origin_monitor,&mic);
709
hp = HAlloc(BIF_P, 3 + mic.sz);
474
for (mi_max = mi_i, mi_i = 0; mi_i < mi_max; mi_i++) {
475
if (is_atom(mi[mi_i].entity)) {
711
for (i = 0; i < mic.mi_i; i++) {
712
if (is_atom(mic.mi[i].entity)) {
476
713
/* Monitor by name.
477
714
* Build {process, {Name, Node}} and cons it.
481
t1 = TUPLE2(hp, mi[mi_i].entity, mi[mi_i].node);
718
t1 = TUPLE2(hp, mic.mi[i].entity, mic.mi[i].node);
483
720
t2 = TUPLE2(hp, am_process, t1);
491
728
Eterm pid = STORE_NC(&hp,
492
729
&MSO(BIF_P).externals,
494
731
t = TUPLE2(hp, am_process, pid);
496
733
res = CONS(hp, t, res);
501
erts_free(ERTS_ALC_T_TMP, (void *) mi);
737
DESTROY_MONITOR_INFOS(mic);
503
738
} else if (item == am_monitored_by) {
739
MonitorInfoCollection mic;
508
/* lnk->item is the monitor link origin end */
509
for (lnk = rp->links; lnk; lnk = lnk->next) {
510
if (lnk->type == LNK_LINK1 && rp->id != lnk->item) {
511
sz += NC_HEAP_SIZE(lnk->item);
515
hp = HAlloc(BIF_P, 3 + sz);
743
INIT_MONITOR_INFOS(mic);
744
erts_doforall_monitors(rp->monitors,&collect_one_target_monitor,&mic);
745
hp = HAlloc(BIF_P, 3 + mic.sz);
517
for (lnk = rp->links; lnk; lnk = lnk->next) {
518
if (lnk->type == LNK_LINK1 && rp->id != lnk->item) {
519
item = STORE_NC(&hp, &MSO(BIF_P).externals, lnk->item);
520
res = CONS(hp, item, res);
748
for (i = 0; i < mic.mi_i; ++i) {
749
item = STORE_NC(&hp, &MSO(BIF_P).externals, mic.mi[i].entity);
750
res = CONS(hp, item, res);
753
DESTROY_MONITOR_INFOS(mic);
524
754
} else if (item == am_dictionary) {
525
res = dictionary_copy(BIF_P, rp->dictionary);
755
res = erts_dictionary_copy(BIF_P, rp->dictionary);
526
756
hp = HAlloc(BIF_P, 3);
527
757
} else if (item == am_DollarDictionary) {
528
res = dictionary_copy(BIF_P, rp->debug_dictionary);
758
res = erts_dictionary_copy(BIF_P, rp->debug_dictionary);
529
759
hp = HAlloc(BIF_P, 3);
530
760
} else if (item == am_trap_exit) {
531
761
hp = HAlloc(BIF_P, 3);
537
767
hp = HAlloc(BIF_P, 3);
538
768
res = rp->error_handler;
539
769
} else if (item == am_heap_size) {
540
hp = HAlloc(BIF_P, 3);
541
res = make_small(HEAP_SIZE(rp));
771
(void) erts_bld_uint(NULL, &hsz, HEAP_SIZE(rp));
772
hp = HAlloc(BIF_P, hsz);
773
res = erts_bld_uint(&hp, NULL, HEAP_SIZE(rp));
542
774
} else if (item == am_stack_size) {
543
hp = HAlloc(BIF_P, 3);
544
res = make_small(STACK_START(rp) - rp->stop);
775
Uint stack_size = STACK_START(rp) - rp->stop;
777
(void) erts_bld_uint(NULL, &hsz, stack_size);
778
hp = HAlloc(BIF_P, hsz);
779
res = erts_bld_uint(&hp, NULL, stack_size);
545
780
} else if (item == am_memory) { /* Memory consumed in bytes */
550
783
size += sizeof(Process);
552
for(lnk = rp->links; lnk; lnk = lnk->next)
553
size += erts_link_size(lnk);
785
ERTS_SMP_MSGQ_MV_INQ2PRIVQ(rp);
556
size += (rp->stack - rp->send) * sizeof(Eterm);
787
erts_doforall_links(rp->nlinks, &one_link_size, &size);
788
erts_doforall_monitors(rp->monitors, &one_mon_size, &size);
558
789
size += (rp->heap_sz + rp->mbuf_sz) * sizeof(Eterm);
559
790
if (rp->old_hend && rp->old_heap)
560
791
size += (rp->old_hend - rp->old_heap) * sizeof(Eterm);
563
793
size += rp->msg.len * sizeof(ErlMessage);
591
821
res = STORE_NC(&hp, &MSO(BIF_P).externals, rp->group_leader);
592
822
} else if (item == am_reductions) {
595
hp = HAlloc(BIF_P, 3);
596
reds = rp->reds + erts_current_reductions(BIF_P, rp);
597
res = make_small_or_big(reds, BIF_P);
823
Uint reds = rp->reds + erts_current_reductions(BIF_P, rp);
825
(void) erts_bld_uint(NULL, &hsz, reds);
826
hp = HAlloc(BIF_P, hsz);
827
res = erts_bld_uint(&hp, NULL, reds);
598
828
} else if (item == am_priority) {
599
829
hp = HAlloc(BIF_P, 3);
604
res = am_high; break;
605
case PRIORITY_NORMAL:
606
res = am_normal; break;
830
res = erts_get_process_priority(rp);
610
831
} else if (item == am_trace) {
611
832
hp = HAlloc(BIF_P, 3);
612
res = make_small(rp->flags & TRACE_FLAGS);
833
res = make_small(rp->trace_flags & TRACEE_FLAGS);
613
834
} else if (item == am_binary) {
615
836
(void) bld_bin_list(NULL, &sz, MSO(rp).mso);
616
837
hp = HAlloc(BIF_P, sz);
617
838
res = bld_bin_list(&hp, NULL, MSO(rp).mso);
840
} else if (item == am_message_binary) {
842
(void) bld_bin_list(NULL, &sz, erts_global_offheap.mso);
843
hp = HAlloc(BIF_P, sz);
844
res = bld_bin_list(&hp, NULL, erts_global_offheap.mso);
618
846
} else if (item == am_sequential_trace_token) {
685
928
if (sel == am_memory) {
687
931
return am_badarg;
688
return erts_memory(NULL, BIF_P, *tp);
932
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
933
res = erts_memory(NULL, NULL, BIF_P, *tp);
934
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
689
936
} else if (sel == am_allocated) {
690
937
if (arity == 2) {
694
return THE_NON_VALUE;
696
if ((len = intlist_to_buf(*tp, tmp_buf, TMP_BUF_SIZE-1)) < 0)
697
return THE_NON_VALUE;
700
if (erts_instr_dump_memory_map(tmp_buf))
938
Eterm res = THE_NON_VALUE;
940
int len = is_string(*tp);
943
buf = (char *) erts_alloc(ERTS_ALC_T_TMP, len+1);
944
if (intlist_to_buf(*tp, buf, len) != len)
945
erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__);
947
res = erts_instr_dump_memory_map(buf) ? am_true : am_false;
948
erts_free(ERTS_ALC_T_TMP, (void *) buf);
705
951
else if (arity == 3 && tp[0] == am_status) {
706
952
if (is_atom(tp[1]))
707
953
return erts_instr_get_stat(BIF_P, tp[1], 1);
710
if (!is_string(tp[1]))
711
return THE_NON_VALUE;
713
if ((len = intlist_to_buf(tp[1], tmp_buf, TMP_BUF_SIZE-1)) < 0)
714
return THE_NON_VALUE;
717
if (erts_instr_dump_stat(tmp_buf, 1))
955
Eterm res = THE_NON_VALUE;
957
int len = is_string(tp[1]);
960
buf = (char *) erts_alloc(ERTS_ALC_T_TMP, len+1);
961
if (intlist_to_buf(tp[1], buf, len) != len)
962
erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__);
964
res = erts_instr_dump_stat(buf, 1) ? am_true : am_false;
965
erts_free(ERTS_ALC_T_TMP, (void *) buf);
724
970
return THE_NON_VALUE;
726
} else if (sel == am_purify) {
971
#if defined(PURIFY) || defined(VALGRIND)
972
} else if (sel == AM_error_checker
975
#elif defined(VALGRIND)
976
|| sel == AM_valgrind
727
979
if (*tp == am_memory) {
728
BIF_RET(make_small_or_big(purify_new_leaks(), BIF_P));
981
BIF_RET(erts_make_integer(purify_new_leaks(), BIF_P));
982
#elif defined(VALGRIND)
983
VALGRIND_DO_LEAK_CHECK;
984
BIF_RET(make_small(0));
729
986
} else if (*tp == am_fd) {
730
BIF_RET(make_small_or_big(purify_new_fds_inuse(), BIF_P));
988
BIF_RET(erts_make_integer(purify_new_fds_inuse(), BIF_P));
989
#elif defined(VALGRIND)
990
/* Not present in valgrind... */
991
BIF_RET(make_small(0));
731
993
} else if (*tp == am_running) {
732
995
BIF_RET(purify_is_running() ? am_true : am_false);
996
#elif defined(VALGRIND)
997
BIF_RET(RUNNING_ON_VALGRIND ? am_true : am_false);
733
999
} else if (is_list(*tp)) {
736
r = io_list_to_buf(*tp, (char*) tmp_buf, TMP_BUF_SIZE - 1);
738
tmp_buf[TMP_BUF_SIZE - 1 - r] = '\0';
739
purify_printf("%s\n", tmp_buf);
741
return THE_NON_VALUE;
1001
#define ERTS_ERROR_CHECKER_PRINTF purify_printf
1002
#elif defined(VALGRIND)
1003
#define ERTS_ERROR_CHECKER_PRINTF VALGRIND_PRINTF
1005
int buf_size = 8*1024; /* Try with 8KB first */
1006
char *buf = erts_alloc(ERTS_ALC_T_TMP, buf_size);
1007
int r = io_list_to_buf(*tp, (char*) buf, buf_size - 1);
1009
erts_free(ERTS_ALC_T_TMP, (void *) buf);
1010
buf_size = io_list_len(*tp);
1012
return THE_NON_VALUE;
1014
buf = erts_alloc(ERTS_ALC_T_TMP, buf_size);
1015
r = io_list_to_buf(*tp, (char*) buf, buf_size - 1);
1016
ASSERT(r == buf_size - 1);
1018
buf[buf_size - 1 - r] = '\0';
1019
ERTS_ERROR_CHECKER_PRINTF("%s\n", buf);
1020
erts_free(ERTS_ALC_T_TMP, (void *) buf);
743
1021
BIF_RET(am_true);
1022
#undef ERTS_ERROR_CHECKER_PRINTF
779
1058
BIF_RET(am_true);
781
} else if (sel == am_link_list) {
782
ErlLink *links = NULL;
783
if(is_internal_pid(*tp)) {
784
Process *p = pid2proc(*tp);
790
else if(is_internal_port(*tp)) {
791
Port *p = id2port(*tp);
797
else if(is_node_name_atom(*tp)) {
798
DistEntry *dep = erts_find_dist_entry(*tp);
805
return THE_NON_VALUE;
807
return make_link_list(BIF_P, links);
809
else if (sel == am_allocator && arity == 2) {
1060
} else if (sel == am_allocator && arity == 2) {
810
1061
return erts_allocator_info_term(BIF_P, *tp);
813
1063
return THE_NON_VALUE;
1066
#define INFO_DSBUF_INC_SZ 256
1068
static erts_dsprintf_buf_t *
1069
grow_info_dsbuf(erts_dsprintf_buf_t *dsbufp, size_t need)
1072
size_t free_size = dsbufp->size - dsbufp->str_len;
1076
if (need <= free_size)
1078
size = need - free_size + INFO_DSBUF_INC_SZ;
1079
size = ((size + INFO_DSBUF_INC_SZ - 1)/INFO_DSBUF_INC_SZ)*INFO_DSBUF_INC_SZ;
1080
size += dsbufp->size;
1081
ASSERT(dsbufp->str_len + need <= size);
1082
dsbufp->str = (char *) erts_realloc(ERTS_ALC_T_INFO_DSBUF,
1083
(void *) dsbufp->str,
1085
dsbufp->size = size;
1089
static erts_dsprintf_buf_t *
1090
erts_create_info_dsbuf(Uint size)
1092
Uint init_size = size ? size : INFO_DSBUF_INC_SZ;
1093
erts_dsprintf_buf_t init = ERTS_DSPRINTF_BUF_INITER(grow_info_dsbuf);
1094
erts_dsprintf_buf_t *dsbufp = erts_alloc(ERTS_ALC_T_INFO_DSBUF,
1095
sizeof(erts_dsprintf_buf_t));
1096
sys_memcpy((void *) dsbufp, (void *) &init, sizeof(erts_dsprintf_buf_t));
1097
dsbufp->str = (char *) erts_alloc(ERTS_ALC_T_INFO_DSBUF, init_size);
1098
dsbufp->str[0] = '\0';
1099
dsbufp->size = init_size;
1104
erts_destroy_info_dsbuf(erts_dsprintf_buf_t *dsbufp)
1107
erts_free(ERTS_ALC_T_INFO_DSBUF, (void *) dsbufp->str);
1108
erts_free(ERTS_ALC_T_INFO_DSBUF, (void *) dsbufp);
816
1112
BIF_RETTYPE system_info_1(BIF_ALIST_1)
823
1118
DECL_AM(ets_realloc_moves);
824
1119
DECL_AM(dist_ctrl);
828
1121
if (is_tuple(BIF_ARG_1)) {
829
1122
Eterm* tp = tuple_val(BIF_ARG_1);
830
1123
Uint arity = *tp++;
832
1125
if (is_non_value(res))
1128
} else if (BIF_ARG_1 == am_compat_rel) {
1129
ASSERT(erts_compat_rel > 0);
1130
BIF_RET(make_small(erts_compat_rel));
835
1131
} else if (BIF_ARG_1 == am_memory) {
836
BIF_RET(erts_memory(NULL, BIF_P, THE_NON_VALUE));
1132
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
1133
res = erts_memory(NULL, NULL, BIF_P, THE_NON_VALUE);
1134
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
837
1136
} else if (BIF_ARG_1 == am_allocated_areas) {
838
BIF_RET(erts_allocated_areas(NULL, BIF_P));
1137
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
1138
res = erts_allocated_areas(NULL, NULL, BIF_P);
1139
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
839
1141
} else if (BIF_ARG_1 == am_allocated) {
840
1142
BIF_RET(erts_instr_get_memory_map(BIF_P));
841
1143
} else if (BIF_ARG_1 == am_hipe_architecture) {
842
1144
#if defined(HIPE)
843
# define MAKE_STR2(x) #x
844
# define MAKE_STR(s) MAKE_STR2(s)
845
static char arch[] = MAKE_STR(HIPE_ARCHITECTURE);
846
BIF_RET(am_atom_put(arch, sizeof(arch) - 1));
1145
BIF_RET(hipe_arch_name);
849
1147
BIF_RET(am_undefined);
853
1151
} else if (BIF_ARG_1 == AM_ets_realloc_moves) {
854
1152
BIF_RET((erts_ets_realloc_always_moves) ? am_true : am_false);
855
1153
} else if (BIF_ARG_1 == am_sequential_tracer) {
856
if (is_pid(system_seq_tracer) || is_port(system_seq_tracer)) {
857
val = STORE_NC_IN_PROC(BIF_P, system_seq_tracer);
1154
val = erts_get_system_seq_tracer();
1155
ASSERT(is_internal_pid(val) || is_internal_port(val) || val==am_false)
861
1156
hp = HAlloc(BIF_P, 3);
862
1157
res = TUPLE2(hp, am_sequential_tracer, val);
864
1159
} else if (BIF_ARG_1 == am_garbage_collection){
1160
Uint val = (Uint) erts_smp_atomic_read(&erts_max_gen_gcs);
865
1161
hp = HAlloc(BIF_P, 3+2);
866
res = TUPLE2(hp, am_fullsweep_after, make_small(erts_max_gen_gcs));
1162
res = TUPLE2(hp, am_fullsweep_after, make_small(val));
868
1164
res = CONS(hp, res, NIL);
870
1166
} else if (BIF_ARG_1 == am_fullsweep_after){
1167
Uint val = (Uint) erts_smp_atomic_read(&erts_max_gen_gcs);
871
1168
hp = HAlloc(BIF_P, 3);
872
res = TUPLE2(hp, am_fullsweep_after, make_small(erts_max_gen_gcs));
1169
res = TUPLE2(hp, am_fullsweep_after, make_small(val));
874
1171
} else if (BIF_ARG_1 == am_process_count) {
876
for (i = 0; i < erts_max_processes; i++) {
877
if (process_tab[i] != NULL && process_tab[i]->status != P_EXITING) {
881
BIF_RET(make_small(count));
1172
BIF_RET(make_small(erts_process_count()));
882
1173
} else if (BIF_ARG_1 == am_process_limit) {
883
1174
BIF_RET(make_small(erts_max_processes));
884
} else if (BIF_ARG_1 == am_info) {
886
} else if (BIF_ARG_1 == am_procs)
888
else if (BIF_ARG_1 == am_loaded)
890
else if (BIF_ARG_1 == am_dist)
891
distribution_info(CBUF);
892
else if (BIF_ARG_1 == AM_dist_ctrl) {
1175
} else if (BIF_ARG_1 == am_info
1176
|| BIF_ARG_1 == am_procs
1177
|| BIF_ARG_1 == am_loaded
1178
|| BIF_ARG_1 == am_dist) {
1179
erts_dsprintf_buf_t *dsbufp = erts_create_info_dsbuf(0);
1181
/* Need to be the only thread running... */
1182
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
1183
erts_smp_block_system(0);
1185
if (BIF_ARG_1 == am_info)
1186
info(ERTS_PRINT_DSBUF, (void *) dsbufp);
1187
else if (BIF_ARG_1 == am_procs)
1188
process_info(ERTS_PRINT_DSBUF, (void *) dsbufp);
1189
else if (BIF_ARG_1 == am_loaded)
1190
loaded(ERTS_PRINT_DSBUF, (void *) dsbufp);
1192
distribution_info(ERTS_PRINT_DSBUF, (void *) dsbufp);
1194
erts_smp_release_system();
1195
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
1197
ASSERT(dsbufp && dsbufp->str);
1198
res = new_binary(BIF_P, (byte *) dsbufp->str, (int) dsbufp->str_len);
1199
erts_destroy_info_dsbuf(dsbufp);
1201
} else if (BIF_ARG_1 == AM_dist_ctrl) {
1204
ERTS_SMP_LOCK_NODE_TABLES_AND_ENTRIES;
895
1205
for (dep = erts_visible_dist_entries; dep; dep = dep->next)
897
1207
for (dep = erts_hidden_dist_entries; dep; dep = dep->next)
914
1224
res = CONS(hp, tpl, res);
1227
ERTS_SMP_UNLOCK_NODE_TABLES_AND_ENTRIES;
918
1229
} else if (BIF_ARG_1 == am_system_version) {
922
sys_ver = erts_get_system_version(&sys_ver_len);
923
hp = HAlloc(BIF_P, sys_ver_len*2);
924
BIF_RET(buf_to_intlist(&hp, sys_ver, sys_ver_len, NIL));
1230
erts_dsprintf_buf_t *dsbufp = erts_create_tmp_dsbuf(0);
1231
erts_print_system_version(ERTS_PRINT_DSBUF, (void *) dsbufp, BIF_P);
1232
hp = HAlloc(BIF_P, dsbufp->str_len*2);
1233
res = buf_to_intlist(&hp, dsbufp->str, dsbufp->str_len, NIL);
1234
erts_destroy_tmp_dsbuf(dsbufp);
925
1236
} else if (BIF_ARG_1 == am_system_architecture) {
928
sys_strcpy((char*)tmp_buf, ERLANG_ARCHITECTURE);
929
n = sys_strlen((char*)tmp_buf);
930
hp = HAlloc(BIF_P, n*2);
931
BIF_RET(buf_to_intlist(&hp, tmp_buf, n, NIL));
1237
hp = HAlloc(BIF_P, 2*(sizeof(ERLANG_ARCHITECTURE)-1));
1238
BIF_RET(buf_to_intlist(&hp,
1239
ERLANG_ARCHITECTURE,
1240
sizeof(ERLANG_ARCHITECTURE)-1,
933
1243
else if (BIF_ARG_1 == am_memory_types) {
934
1244
return erts_instr_get_type_info(BIF_P);
1056
1368
else if (BIF_ARG_1 == am_version) {
1057
1369
int n = strlen(ERLANG_VERSION);
1058
1370
hp = HAlloc(BIF_P, ((sizeof ERLANG_VERSION)-1) * 2);
1059
BIF_RET(buf_to_intlist(&hp, (byte*)ERLANG_VERSION, n, NIL));
1371
BIF_RET(buf_to_intlist(&hp, ERLANG_VERSION, n, NIL));
1061
1373
else if (BIF_ARG_1 == am_machine) {
1062
1374
int n = strlen(EMULATOR);
1063
1375
hp = HAlloc(BIF_P, n*2);
1064
BIF_RET(buf_to_intlist(&hp, (byte*)EMULATOR, n, NIL));
1376
BIF_RET(buf_to_intlist(&hp, EMULATOR, n, NIL));
1066
1378
else if (BIF_ARG_1 == am_garbage_collection) {
1067
1379
BIF_RET(am_generational);
1380
#ifndef ERTS_SMP /* Not supported with smp emulator */
1068
1381
} else if (BIF_ARG_1 == am_instruction_counts) {
1070
hp = HAlloc(BIF_P, num_instructions*5);
1393
bld_instruction_counts:
1072
1396
for (i = num_instructions-1; i >= 0; i--) {
1074
Eterm atom = am_atom_put(opc[i].name, strlen(opc[i].name));
1075
Eterm count = make_small_or_big(opc[i].count, BIF_P);
1077
tuple = TUPLE2(hp, atom, count);
1079
res = CONS(hp, tuple, res);
1397
res = erts_bld_cons(hpp, hszp,
1398
erts_bld_tuple(hpp, hszp, 2,
1399
am_atom_put(opc[i].name,
1400
strlen(opc[i].name)),
1401
erts_bld_uint(hpp, hszp,
1407
hp = HAlloc(BIF_P, hsz);
1413
goto bld_instruction_counts;
1421
#endif /* #ifndef ERTS_SMP */
1083
1422
} else if (BIF_ARG_1 == am_wordsize) {
1084
1423
return make_small(sizeof(Eterm));
1085
1424
} else if (BIF_ARG_1 == am_endian) {
1185
1529
return am_false;
1187
1531
/* Arguments that are unusual... */
1188
DECL_AM(node_and_dist_references);
1532
DECL_AM(constant_pool_support);
1533
DECL_AM(scheduler_id);
1534
DECL_AM(schedulers);
1535
DECL_AM(smp_support);
1536
DECL_AM(lock_checking);
1537
DECL_AM(kernel_poll);
1189
1539
DECL_AM(stop_memory_trace);
1191
if (BIF_ARG_1 == AM_node_and_dist_references) {
1193
* OBSERVE! Only supposed to be used for testing, and debugging.
1195
BIF_RET(erts_get_node_and_dist_references(BIF_P));
1541
if (BIF_ARG_1 == AM_smp_support) {
1547
} else if (BIF_ARG_1 == AM_constant_pool_support) {
1548
#if defined(HEAP_FRAG_ELIM_TEST)
1553
} else if (BIF_ARG_1 == AM_scheduler_id) {
1555
ASSERT(BIF_P->scheduler_data);
1556
BIF_RET(erts_make_integer(BIF_P->scheduler_data->no, BIF_P));
1558
BIF_RET(make_small(1));
1560
} else if (BIF_ARG_1 == AM_schedulers) {
1561
res = make_small(erts_get_no_schedulers());
1563
} else if (BIF_ARG_1 == AM_kernel_poll) {
1564
#ifdef ERTS_ENABLE_KERNEL_POLL
1565
BIF_RET(erts_use_kernel_poll ? am_true : am_false);
1569
} else if (BIF_ARG_1 == AM_lock_checking) {
1570
#ifdef ERTS_ENABLE_LOCK_CHECK
1575
} else if (BIF_ARG_1 == AM_check_io) {
1576
BIF_RET(erts_check_io_info(BIF_P));
1196
1577
} else if (BIF_ARG_1 == AM_stop_memory_trace) {
1197
1578
erts_mtrace_stop();
1198
1579
BIF_RET(am_true);
1309
1683
res = make_small(internal_port_number(portid));
1311
1685
else if (item == am_links) {
1686
MonitorInfoCollection mic;
1316
for (lnk = erts_port[portix].links; lnk; lnk = lnk->next) {
1317
if (lnk->type == LNK_LINK) {
1318
sz += NC_HEAP_SIZE(lnk->item);
1322
hp = HAlloc(BIF_P, 3 + sz);
1690
INIT_MONITOR_INFOS(mic);
1692
erts_doforall_links(prt->nlinks, &collect_one_link, &mic);
1694
hp = HAlloc(BIF_P, 3 + mic.sz);
1324
for (lnk = erts_port[portix].links; lnk; lnk = lnk->next) {
1325
if (lnk->type == LNK_LINK) {
1326
item = STORE_NC(&hp, &MSO(BIF_P).externals, lnk->item);
1327
res = CONS(hp, item, res);
1696
for (i = 0; i < mic.mi_i; i++) {
1697
item = STORE_NC(&hp, &MSO(BIF_P).externals, mic.mi[i].entity);
1698
res = CONS(hp, item, res);
1701
DESTROY_MONITOR_INFOS(mic);
1332
1704
else if (item == am_name) {
1333
count = sys_strlen(erts_port[portix].name);
1705
count = sys_strlen(prt->name);
1335
1707
hp = HAlloc(BIF_P, 3 + 2*count);
1336
res = buf_to_intlist(&hp,(byte*)erts_port[portix].name,count,NIL);
1708
res = buf_to_intlist(&hp, prt->name, count, NIL);
1338
1710
else if (item == am_connected) {
1339
1711
hp = HAlloc(BIF_P, 3);
1340
res = erts_port[portix].connected; /* internal pid */
1712
res = prt->connected; /* internal pid */
1342
1714
else if (item == am_input) {
1343
hp = HAlloc(BIF_P, 3);
1344
res = make_small_or_big(erts_port[portix].bytes_in, BIF_P);
1716
Uint n = prt->bytes_in;
1717
(void) erts_bld_uint(NULL, &hsz, n);
1718
hp = HAlloc(BIF_P, hsz);
1719
res = erts_bld_uint(&hp, NULL, n);
1346
1721
else if (item == am_output) {
1347
hp = HAlloc(BIF_P, 3);
1348
res = make_small_or_big(erts_port[portix].bytes_out, BIF_P);
1723
Uint n = prt->bytes_out;
1724
(void) erts_bld_uint(NULL, &hsz, n);
1725
hp = HAlloc(BIF_P, hsz);
1726
res = erts_bld_uint(&hp, NULL, n);
1350
1728
else if (item == am_registered_name) {
1352
hp = HAlloc(BIF_P, 3);
1353
reg = erts_port[portix].reg;
1732
ERTS_BIF_PREP_RET(ret, NIL);
1735
hp = HAlloc(BIF_P, 3);
1357
1736
res = reg->name;
1359
1739
else if (item == am_memory) {
1360
1740
/* All memory consumed in bytes (the Port struct should not be
1471
if (is_not_atom(BIF_ARG_1))
1472
BIF_ERROR(BIF_P, BADARG);
1474
1913
if (BIF_ARG_1 == am_context_switches) {
1914
Eterm cs = erts_make_integer(erts_get_total_context_switches(), BIF_P);
1475
1915
hp = HAlloc(BIF_P, 3);
1476
res = TUPLE2(hp, make_small_or_big(context_switches, BIF_P), SMALL_ZERO);
1479
else if (BIF_ARG_1 == am_garbage_collection) {
1480
hp = HAlloc(BIF_P, 4);
1481
res = TUPLE3(hp, make_small_or_big(garbage_cols, BIF_P),
1482
make_small_or_big(reclaimed, BIF_P),
1486
else if (BIF_ARG_1 == am_reductions) {
1490
reds = reductions + erts_current_reductions(BIF_P, BIF_P);
1491
b1 = make_small_or_big(reds, BIF_P);
1492
b2 = make_small_or_big(reds - last_reds, BIF_P);
1493
hp = HAlloc(BIF_P,3);
1494
res = TUPLE2(hp, b1, b2);
1498
else if (BIF_ARG_1 == am_runtime) {
1916
res = TUPLE2(hp, cs, SMALL_ZERO);
1918
} else if (BIF_ARG_1 == am_garbage_collection) {
1923
erts_gc_info(&gc_info);
1924
(void) erts_bld_uint(NULL, &hsz, gc_info.garbage_collections);
1925
(void) erts_bld_uint(NULL, &hsz, gc_info.reclaimed);
1926
hp = HAlloc(BIF_P, hsz);
1927
gcs = erts_bld_uint(&hp, NULL, gc_info.garbage_collections);
1928
recl = erts_bld_uint(&hp, NULL, gc_info.reclaimed);
1929
res = TUPLE3(hp, gcs, recl, SMALL_ZERO);
1931
} else if (BIF_ARG_1 == am_reductions) {
1937
erts_get_total_reductions(&reds, &diff);
1938
(void) erts_bld_uint(NULL, &hsz, reds);
1939
(void) erts_bld_uint(NULL, &hsz, diff);
1940
hp = HAlloc(BIF_P, hsz);
1941
b1 = erts_bld_uint(&hp, NULL, reds);
1942
b2 = erts_bld_uint(&hp, NULL, diff);
1943
res = TUPLE2(hp, b1, b2);
1945
} else if (BIF_ARG_1 == am_exact_reductions) {
1951
erts_get_exact_total_reductions(BIF_P, &reds, &diff);
1952
(void) erts_bld_uint(NULL, &hsz, reds);
1953
(void) erts_bld_uint(NULL, &hsz, diff);
1954
hp = HAlloc(BIF_P, hsz);
1955
b1 = erts_bld_uint(&hp, NULL, reds);
1956
b2 = erts_bld_uint(&hp, NULL, diff);
1957
res = TUPLE2(hp, b1, b2);
1959
} else if (BIF_ARG_1 == am_runtime) {
1499
1960
unsigned long u1, u2, dummy;
1501
1962
elapsed_time_both(&u1,&dummy,&u2,&dummy);
1502
b1 = make_small_or_big(u1,BIF_P);
1503
b2 = make_small_or_big(u2,BIF_P);
1963
b1 = erts_make_integer(u1,BIF_P);
1964
b2 = erts_make_integer(u2,BIF_P);
1504
1965
hp = HAlloc(BIF_P,3);
1505
1966
res = TUPLE2(hp, b1, b2);
1508
else if (BIF_ARG_1 == am_run_queue) {
1968
} else if (BIF_ARG_1 == am_run_queue) {
1509
1969
res = sched_q_len();
1510
1970
BIF_RET(make_small(res));
1512
else if (BIF_ARG_1 == am_wall_clock) {
1971
} else if (BIF_ARG_1 == am_wall_clock) {
1515
1974
wall_clock_elapsed_time_both(&w1, &w2);
1516
b1 = make_small_or_big(w1,BIF_P);
1517
b2 = make_small_or_big(w2,BIF_P);
1975
b1 = erts_make_integer(w1,BIF_P);
1976
b2 = erts_make_integer(w2,BIF_P);
1518
1977
hp = HAlloc(BIF_P,3);
1519
1978
res = TUPLE2(hp, b1, b2);
1522
else if (BIF_ARG_1 == am_io) {
1980
} else if (BIF_ARG_1 == am_io) {
1525
in = make_small_or_big(bytes_in,BIF_P);
1526
out = make_small_or_big(bytes_out,BIF_P);
1527
hp = HAlloc(BIF_P, 9);
1985
erts_smp_io_safe_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
1987
(void) erts_bld_uint(NULL, &hsz, bytes_in);
1988
(void) erts_bld_uint(NULL, &hsz, bytes_out);
1989
hp = HAlloc(BIF_P, hsz);
1990
in = erts_bld_uint(&hp, NULL, bytes_in);
1991
out = erts_bld_uint(&hp, NULL, bytes_out);
1993
erts_smp_io_unlock();
1528
1995
r1 = TUPLE2(hp, am_input, in);
1530
1997
r2 = TUPLE2(hp, am_output, out);
1539
2006
BIF_RET(erts_error_logger_warnings);
2009
static erts_smp_atomic_t available_internal_state;
2011
BIF_RETTYPE erts_debug_get_internal_state_1(BIF_ALIST_1)
2014
* NOTE: Only supposed to be used for testing, and debugging.
2017
if (!erts_smp_atomic_read(&available_internal_state)) {
2018
BIF_ERROR(BIF_P, EXC_UNDEF);
2021
if (is_atom(BIF_ARG_1)) {
2022
DECL_AM(node_and_dist_references);
2023
DECL_AM(DbTable_words);
2026
DECL_AM(check_io_debug);
2027
DECL_AM(available_internal_state);
2029
if (BIF_ARG_1 == AM_node_and_dist_references) {
2030
/* Used by node_container_SUITE (emulator) */
2031
Eterm res = erts_get_node_and_dist_references(BIF_P);
2034
else if (BIF_ARG_1 == AM_next_pid || BIF_ARG_1 == AM_next_port) {
2035
/* Used by node_container_SUITE (emulator) */
2037
if (BIF_ARG_1 == AM_next_pid)
2038
res = erts_test_next_pid(0, 0);
2040
erts_smp_io_safe_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
2041
res = erts_test_next_port(0, 0);
2042
erts_smp_io_unlock();
2046
BIF_RET(erts_make_integer(res, BIF_P));
2048
else if (BIF_ARG_1 == AM_DbTable_words) {
2049
/* Used by ets_SUITE (stdlib) */
2050
size_t words = (sizeof(DbTable) + sizeof(Uint) - 1)/sizeof(Uint);
2051
BIF_RET(make_small((Uint) words));
2053
else if (BIF_ARG_1 == AM_check_io_debug) {
2054
/* Used by (emulator) */
2056
#ifdef HAVE_ERTS_CHECK_IO_DEBUG
2057
res = erts_check_io_debug();
2062
BIF_RET(erts_make_integer((Uint) res, BIF_P));
2064
else if (BIF_ARG_1 == AM_available_internal_state) {
2068
else if (is_tuple(BIF_ARG_1)) {
2069
Eterm* tp = tuple_val(BIF_ARG_1);
2070
switch (arityval(tp[0])) {
2073
DECL_AM(monitor_list);
2074
DECL_AM(channel_number);
2075
DECL_AM(have_pending_exit);
2077
if (tp[1] == AM_link_list) {
2078
/* Used by erl_link_SUITE (emulator) */
2079
if(is_internal_pid(tp[2])) {
2083
p = erts_pid2proc(BIF_P,
2084
ERTS_PROC_LOCK_MAIN,
2086
ERTS_PROC_LOCK_LINK);
2088
ERTS_SMP_ASSERT_IS_NOT_EXITING(BIF_P);
2089
BIF_RET(am_undefined);
2091
res = make_link_list(BIF_P, p->nlinks, NIL);
2092
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_LINK);
2095
else if(is_internal_port(tp[2])) {
2097
Port *p = erts_id2port(tp[2], BIF_P, ERTS_PROC_LOCK_MAIN);
2099
res = make_link_list(BIF_P, p->nlinks, NIL);
2102
erts_smp_io_unlock();
2105
else if(is_node_name_atom(tp[2])) {
2106
DistEntry *dep = erts_find_dist_entry(tp[2]);
2109
erts_smp_dist_entry_lock(dep);
2110
subres = make_link_list(BIF_P, dep->nlinks, NIL);
2111
subres = make_link_list(BIF_P, dep->node_links, subres);
2112
erts_smp_dist_entry_unlock(dep);
2113
erts_deref_dist_entry(dep);
2116
BIF_RET(am_undefined);
2120
else if (tp[1] == AM_monitor_list) {
2121
/* Used by erl_link_SUITE (emulator) */
2122
if(is_internal_pid(tp[2])) {
2126
p = erts_pid2proc(BIF_P,
2127
ERTS_PROC_LOCK_MAIN,
2129
ERTS_PROC_LOCK_LINK);
2131
ERTS_SMP_ASSERT_IS_NOT_EXITING(BIF_P);
2132
BIF_RET(am_undefined);
2134
res = make_monitor_list(BIF_P, p->monitors);
2135
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_LINK);
2137
} else if(is_node_name_atom(tp[2])) {
2138
DistEntry *dep = erts_find_dist_entry(tp[2]);
2141
erts_smp_dist_entry_lock(dep);
2142
ml = make_monitor_list(BIF_P, dep->monitors);
2143
erts_smp_dist_entry_unlock(dep);
2144
erts_deref_dist_entry(dep);
2147
BIF_RET(am_undefined);
2151
else if (tp[1] == AM_channel_number) {
2153
DistEntry *dep = erts_find_dist_entry(tp[2]);
2157
Uint cno = dist_entry_channel_no(dep);
2158
res = make_small(cno);
2159
erts_deref_dist_entry(dep);
2163
else if (tp[1] == AM_have_pending_exit) {
2164
Process *rp = erts_pid2proc(BIF_P, ERTS_PROC_LOCK_MAIN,
2165
tp[2], ERTS_PROC_LOCK_STATUS);
2167
BIF_RET(am_undefined);
2170
Eterm res = ERTS_PROC_PENDING_EXIT(rp) ? am_true : am_false;
2171
erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_STATUS);
2182
BIF_ERROR(BIF_P, BADARG);
2185
BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2)
2187
DECL_AM(available_internal_state);
2189
* NOTE: Only supposed to be used for testing, and debugging.
2192
if (BIF_ARG_1 == AM_available_internal_state
2193
&& (BIF_ARG_2 == am_true || BIF_ARG_2 == am_false)) {
2194
long on = (long) (BIF_ARG_2 == am_true);
2195
long prev_on = erts_smp_atomic_xchg(&available_internal_state, on);
2197
erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf();
2198
erts_dsprintf(dsbufp, "Process %T ", BIF_P->id);
2199
if (erts_is_alive())
2200
erts_dsprintf(dsbufp, "on node %T ", erts_this_node->sysname);
2201
erts_dsprintf(dsbufp,
2202
"enabled access to the emulator internal state.\n");
2203
erts_dsprintf(dsbufp,
2204
"NOTE: This is an erts internal test feature and "
2205
"should *only* be used by OTP test-suites.\n");
2206
erts_send_warning_to_logger(BIF_P->group_leader, dsbufp);
2208
BIF_RET(prev_on ? am_true : am_false);
2211
if (!erts_smp_atomic_read(&available_internal_state)) {
2212
BIF_ERROR(BIF_P, EXC_UNDEF);
2215
if (is_atom(BIF_ARG_1)) {
2218
DECL_AM(send_fake_exit_signal);
2220
if (BIF_ARG_1 == AM_next_pid || BIF_ARG_1 == AM_next_port) {
2221
/* Used by node_container_SUITE (emulator) */
2224
if (term_to_Uint(BIF_ARG_2, &next) != 0) {
2227
if (BIF_ARG_1 == AM_next_pid)
2228
res = erts_test_next_pid(1, next);
2230
erts_smp_io_safe_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
2231
res = erts_test_next_port(1, next);
2232
erts_smp_io_unlock();
2236
BIF_RET(erts_make_integer(res, BIF_P));
2239
else if (BIF_ARG_1 == AM_send_fake_exit_signal) {
2240
/* Used by signal_SUITE (emulator) */
2242
/* Testcases depend on the exit being received via
2243
a pending exit when the receiver is the same as
2245
if (is_tuple(BIF_ARG_2)) {
2246
Eterm* tp = tuple_val(BIF_ARG_2);
2247
if (arityval(tp[0]) == 3
2248
&& (is_pid(tp[1]) || is_port(tp[1]))
2249
&& is_internal_pid(tp[2])) {
2251
Uint32 rp_locks = ERTS_PROC_LOCKS_XSIG_SEND;
2252
Process *rp = erts_pid2proc(BIF_P, ERTS_PROC_LOCK_MAIN,
2261
rp_locks |= ERTS_PROC_LOCK_MAIN;
2263
xres = erts_send_exit_signal(NULL, /* NULL in order to
2264
force a pending exit
2276
rp_locks &= ~ERTS_PROC_LOCK_MAIN;
2278
erts_smp_proc_unlock(rp, rp_locks);
2281
BIF_RET(AM_message);
2283
else if (xres == 0) {
2284
DECL_AM(unaffected);
2285
BIF_RET(AM_unaffected);
2296
BIF_ERROR(BIF_P, BADARG);
1543
2300
erts_bif_info_init(void)
2302
#if defined(PURIFY) || defined(VALGRIND)
2303
INIT_AM(error_checker);
2308
erts_smp_atomic_init(&available_internal_state, 0);