From fc3137ef54562c3c3290245c0f62e0bb193c3145 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Wed, 19 Oct 2022 18:53:38 +1300 Subject: Add support for anonymous shared IO buffers. (#6580) --- io_buffer.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) (limited to 'io_buffer.c') diff --git a/io_buffer.c b/io_buffer.c index bc5fac8118..e252af3513 100644 --- a/io_buffer.c +++ b/io_buffer.c @@ -47,7 +47,7 @@ struct rb_io_buffer { }; static inline void * -io_buffer_map_memory(size_t size) +io_buffer_map_memory(size_t size, int flags) { #if defined(_WIN32) void * base = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); @@ -56,7 +56,14 @@ io_buffer_map_memory(size_t size) rb_sys_fail("io_buffer_map_memory:VirtualAlloc"); } #else - void * base = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); + int mmap_flags = MAP_ANONYMOUS; + if (flags & RB_IO_BUFFER_SHARED) { + mmap_flags |= MAP_SHARED; + } else { + mmap_flags |= MAP_PRIVATE; + } + + void * base = mmap(NULL, size, PROT_READ | PROT_WRITE, mmap_flags, -1, 0); if (base == MAP_FAILED) { rb_sys_fail("io_buffer_map_memory:mmap"); @@ -93,6 +100,7 @@ io_buffer_map_file(struct rb_io_buffer *data, int descriptor, size_t size, rb_of else { // This buffer refers to external data. data->flags |= RB_IO_BUFFER_EXTERNAL; + data->flags |= RB_IO_BUFFER_SHARED; } void *base = MapViewOfFile(mapping, access, (DWORD)(offset >> 32), (DWORD)(offset & 0xFFFFFFFF), size); @@ -119,6 +127,7 @@ io_buffer_map_file(struct rb_io_buffer *data, int descriptor, size_t size, rb_of else { // This buffer refers to external data. data->flags |= RB_IO_BUFFER_EXTERNAL; + data->flags |= RB_IO_BUFFER_SHARED; access |= MAP_SHARED; } @@ -184,7 +193,7 @@ io_buffer_initialize(struct rb_io_buffer *data, void *base, size_t size, enum rb base = calloc(size, 1); } else if (flags & RB_IO_BUFFER_MAPPED) { - base = io_buffer_map_memory(size); + base = io_buffer_map_memory(size, flags); } if (!base) { @@ -655,6 +664,10 @@ rb_io_buffer_to_s(VALUE self) rb_str_cat2(result, " MAPPED"); } + if (data->flags & RB_IO_BUFFER_SHARED) { + rb_str_cat2(result, " SHARED"); + } + if (data->flags & RB_IO_BUFFER_LOCKED) { rb_str_cat2(result, " LOCKED"); } @@ -879,6 +892,22 @@ rb_io_buffer_mapped_p(VALUE self) return RBOOL(data->flags & RB_IO_BUFFER_MAPPED); } +/* + * call-seq: shared? -> true or false + * + * If the buffer is _shared_, meaning it references memory that can be shared + * with other processes (and thus might change without being modified + * locally). + */ +static VALUE +rb_io_buffer_shared_p(VALUE self) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + return RBOOL(data->flags & RB_IO_BUFFER_SHARED); +} + /* * call-seq: locked? -> true or false * @@ -3176,6 +3205,7 @@ Init_IO_Buffer(void) rb_define_const(rb_cIOBuffer, "EXTERNAL", RB_INT2NUM(RB_IO_BUFFER_EXTERNAL)); rb_define_const(rb_cIOBuffer, "INTERNAL", RB_INT2NUM(RB_IO_BUFFER_INTERNAL)); rb_define_const(rb_cIOBuffer, "MAPPED", RB_INT2NUM(RB_IO_BUFFER_MAPPED)); + rb_define_const(rb_cIOBuffer, "SHARED", RB_INT2NUM(RB_IO_BUFFER_SHARED)); rb_define_const(rb_cIOBuffer, "LOCKED", RB_INT2NUM(RB_IO_BUFFER_LOCKED)); rb_define_const(rb_cIOBuffer, "PRIVATE", RB_INT2NUM(RB_IO_BUFFER_PRIVATE)); rb_define_const(rb_cIOBuffer, "READONLY", RB_INT2NUM(RB_IO_BUFFER_READONLY)); @@ -3191,6 +3221,7 @@ Init_IO_Buffer(void) rb_define_method(rb_cIOBuffer, "external?", rb_io_buffer_external_p, 0); rb_define_method(rb_cIOBuffer, "internal?", rb_io_buffer_internal_p, 0); rb_define_method(rb_cIOBuffer, "mapped?", rb_io_buffer_mapped_p, 0); + rb_define_method(rb_cIOBuffer, "shared?", rb_io_buffer_shared_p, 0); rb_define_method(rb_cIOBuffer, "locked?", rb_io_buffer_locked_p, 0); rb_define_method(rb_cIOBuffer, "readonly?", io_buffer_readonly_p, 0); -- cgit v1.2.1