mirror of
https://github.com/janet-lang/janet
synced 2025-01-13 00:50:26 +00:00
Allow passing pointer-buffers to other threads.
This commit is contained in:
parent
1cadff8e58
commit
2e38f9ba61
@ -2,6 +2,8 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
## ??? - Unreleased
|
## ??? - Unreleased
|
||||||
|
- Add `ffi/pointer-buffer` to convert pointers to buffers the cannot be reallocated. This
|
||||||
|
allows easier manipulation of FFI memory, memory mapped files, and buffer memory shared between threads.
|
||||||
- Calling `ev/cancel` on a fiber waiting on `ev/gather` will correctly
|
- Calling `ev/cancel` on a fiber waiting on `ev/gather` will correctly
|
||||||
cancel the child fibers.
|
cancel the child fibers.
|
||||||
- Add `(sandbox ...)` function to core for permission based security. Also add `janet_sandbox` to C API.
|
- Add `(sandbox ...)` function to core for permission based security. Also add `janet_sandbox` to C API.
|
||||||
|
@ -58,6 +58,18 @@ JanetBuffer *janet_buffer_init(JanetBuffer *buffer, int32_t capacity) {
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize an unmanaged buffer */
|
||||||
|
JanetBuffer *janet_pointer_buffer_unsafe(void *memory, int32_t capacity, int32_t count) {
|
||||||
|
if (count < 0) janet_panic("count < 0");
|
||||||
|
if (capacity < count) janet_panic("capacity < count");
|
||||||
|
JanetBuffer *buffer = janet_gcalloc(JANET_MEMORY_BUFFER, sizeof(JanetBuffer));
|
||||||
|
buffer->gc.flags |= JANET_BUFFER_FLAG_NO_REALLOC;
|
||||||
|
buffer->capacity = capacity;
|
||||||
|
buffer->count = count;
|
||||||
|
buffer->data = (uint8_t *) memory;
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
/* Deinitialize a buffer (free data memory) */
|
/* Deinitialize a buffer (free data memory) */
|
||||||
void janet_buffer_deinit(JanetBuffer *buffer) {
|
void janet_buffer_deinit(JanetBuffer *buffer) {
|
||||||
if (!(buffer->gc.flags & JANET_BUFFER_FLAG_NO_REALLOC)) {
|
if (!(buffer->gc.flags & JANET_BUFFER_FLAG_NO_REALLOC)) {
|
||||||
|
@ -1515,12 +1515,8 @@ JANET_CORE_FN(cfun_ffi_pointer_buffer,
|
|||||||
int32_t capacity = janet_getnat(argv, 1);
|
int32_t capacity = janet_getnat(argv, 1);
|
||||||
int32_t count = janet_optnat(argv, argc, 2, 0);
|
int32_t count = janet_optnat(argv, argc, 2, 0);
|
||||||
int64_t offset = janet_optinteger64(argv, argc, 3, 0);
|
int64_t offset = janet_optinteger64(argv, argc, 3, 0);
|
||||||
JanetBuffer *buffer = janet_gcalloc(JANET_MEMORY_BUFFER, sizeof(JanetBuffer));
|
uint8_t *offset_pointer = ((uint8_t *) pointer) + offset;
|
||||||
buffer->gc.flags |= JANET_BUFFER_FLAG_NO_REALLOC;
|
return janet_wrap_buffer(janet_pointer_buffer_unsafe(offset_pointer, capacity, count));
|
||||||
buffer->capacity = capacity;
|
|
||||||
buffer->count = count;
|
|
||||||
buffer->data = ((uint8_t *) pointer) + offset;
|
|
||||||
return janet_wrap_buffer(buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void janet_lib_ffi(JanetTable *env) {
|
void janet_lib_ffi(JanetTable *env) {
|
||||||
|
@ -67,7 +67,8 @@ enum {
|
|||||||
LB_UNSAFE_POINTER, /* 222 */
|
LB_UNSAFE_POINTER, /* 222 */
|
||||||
LB_STRUCT_PROTO, /* 223 */
|
LB_STRUCT_PROTO, /* 223 */
|
||||||
#ifdef JANET_EV
|
#ifdef JANET_EV
|
||||||
LB_THREADED_ABSTRACT/* 224 */
|
LB_THREADED_ABSTRACT, /* 224 */
|
||||||
|
LB_POINTER_BUFFER, /* 224 */
|
||||||
#endif
|
#endif
|
||||||
} LeadBytes;
|
} LeadBytes;
|
||||||
|
|
||||||
@ -153,6 +154,10 @@ static void pushbytes(MarshalState *st, const uint8_t *bytes, int32_t len) {
|
|||||||
janet_buffer_push_bytes(st->buf, bytes, len);
|
janet_buffer_push_bytes(st->buf, bytes, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pushpointer(MarshalState *st, void *ptr) {
|
||||||
|
janet_buffer_push_bytes(st->buf, (const uint8_t *) &ptr, sizeof(ptr));
|
||||||
|
}
|
||||||
|
|
||||||
/* Marshal a size_t onto the buffer */
|
/* Marshal a size_t onto the buffer */
|
||||||
static void push64(MarshalState *st, uint64_t x) {
|
static void push64(MarshalState *st, uint64_t x) {
|
||||||
if (x <= 0xF0) {
|
if (x <= 0xF0) {
|
||||||
@ -511,6 +516,16 @@ static void marshal_one(MarshalState *st, Janet x, int flags) {
|
|||||||
JanetBuffer *buffer = janet_unwrap_buffer(x);
|
JanetBuffer *buffer = janet_unwrap_buffer(x);
|
||||||
/* Record reference */
|
/* Record reference */
|
||||||
MARK_SEEN();
|
MARK_SEEN();
|
||||||
|
#ifdef JANET_EV
|
||||||
|
if ((flags & JANET_MARSHAL_UNSAFE) &&
|
||||||
|
(buffer->gc.flags & JANET_BUFFER_FLAG_NO_REALLOC)) {
|
||||||
|
pushbyte(st, LB_POINTER_BUFFER);
|
||||||
|
pushint(st, buffer->count);
|
||||||
|
pushint(st, buffer->capacity);
|
||||||
|
pushpointer(st, buffer->data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
pushbyte(st, LB_BUFFER);
|
pushbyte(st, LB_BUFFER);
|
||||||
pushint(st, buffer->count);
|
pushint(st, buffer->count);
|
||||||
pushbytes(st, buffer->data, buffer->count);
|
pushbytes(st, buffer->data, buffer->count);
|
||||||
@ -606,8 +621,7 @@ static void marshal_one(MarshalState *st, Janet x, int flags) {
|
|||||||
if (!(flags & JANET_MARSHAL_UNSAFE)) goto no_registry;
|
if (!(flags & JANET_MARSHAL_UNSAFE)) goto no_registry;
|
||||||
MARK_SEEN();
|
MARK_SEEN();
|
||||||
pushbyte(st, LB_UNSAFE_POINTER);
|
pushbyte(st, LB_UNSAFE_POINTER);
|
||||||
void *ptr = janet_unwrap_pointer(x);
|
pushpointer(st, janet_unwrap_pointer(x));
|
||||||
pushbytes(st, (uint8_t *) &ptr, sizeof(void *));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
no_registry:
|
no_registry:
|
||||||
@ -1415,6 +1429,27 @@ static const uint8_t *unmarshal_one(
|
|||||||
janet_v_push(st->lookup, *out);
|
janet_v_push(st->lookup, *out);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
case LB_POINTER_BUFFER: {
|
||||||
|
data++;
|
||||||
|
int32_t count = readnat(st, &data);
|
||||||
|
int32_t capacity = readnat(st, &data);
|
||||||
|
MARSH_EOS(st, data + sizeof(void *));
|
||||||
|
union {
|
||||||
|
void *ptr;
|
||||||
|
uint8_t bytes[sizeof(void *)];
|
||||||
|
} u;
|
||||||
|
if (!(flags & JANET_MARSHAL_UNSAFE)) {
|
||||||
|
janet_panicf("unsafe flag not given, "
|
||||||
|
"will not unmarshal raw pointer at index %d",
|
||||||
|
(int)(data - st->start));
|
||||||
|
}
|
||||||
|
memcpy(u.bytes, data, sizeof(void *));
|
||||||
|
data += sizeof(void *);
|
||||||
|
JanetBuffer *buffer = janet_pointer_buffer_unsafe(u.ptr, capacity, count);
|
||||||
|
*out = janet_wrap_buffer(buffer);
|
||||||
|
janet_v_push(st->lookup, *out);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
case LB_UNSAFE_CFUNCTION: {
|
case LB_UNSAFE_CFUNCTION: {
|
||||||
MARSH_EOS(st, data + sizeof(JanetCFunction));
|
MARSH_EOS(st, data + sizeof(JanetCFunction));
|
||||||
data++;
|
data++;
|
||||||
|
@ -334,6 +334,7 @@ JANET_CORE_FN(cfun_net_sockaddr,
|
|||||||
"given in the port argument. On Linux, abstract "
|
"given in the port argument. On Linux, abstract "
|
||||||
"unix domain sockets are specified with a leading '@' character in port. If `multi` is truthy, will "
|
"unix domain sockets are specified with a leading '@' character in port. If `multi` is truthy, will "
|
||||||
"return all address that match in an array instead of just the first.") {
|
"return all address that match in an array instead of just the first.") {
|
||||||
|
janet_sandbox_assert(JANET_SANDBOX_NET_CONNECT); /* connect OR listen */
|
||||||
janet_arity(argc, 2, 4);
|
janet_arity(argc, 2, 4);
|
||||||
int socktype = janet_get_sockettype(argv, argc, 2);
|
int socktype = janet_get_sockettype(argv, argc, 2);
|
||||||
int is_unix = 0;
|
int is_unix = 0;
|
||||||
|
@ -1588,6 +1588,7 @@ JANET_API Janet janet_array_peek(JanetArray *array);
|
|||||||
#define JANET_BUFFER_FLAG_NO_REALLOC 0x10000
|
#define JANET_BUFFER_FLAG_NO_REALLOC 0x10000
|
||||||
JANET_API JanetBuffer *janet_buffer(int32_t capacity);
|
JANET_API JanetBuffer *janet_buffer(int32_t capacity);
|
||||||
JANET_API JanetBuffer *janet_buffer_init(JanetBuffer *buffer, int32_t capacity);
|
JANET_API JanetBuffer *janet_buffer_init(JanetBuffer *buffer, int32_t capacity);
|
||||||
|
JANET_API JanetBuffer *janet_pointer_buffer_unsafe(void *memory, int32_t capacity, int32_t count);
|
||||||
JANET_API void janet_buffer_deinit(JanetBuffer *buffer);
|
JANET_API void janet_buffer_deinit(JanetBuffer *buffer);
|
||||||
JANET_API void janet_buffer_ensure(JanetBuffer *buffer, int32_t capacity, int32_t growth);
|
JANET_API void janet_buffer_ensure(JanetBuffer *buffer, int32_t capacity, int32_t growth);
|
||||||
JANET_API void janet_buffer_setcount(JanetBuffer *buffer, int32_t count);
|
JANET_API void janet_buffer_setcount(JanetBuffer *buffer, int32_t count);
|
||||||
|
Loading…
Reference in New Issue
Block a user