diff options
Diffstat (limited to 'erts')
-rw-r--r-- | erts/emulator/beam/erl_gc.c | 15 | ||||
-rw-r--r-- | erts/emulator/beam/erl_message.c | 15 | ||||
-rw-r--r-- | erts/emulator/beam/erl_message.h | 29 | ||||
-rw-r--r-- | erts/emulator/beam/erl_nif.c | 24 |
4 files changed, 60 insertions, 23 deletions
diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index 374da9407c..c7bbbd5ca0 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -2293,18 +2293,13 @@ move_msgq_to_heap(Process *p) free_message_buffer(bp); } else { - ErtsMessage *tmp = erts_alloc_message(0, NULL); - sys_memcpy((void *) tmp->m, (void *) mp->m, - sizeof(Eterm)*ERL_MESSAGE_REF_ARRAY_SZ); - tmp->next = mp->next; - if (p->msg.save == &mp->next) - p->msg.save = &tmp->next; - if (p->msg.last == &mp->next) - p->msg.last = &tmp->next; - *mpp = tmp; + ErtsMessage *new_mp = erts_alloc_message(0, NULL); + sys_memcpy((void *) new_mp->m, (void *) mp->m, + sizeof(Eterm)*ERL_MESSAGE_REF_ARRAY_SZ); + erts_msgq_replace_msg_ref(&p->msg, new_mp, mpp); mp->next = NULL; erts_cleanup_messages(mp); - mp = tmp; + mp = new_mp; } } diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c index d82532b354..ac7b9d6606 100644 --- a/erts/emulator/beam/erl_message.c +++ b/erts/emulator/beam/erl_message.c @@ -1345,10 +1345,10 @@ erts_prep_msgq_for_inspection(Process *c_p, Process *rp, mpp = i == 0 ? &rp->msg.first : &mip[i-1].msgp->next; - if (rp->msg.save == &bad_mp->next) - rp->msg.save = mpp; - if (rp->msg.last == &bad_mp->next) - rp->msg.last = mpp; + ASSERT((*mpp)->next == bad_mp); + + erts_msgq_update_internal_pointers(&rp->msg, mpp, &bad_mp->next); + mp = mp->next; *mpp = mp; rp->msg.len--; @@ -1385,12 +1385,7 @@ erts_prep_msgq_for_inspection(Process *c_p, Process *rp, sys_memcpy((void *) tmp->m, (void *) mp->m, sizeof(Eterm)*ERL_MESSAGE_REF_ARRAY_SZ); mpp = i == 0 ? &rp->msg.first : &mip[i-1].msgp->next; - tmp->next = mp->next; - if (rp->msg.save == &mp->next) - rp->msg.save = &tmp->next; - if (rp->msg.last == &mp->next) - rp->msg.last = &tmp->next; - *mpp = tmp; + erts_msgq_replace_msg_ref(&rp->msg, tmp, mpp); erts_save_message_in_proc(rp, mp); mp = tmp; } diff --git a/erts/emulator/beam/erl_message.h b/erts/emulator/beam/erl_message.h index 46063ea0c2..6df969367b 100644 --- a/erts/emulator/beam/erl_message.h +++ b/erts/emulator/beam/erl_message.h @@ -366,6 +366,12 @@ ERTS_GLB_FORCE_INLINE ErtsMessage *erts_shrink_message(ErtsMessage *mp, Uint sz, ERTS_GLB_FORCE_INLINE void erts_free_message(ErtsMessage *mp); ERTS_GLB_INLINE Uint erts_used_frag_sz(const ErlHeapFragment*); ERTS_GLB_INLINE Uint erts_msg_attached_data_size(ErtsMessage *msg); +ERTS_GLB_INLINE void erts_msgq_update_internal_pointers(ErlMessageQueue *msgq, + ErtsMessage **newpp, + ErtsMessage **oldpp); +ERTS_GLB_INLINE void erts_msgq_replace_msg_ref(ErlMessageQueue *msgq, + ErtsMessage *newp, + ErtsMessage **oldpp); #define ERTS_MSG_COMBINED_HFRAG ((void *) 0x1) @@ -468,6 +474,29 @@ ERTS_GLB_INLINE Uint erts_msg_attached_data_size(ErtsMessage *msg) return sz; } } + +ERTS_GLB_INLINE void +erts_msgq_update_internal_pointers(ErlMessageQueue *msgq, + ErtsMessage **newpp, + ErtsMessage **oldpp) +{ + if (msgq->save == oldpp) + msgq->save = newpp; + if (msgq->last == oldpp) + msgq->last = newpp; + if (msgq->saved_last == oldpp) + msgq->saved_last = newpp; +} + +ERTS_GLB_INLINE void +erts_msgq_replace_msg_ref(ErlMessageQueue *msgq, ErtsMessage *newp, ErtsMessage **oldpp) +{ + ErtsMessage *oldp = *oldpp; + newp->next = oldp->next; + erts_msgq_update_internal_pointers(msgq, &newp->next, &oldp->next); + *oldpp = newp; +} + #endif #endif diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 606b73c7b5..2bbb8e3c91 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -623,10 +623,28 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid, } } else { Uint sz = size_object(msg); + ErlOffHeap *ohp; Eterm *hp; - mp = erts_alloc_message(sz, &hp); - msg = copy_struct(msg, sz, &hp, &mp->hfrag.off_heap); - ASSERT(hp == mp->hfrag.mem+mp->hfrag.used_size); + if (env && !env->tracee) { + flush_env(env); + mp = erts_alloc_message_heap(rp, &rp_locks, sz, &hp, &ohp); + cache_env(env); + } + else { + erts_aint_t state = erts_smp_atomic32_read_nob(&rp->state); + if (state & ERTS_PSFLG_OFF_HEAP_MSGQ) { + mp = erts_alloc_message(sz, &hp); + ohp = sz == 0 ? NULL : &mp->hfrag.off_heap; + } + else { + ErlHeapFragment *bp = new_message_buffer(sz); + mp = erts_alloc_message(0, NULL); + mp->data.heap_frag = bp; + hp = bp->mem; + ohp = &bp->off_heap; + } + } + msg = copy_struct(msg, sz, &hp, ohp); } ERL_MESSAGE_TERM(mp) = msg; |