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 }
void erts_link_mbuf_to_proc(Process *proc, ErlHeapFragment *first_bp) { if (first_bp) { ErlHeapFragment *bp = first_bp; while (1) { /* Move any off_heap's into the process */ if (bp->off_heap.first != NULL) { struct erl_off_heap_header** next_p = &bp->off_heap.first; while (*next_p != NULL) { next_p = &((*next_p)->next); } *next_p = MSO(proc).first; MSO(proc).first = bp->off_heap.first; bp->off_heap.first = NULL; OH_OVERHEAD(&(MSO(proc)), bp->off_heap.overhead); } MBUF_SIZE(proc) += bp->used_size; if (!bp->next) break; bp = bp->next; } /* Link the message buffer */ bp->next = MBUF(proc); MBUF(proc) = first_bp; } }
static ERTS_INLINE void link_mbuf_to_proc(Process *proc, ErlHeapFragment *bp) { if (bp) { /* Link the message buffer */ bp->next = MBUF(proc); MBUF(proc) = bp; MBUF_SIZE(proc) += bp->size; MSO(proc).overhead += proc->heap_sz; /* Force GC */ /* Move any binaries into the process */ if (bp->off_heap.mso != NULL) { ProcBin** next_p = &bp->off_heap.mso; while (*next_p != NULL) { next_p = &((*next_p)->next); } *next_p = MSO(proc).mso; MSO(proc).mso = bp->off_heap.mso; bp->off_heap.mso = NULL; MSO(proc).overhead += bp->off_heap.overhead; } /* Move any funs into the process */ #ifndef HYBRID if (bp->off_heap.funs != NULL) { ErlFunThing** next_p = &bp->off_heap.funs; while (*next_p != NULL) { next_p = &((*next_p)->next); } *next_p = MSO(proc).funs; MSO(proc).funs = bp->off_heap.funs; bp->off_heap.funs = NULL; } #endif /* Move any external things into the process */ if (bp->off_heap.externals != NULL) { ExternalThing** next_p = &bp->off_heap.externals; while (*next_p != NULL) { next_p = &((*next_p)->next); } *next_p = MSO(proc).externals; MSO(proc).externals = bp->off_heap.externals; bp->off_heap.externals = NULL; } } }
static ERTS_INLINE void link_mbuf_to_proc(Process *proc, ErlHeapFragment *bp) { if (bp) { /* Link the message buffer */ bp->next = MBUF(proc); MBUF(proc) = bp; MBUF_SIZE(proc) += bp->used_size; FLAGS(proc) |= F_FORCE_GC; /* Move any off_heap's into the process */ if (bp->off_heap.first != NULL) { struct erl_off_heap_header** next_p = &bp->off_heap.first; while (*next_p != NULL) { next_p = &((*next_p)->next); } *next_p = MSO(proc).first; MSO(proc).first = bp->off_heap.first; bp->off_heap.first = NULL; OH_OVERHEAD(&(MSO(proc)), bp->off_heap.overhead); } } }
/* Display info about an individual Erlang process */ void print_process_info(int to, void *to_arg, Process *p) { time_t approx_started; int garbing = 0; int running = 0; struct saved_calls *scb; erts_aint32_t state; /* display the PID */ erts_print(to, to_arg, "=proc:%T\n", p->common.id); /* Display the state */ erts_print(to, to_arg, "State: "); state = erts_smp_atomic32_read_acqb(&p->state); erts_dump_process_state(to, to_arg, state); if (state & ERTS_PSFLG_GC) { garbing = 1; running = 1; } else if (state & ERTS_PSFLG_RUNNING) running = 1; /* * If the process is registered as a global process, display the * registered name */ if (p->common.u.alive.reg) erts_print(to, to_arg, "Name: %T\n", p->common.u.alive.reg->name); /* * Display the initial function name */ erts_print(to, to_arg, "Spawned as: %T:%T/%bpu\n", p->u.initial[INITIAL_MOD], p->u.initial[INITIAL_FUN], p->u.initial[INITIAL_ARI]); if (p->current != NULL) { if (running) { erts_print(to, to_arg, "Last scheduled in for: "); } else { erts_print(to, to_arg, "Current call: "); } erts_print(to, to_arg, "%T:%T/%bpu\n", p->current[0], p->current[1], p->current[2]); } erts_print(to, to_arg, "Spawned by: %T\n", p->parent); approx_started = (time_t) p->approx_started; erts_print(to, to_arg, "Started: %s", ctime(&approx_started)); ERTS_SMP_MSGQ_MV_INQ2PRIVQ(p); erts_print(to, to_arg, "Message queue length: %d\n", p->msg.len); /* display the message queue only if there is anything in it */ if (!ERTS_IS_CRASH_DUMPING && p->msg.first != NULL && !garbing) { ErlMessage* mp; erts_print(to, to_arg, "Message queue: ["); for (mp = p->msg.first; mp; mp = mp->next) erts_print(to, to_arg, mp->next ? "%T," : "%T", ERL_MESSAGE_TERM(mp)); erts_print(to, to_arg, "]\n"); } { int frags = 0; ErlHeapFragment *m = p->mbuf; while (m != NULL) { frags++; m = m->next; } erts_print(to, to_arg, "Number of heap fragments: %d\n", frags); } erts_print(to, to_arg, "Heap fragment data: %beu\n", MBUF_SIZE(p)); scb = ERTS_PROC_GET_SAVED_CALLS_BUF(p); if (scb) { int i, j; erts_print(to, to_arg, "Last calls:"); for (i = 0; i < scb->n; i++) { erts_print(to, to_arg, " "); j = scb->cur - i - 1; if (j < 0) j += scb->len; if (scb->ct[j] == &exp_send) erts_print(to, to_arg, "send"); else if (scb->ct[j] == &exp_receive) erts_print(to, to_arg, "'receive'"); else if (scb->ct[j] == &exp_timeout) erts_print(to, to_arg, "timeout"); else erts_print(to, to_arg, "%T:%T/%bpu\n", scb->ct[j]->code[0], scb->ct[j]->code[1], scb->ct[j]->code[2]); } erts_print(to, to_arg, "\n"); } /* display the links only if there are any*/ if (ERTS_P_LINKS(p) || ERTS_P_MONITORS(p)) { PrintMonitorContext context = {1,to}; erts_print(to, to_arg,"Link list: ["); erts_doforall_links(ERTS_P_LINKS(p), &doit_print_link, &context); erts_doforall_monitors(ERTS_P_MONITORS(p), &doit_print_monitor, &context); erts_print(to, to_arg,"]\n"); } if (!ERTS_IS_CRASH_DUMPING) { /* and the dictionary */ if (p->dictionary != NULL && !garbing) { erts_print(to, to_arg, "Dictionary: "); erts_dictionary_dump(to, to_arg, p->dictionary); erts_print(to, to_arg, "\n"); } } /* print the number of reductions etc */ erts_print(to, to_arg, "Reductions: %beu\n", p->reds); erts_print(to, to_arg, "Stack+heap: %beu\n", p->heap_sz); erts_print(to, to_arg, "OldHeap: %bpu\n", (OLD_HEAP(p) == NULL) ? 0 : (OLD_HEND(p) - OLD_HEAP(p)) ); erts_print(to, to_arg, "Heap unused: %bpu\n", (p->hend - p->htop)); erts_print(to, to_arg, "OldHeap unused: %bpu\n", (OLD_HEAP(p) == NULL) ? 0 : (OLD_HEND(p) - OLD_HTOP(p)) ); erts_print(to, to_arg, "Memory: %beu\n", erts_process_memory(p)); if (garbing) { print_garb_info(to, to_arg, p); } if (ERTS_IS_CRASH_DUMPING) { erts_program_counter_info(to, to_arg, p); } else { erts_print(to, to_arg, "Stack dump:\n"); #ifdef ERTS_SMP if (!garbing) #endif erts_stack_dump(to, to_arg, p); } /* Display all states */ erts_print(to, to_arg, "Internal State: "); erts_dump_extended_process_state(to, to_arg, state); }