1
0
mirror of https://github.com/janet-lang/janet synced 2024-12-26 00:10:27 +00:00

Allow passing pointer-buffers to other threads.

This commit is contained in:
Calvin Rose 2023-02-12 11:07:45 -06:00
parent 1cadff8e58
commit 2e38f9ba61
6 changed files with 56 additions and 9 deletions

View File

@ -2,6 +2,8 @@
All notable changes to this project will be documented in this file.
## ??? - 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
cancel the child fibers.
- Add `(sandbox ...)` function to core for permission based security. Also add `janet_sandbox` to C API.

View File

@ -58,6 +58,18 @@ JanetBuffer *janet_buffer_init(JanetBuffer *buffer, int32_t capacity) {
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) */
void janet_buffer_deinit(JanetBuffer *buffer) {
if (!(buffer->gc.flags & JANET_BUFFER_FLAG_NO_REALLOC)) {

View File

@ -1515,12 +1515,8 @@ JANET_CORE_FN(cfun_ffi_pointer_buffer,
int32_t capacity = janet_getnat(argv, 1);
int32_t count = janet_optnat(argv, argc, 2, 0);
int64_t offset = janet_optinteger64(argv, argc, 3, 0);
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 *) pointer) + offset;
return janet_wrap_buffer(buffer);
uint8_t *offset_pointer = ((uint8_t *) pointer) + offset;
return janet_wrap_buffer(janet_pointer_buffer_unsafe(offset_pointer, capacity, count));
}
void janet_lib_ffi(JanetTable *env) {

View File

@ -67,7 +67,8 @@ enum {
LB_UNSAFE_POINTER, /* 222 */
LB_STRUCT_PROTO, /* 223 */
#ifdef JANET_EV
LB_THREADED_ABSTRACT/* 224 */
LB_THREADED_ABSTRACT, /* 224 */
LB_POINTER_BUFFER, /* 224 */
#endif
} 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);
}
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 */
static void push64(MarshalState *st, uint64_t x) {
if (x <= 0xF0) {
@ -511,6 +516,16 @@ static void marshal_one(MarshalState *st, Janet x, int flags) {
JanetBuffer *buffer = janet_unwrap_buffer(x);
/* Record reference */
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);
pushint(st, 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;
MARK_SEEN();
pushbyte(st, LB_UNSAFE_POINTER);
void *ptr = janet_unwrap_pointer(x);
pushbytes(st, (uint8_t *) &ptr, sizeof(void *));
pushpointer(st, janet_unwrap_pointer(x));
return;
}
no_registry:
@ -1415,6 +1429,27 @@ static const uint8_t *unmarshal_one(
janet_v_push(st->lookup, *out);
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: {
MARSH_EOS(st, data + sizeof(JanetCFunction));
data++;

View File

@ -334,6 +334,7 @@ JANET_CORE_FN(cfun_net_sockaddr,
"given in the port argument. On Linux, abstract "
"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.") {
janet_sandbox_assert(JANET_SANDBOX_NET_CONNECT); /* connect OR listen */
janet_arity(argc, 2, 4);
int socktype = janet_get_sockettype(argv, argc, 2);
int is_unix = 0;

View File

@ -1588,6 +1588,7 @@ JANET_API Janet janet_array_peek(JanetArray *array);
#define JANET_BUFFER_FLAG_NO_REALLOC 0x10000
JANET_API JanetBuffer *janet_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_ensure(JanetBuffer *buffer, int32_t capacity, int32_t growth);
JANET_API void janet_buffer_setcount(JanetBuffer *buffer, int32_t count);