summaryrefslogtreecommitdiff
path: root/io_buffer.c
diff options
context:
space:
mode:
authorSamuel Williams <samuel.williams@oriontransfer.co.nz>2022-10-19 18:53:38 +1300
committerGitHub <noreply@github.com>2022-10-19 18:53:38 +1300
commitfc3137ef54562c3c3290245c0f62e0bb193c3145 (patch)
tree65db334b4c606747eb2da3fd61ea80ef7aede423 /io_buffer.c
parentf982a26374f4300ed9e5cbd122f792f907e20b22 (diff)
downloadruby-fc3137ef54562c3c3290245c0f62e0bb193c3145.tar.gz
Add support for anonymous shared IO buffers. (#6580)
Diffstat (limited to 'io_buffer.c')
-rw-r--r--io_buffer.c37
1 files changed, 34 insertions, 3 deletions
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");
}
@@ -880,6 +893,22 @@ rb_io_buffer_mapped_p(VALUE self)
}
/*
+ * 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
*
* If the buffer is _locked_, meaning it is inside #locked block execution.
@@ -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);