diff options
author | John Högberg <[email protected]> | 2017-11-07 09:31:24 +0100 |
---|---|---|
committer | John Högberg <[email protected]> | 2017-11-30 15:26:26 +0100 |
commit | 5036bf7d5006a6f1a4294b4a3b1f4120d39113ac (patch) | |
tree | d08757379bef5c9e5607c1da95909e4511d51cc9 /erts/emulator/beam | |
parent | f5e99a55d4d62074d2bd2e5a58c578a31bc214c8 (diff) | |
download | otp-5036bf7d5006a6f1a4294b4a3b1f4120d39113ac.tar.gz otp-5036bf7d5006a6f1a4294b4a3b1f4120d39113ac.tar.bz2 otp-5036bf7d5006a6f1a4294b4a3b1f4120d39113ac.zip |
Add enif_ioq_peek_head
This introduces a way to retrieve erlang terms from NIF IO queues
without having to resort to copying.
OTP-14797
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r-- | erts/emulator/beam/erl_nif.c | 49 | ||||
-rw-r--r-- | erts/emulator/beam/erl_nif.h | 3 | ||||
-rw-r--r-- | erts/emulator/beam/erl_nif_api_funcs.h | 2 |
3 files changed, 53 insertions, 1 deletions
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index dbcc894ac9..abb490cf9c 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -3605,6 +3605,55 @@ int enif_ioq_deq(ErlNifIOQueue *q, size_t elems, size_t *size) return 1; } +int enif_ioq_peek_head(ErlNifEnv *env, ErlNifIOQueue *q, size_t *size, ERL_NIF_TERM *bin_term) { + SysIOVec *iov_entry; + Binary *ref_bin; + + if (q->size == 0) { + return 0; + } + + ASSERT(q->b_head != q->b_tail && q->v_head != q->v_tail); + + ref_bin = &q->b_head[0]->nif; + iov_entry = &q->v_head[0]; + + if (size != NULL) { + *size = iov_entry->iov_len; + } + + if (iov_entry->iov_len > ERL_ONHEAP_BIN_LIMIT) { + ProcBin *pb = (ProcBin*)alloc_heap(env, PROC_BIN_SIZE); + + pb->thing_word = HEADER_PROC_BIN; + pb->next = MSO(env->proc).first; + pb->val = ref_bin; + pb->flags = 0; + + ASSERT((byte*)iov_entry->iov_base >= (byte*)ref_bin->orig_bytes); + ASSERT(iov_entry->iov_len <= ref_bin->orig_size); + + pb->bytes = (byte*)iov_entry->iov_base; + pb->size = iov_entry->iov_len; + + MSO(env->proc).first = (struct erl_off_heap_header*) pb; + OH_OVERHEAD(&(MSO(env->proc)), pb->size / sizeof(Eterm)); + + erts_refc_inc(&ref_bin->intern.refc, 2); + *bin_term = make_binary(pb); + } else { + ErlHeapBin* hb = (ErlHeapBin*)alloc_heap(env, heap_bin_size(iov_entry->iov_len)); + + hb->thing_word = header_heap_bin(iov_entry->iov_len); + hb->size = iov_entry->iov_len; + + sys_memcpy(hb->data, iov_entry->iov_base, iov_entry->iov_len); + *bin_term = make_binary(hb); + } + + return 1; +} + SysIOVec *enif_ioq_peek(ErlNifIOQueue *q, int *iovlen) { return erts_ioq_peekq(q, iovlen); diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h index 7fb447e4a8..053f7673c4 100644 --- a/erts/emulator/beam/erl_nif.h +++ b/erts/emulator/beam/erl_nif.h @@ -52,9 +52,10 @@ ** 2.11: 19.0 enif_snprintf ** 2.12: 20.0 add enif_select, enif_open_resource_type_x ** 2.13: 20.1 add enif_ioq +** 2.14: 21.0 add enif_ioq_peek_head */ #define ERL_NIF_MAJOR_VERSION 2 -#define ERL_NIF_MINOR_VERSION 13 +#define ERL_NIF_MINOR_VERSION 14 /* * The emulator will refuse to load a nif-lib with a major version diff --git a/erts/emulator/beam/erl_nif_api_funcs.h b/erts/emulator/beam/erl_nif_api_funcs.h index 9e573307d8..3750fd9b68 100644 --- a/erts/emulator/beam/erl_nif_api_funcs.h +++ b/erts/emulator/beam/erl_nif_api_funcs.h @@ -198,6 +198,7 @@ ERL_NIF_API_FUNC_DECL(SysIOVec*,enif_ioq_peek,(ErlNifIOQueue *q, int *iovlen)); ERL_NIF_API_FUNC_DECL(int,enif_inspect_iovec,(ErlNifEnv *env, size_t max_length, ERL_NIF_TERM iovec_term, ERL_NIF_TERM *tail, ErlNifIOVec **iovec)); ERL_NIF_API_FUNC_DECL(void,enif_free_iovec,(ErlNifIOVec *iov)); +ERL_NIF_API_FUNC_DECL(int,enif_ioq_peek_head,(ErlNifEnv *env, ErlNifIOQueue *q, size_t *size, ERL_NIF_TERM *head)); /* ** ADD NEW ENTRIES HERE (before this comment) !!! @@ -373,6 +374,7 @@ ERL_NIF_API_FUNC_DECL(void,enif_free_iovec,(ErlNifIOVec *iov)); # define enif_ioq_peek ERL_NIF_API_FUNC_MACRO(enif_ioq_peek) # define enif_inspect_iovec ERL_NIF_API_FUNC_MACRO(enif_inspect_iovec) # define enif_free_iovec ERL_NIF_API_FUNC_MACRO(enif_free_iovec) +# define enif_ioq_peek_head ERL_NIF_API_FUNC_MACRO(enif_ioq_peek_head) /* ** ADD NEW ENTRIES HERE (before this comment) |