/* * Creates a structure looking like this * #{ type => scheduler, id => 1, counters => #{ State1 => Counter1 ... StateN => CounterN}} */ static Eterm erts_msacc_gather_stats(ErtsMsAcc *msacc, ErtsHeapFactory *factory) { Uint sz = 0; Eterm *hp, cvs[ERTS_MSACC_STATE_COUNT]; Eterm key, state_map; int i; flatmap_t *map; hp = erts_produce_heap(factory, 4, 0); key = TUPLE3(hp,am_counters,am_id,am_type); for (i = 0; i < ERTS_MSACC_STATE_COUNT; i++) { cvs[i] = erts_bld_sint64(NULL, &sz,(Sint64)msacc->counters[i].pc); #ifdef ERTS_MSACC_STATE_COUNTERS erts_bld_uint64(NULL,&sz,msacc->counters[i].sc); sz += 3; #endif } hp = erts_produce_heap(factory, sz, 0); for (i = 0; i < ERTS_MSACC_STATE_COUNT; i++) { cvs[i] = erts_bld_sint64(&hp,NULL,(Sint64)msacc->counters[i].pc); #ifdef ERTS_MSACC_STATE_COUNTERS Eterm counter__ = erts_bld_uint64(&hp,NULL,msacc->counters[i].sc); cvs[i] = TUPLE2(hp,cvs[i],counter__); hp += 3; #endif } state_map = erts_map_from_ks_and_vs(factory, erts_msacc_state_atoms, cvs, ERTS_MSACC_STATE_COUNT); hp = erts_produce_heap(factory, MAP_HEADER_FLATMAP_SZ + 3, 0); map = (flatmap_t*)hp; hp += MAP_HEADER_FLATMAP_SZ; map->thing_word = MAP_HEADER_FLATMAP; map->size = 3; map->keys = key; hp[0] = state_map; hp[1] = msacc->id; hp[2] = am_atom_put(msacc->type,strlen(msacc->type)); return make_flatmap(map); }
Eterm erts_msg_distext2heap(Process *pp, ErtsProcLocks *plcksp, ErlHeapFragment **bpp, Eterm *tokenp, ErtsDistExternal *dist_extp) { Eterm msg; Uint tok_sz = 0; Eterm *hp = NULL; ErtsHeapFactory factory; Sint sz; *bpp = NULL; sz = erts_decode_dist_ext_size(dist_extp); if (sz < 0) goto decode_error; if (is_not_nil(*tokenp)) { ErlHeapFragment *heap_frag = erts_dist_ext_trailer(dist_extp); tok_sz = heap_frag->used_size; sz += tok_sz; } if (pp) { ErlOffHeap *ohp; hp = erts_alloc_message_heap(sz, bpp, &ohp, pp, plcksp); } else { *bpp = new_message_buffer(sz); hp = (*bpp)->mem; } erts_factory_message_init(&factory, pp, hp, *bpp); msg = erts_decode_dist_ext(&factory, dist_extp); if (is_non_value(msg)) goto decode_error; if (is_not_nil(*tokenp)) { ErlHeapFragment *heap_frag = erts_dist_ext_trailer(dist_extp); hp = erts_produce_heap(&factory, tok_sz, 0); *tokenp = copy_struct(*tokenp, tok_sz, &hp, factory.off_heap); erts_cleanup_offheap(&heap_frag->off_heap); } erts_free_dist_ext_copy(dist_extp); erts_factory_close(&factory); return msg; decode_error: if (is_not_nil(*tokenp)) { ErlHeapFragment *heap_frag = erts_dist_ext_trailer(dist_extp); erts_cleanup_offheap(&heap_frag->off_heap); } erts_free_dist_ext_copy(dist_extp); *bpp = NULL; return THE_NON_VALUE; }
static void send_reply(ErtsMsAcc *msacc, ErtsMSAccReq *msaccrp) { ErtsSchedulerData *esdp = erts_get_scheduler_data(); Process *rp = msaccrp->proc; ErtsMessage *msgp = NULL; Eterm *hp; Eterm ref_copy = NIL, msg; ErtsProcLocks rp_locks = (esdp && msaccrp->req_sched == esdp->no ? ERTS_PROC_LOCK_MAIN : 0); ErtsHeapFactory factory; if (msaccrp->action == ERTS_MSACC_GATHER) { msgp = erts_factory_message_create(&factory, rp, &rp_locks, DEFAULT_MSACC_MSG_SIZE); if (msacc->unmanaged) erts_mtx_lock(&msacc->mtx); hp = erts_produce_heap(&factory, REF_THING_SIZE + 3 /* tuple */, 0); ref_copy = STORE_NC(&hp, &msgp->hfrag.off_heap, msaccrp->ref); msg = erts_msacc_gather_stats(msacc, &factory); msg = TUPLE2(hp, ref_copy, msg); if (msacc->unmanaged) erts_mtx_unlock(&msacc->mtx); erts_factory_close(&factory); } else { ErlOffHeap *ohp = NULL; msgp = erts_alloc_message_heap(rp, &rp_locks, REF_THING_SIZE, &hp, &ohp); msg = STORE_NC(&hp, &msgp->hfrag.off_heap, msaccrp->ref); } erts_queue_message(rp, rp_locks, msgp, msg, am_system); if (esdp && msaccrp->req_sched == esdp->no) rp_locks &= ~ERTS_PROC_LOCK_MAIN; if (rp_locks) erts_smp_proc_unlock(rp, rp_locks); }