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; }
void erts_factory_trim_and_close(ErtsHeapFactory* factory, Eterm *brefs, Uint brefs_size) { ErlHeapFragment *bp; switch (factory->mode) { case FACTORY_MESSAGE: { ErtsMessage *mp = factory->message; if (mp->data.attached == ERTS_MSG_COMBINED_HFRAG) { if (!factory->heap_frags) { Uint sz = factory->hp - factory->hp_start; mp = erts_shrink_message(mp, sz, brefs, brefs_size); factory->message = mp; factory->mode = FACTORY_CLOSED; return; } /*else we don't trim multi fragmented messages for now (off_heap...) */ break; } /* Fall through... */ } case FACTORY_HEAP_FRAGS: bp = factory->heap_frags; if (!bp) break; if (bp->next == NULL) { Uint used_sz = factory->hp - bp->mem; ASSERT(used_sz <= bp->alloc_size); if (used_sz > 0) { if (used_sz != bp->alloc_size) bp = erts_resize_message_buffer(bp, used_sz, brefs, brefs_size); } else { free_message_buffer(bp); bp = NULL; } factory->heap_frags = bp; if (factory->mode == FACTORY_MESSAGE) factory->message->data.heap_frag = bp; factory->mode = FACTORY_CLOSED; return; } /*else we don't trim multi fragmented messages for now (off_heap...) */ default: break; } erts_factory_close(factory); }
void erts_factory_trim_and_close(ErtsHeapFactory* factory, Eterm *brefs, Uint brefs_size) { if (factory->mode == FACTORY_HEAP_FRAGS) { ErlHeapFragment* bp = factory->heap_frags; if (bp->next == NULL) { Uint used_sz = factory->hp - bp->mem; ASSERT(used_sz <= bp->alloc_size); factory->heap_frags = erts_resize_message_buffer(bp, used_sz, brefs, brefs_size); factory->mode = FACTORY_CLOSED; return; } /*else we don't trim multi fragmented messages for now */ } erts_factory_close(factory); }
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); }