mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-30 23:23:07 +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. | ||||
|  | ||||
| ## ??? - 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. | ||||
|   | ||||
| @@ -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)) { | ||||
|   | ||||
| @@ -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) { | ||||
|   | ||||
| @@ -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++; | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose