Skip to content

Commit

Permalink
Mark non-private mapped files as external.
Browse files Browse the repository at this point in the history
  • Loading branch information
ioquatix committed Dec 19, 2021
1 parent 848eed2 commit 1adf7f1
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 20 deletions.
16 changes: 10 additions & 6 deletions include/ruby/io/buffer.h
Expand Up @@ -27,20 +27,24 @@ RUBY_EXTERN size_t RUBY_IO_BUFFER_DEFAULT_SIZE;

enum rb_io_buffer_flags {
// The memory in the buffer is owned by someone else.
RB_IO_BUFFER_EXTERNAL = 0,
// More specifically, it means that someone else owns the buffer and we shouldn't try to resize it.
RB_IO_BUFFER_EXTERNAL = 1,
// The memory in the buffer is allocated internally.
RB_IO_BUFFER_INTERNAL = 1,
RB_IO_BUFFER_INTERNAL = 2,
// The memory in the buffer is mapped.
RB_IO_BUFFER_MAPPED = 2,
// A non-private mapping is marked as external.
RB_IO_BUFFER_MAPPED = 4,

// The buffer is locked and cannot be resized.
RB_IO_BUFFER_LOCKED = 16,
// More specifically, it means we can't change the base address or size.
// A buffer is typically locked before a system call that uses the data.
RB_IO_BUFFER_LOCKED = 32,

// The buffer mapping is private and will not impact other processes or the underlying file.
RB_IO_BUFFER_PRIVATE = 32,
RB_IO_BUFFER_PRIVATE = 64,

// The buffer is read-only and cannot be modified.
RB_IO_BUFFER_IMMUTABLE = 64
RB_IO_BUFFER_IMMUTABLE = 128
};

enum rb_io_buffer_endian {
Expand Down
15 changes: 7 additions & 8 deletions io_buffer.c
Expand Up @@ -83,6 +83,9 @@ io_buffer_map_file(struct rb_io_buffer *data, int descriptor, size_t size, off_t
if (flags & RB_IO_BUFFER_PRIVATE) {
access |= FILE_MAP_COPY;
data->flags |= RB_IO_BUFFER_PRIVATE;
} else {
// This buffer refers to external data.
data->flags |= RB_IO_BUFFER_EXTERNAL;
}

void *base = MapViewOfFile(mapping, access, (DWORD)(offset >> 32), (DWORD)(offset & 0xFFFFFFFF), size);
Expand All @@ -107,6 +110,8 @@ io_buffer_map_file(struct rb_io_buffer *data, int descriptor, size_t size, off_t
data->flags |= RB_IO_BUFFER_PRIVATE;
}
else {
// This buffer refers to external data.
data->flags |= RB_IO_BUFFER_EXTERNAL;
access |= MAP_SHARED;
}

Expand Down Expand Up @@ -572,7 +577,7 @@ rb_io_buffer_external_p(VALUE self)
struct rb_io_buffer *data = NULL;
TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data);

return data->flags & (RB_IO_BUFFER_INTERNAL | RB_IO_BUFFER_MAPPED) ? Qfalse : Qtrue;
return data->flags & RB_IO_BUFFER_EXTERNAL ? Qtrue : Qfalse;
}

static VALUE
Expand Down Expand Up @@ -611,12 +616,6 @@ rb_io_buffer_immutable_p(VALUE self)
return data->flags & RB_IO_BUFFER_IMMUTABLE ? Qtrue : Qfalse;
}

static int
io_buffer_external_p(enum rb_io_buffer_flags flags)
{
return !(flags & (RB_IO_BUFFER_INTERNAL | RB_IO_BUFFER_MAPPED));
}

VALUE
rb_io_buffer_lock(VALUE self)
{
Expand Down Expand Up @@ -858,7 +857,7 @@ rb_io_buffer_resize(VALUE self, size_t size)
return;
}

if (io_buffer_external_p(data->flags)) {
if (data->flags & RB_IO_BUFFER_EXTERNAL) {
rb_raise(rb_eIOBufferMutationError, "Cannot resize external buffer!");
}

Expand Down
12 changes: 6 additions & 6 deletions test/ruby/test_io_buffer.rb
Expand Up @@ -18,14 +18,14 @@ def assert_positive(value)
end

def test_flags
assert_equal 0, IO::Buffer::EXTERNAL
assert_equal 1, IO::Buffer::INTERNAL
assert_equal 2, IO::Buffer::MAPPED
assert_equal 1, IO::Buffer::EXTERNAL
assert_equal 2, IO::Buffer::INTERNAL
assert_equal 4, IO::Buffer::MAPPED

assert_equal 16, IO::Buffer::LOCKED
assert_equal 32, IO::Buffer::PRIVATE
assert_equal 32, IO::Buffer::LOCKED
assert_equal 64, IO::Buffer::PRIVATE

assert_equal 64, IO::Buffer::IMMUTABLE
assert_equal 128, IO::Buffer::IMMUTABLE
end

def test_endian
Expand Down

0 comments on commit 1adf7f1

Please sign in to comment.