mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 15:43:01 +00:00 
			
		
		
		
	Allow passing pointer-buffers to other threads.
This commit is contained in:
		| @@ -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); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose