Skip to content

Commit cb23916

Browse files
committed
Add missing files
1 parent f966dea commit cb23916

File tree

2 files changed

+122
-0
lines changed

2 files changed

+122
-0
lines changed

ext/um/um_mutex_class.c

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#include "um.h"
2+
#include <stdlib.h>
3+
4+
VALUE cMutex;
5+
6+
static void Mutex_mark(void *ptr) {
7+
struct um_futex *futex = ptr;
8+
rb_gc_mark_movable(futex->self);
9+
}
10+
11+
static void Mutex_compact(void *ptr) {
12+
struct um_futex *futex = ptr;
13+
futex->self = rb_gc_location(futex->self);
14+
}
15+
16+
static size_t Mutex_size(const void *ptr) {
17+
return sizeof(struct um_futex);
18+
}
19+
20+
static const rb_data_type_t Mutex_type = {
21+
"UringMachineMutex",
22+
{Mutex_mark, free, Mutex_size, Mutex_compact},
23+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
24+
};
25+
26+
static VALUE Mutex_allocate(VALUE klass) {
27+
struct um_futex *futex = malloc(sizeof(struct um_futex));
28+
return TypedData_Wrap_Struct(klass, &Mutex_type, futex);
29+
}
30+
31+
inline struct um_futex *Mutex_data(VALUE self) {
32+
return RTYPEDDATA_DATA(self);
33+
}
34+
35+
void um_mutex_init(uint32_t *futex);
36+
37+
VALUE Mutex_initialize(VALUE self) {
38+
struct um_futex *futex = Mutex_data(self);
39+
um_mutex_init(&futex->value);
40+
return self;
41+
}
42+
43+
void Init_Mutex(void) {
44+
cMutex = rb_define_class_under(cUM, "Mutex", rb_cObject);
45+
rb_define_alloc_func(cMutex, Mutex_allocate);
46+
47+
rb_define_method(cMutex, "initialize", Mutex_initialize, 0);
48+
}

ext/um/um_sync.c

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#include "um.h"
2+
#include <stdatomic.h>
3+
#include <linux/futex.h>
4+
5+
struct sync_ctx {
6+
struct um *machine;
7+
uint32_t *futex;
8+
};
9+
10+
void um_futex_wait(struct um *machine, uint32_t *futex, uint32_t expect) {
11+
struct um_op *op = um_op_idle_checkout(machine, OP_SYNCHRONIZE);
12+
struct io_uring_sqe *sqe = um_get_sqe(machine, op);
13+
__s32 result = 0;
14+
15+
// submit futex_wait
16+
io_uring_prep_futex_wait(
17+
sqe, (uint32_t *)futex, expect, FUTEX_BITSET_MATCH_ANY,
18+
FUTEX2_SIZE_U32, 0
19+
);
20+
um_await_op(machine, op, &result, NULL);
21+
if (result != -EAGAIN)
22+
um_raise_on_error_result(result);
23+
}
24+
25+
void um_futex_wake(struct um *machine, uint32_t *futex, uint32_t num_waiters) {
26+
struct um_op *op = um_op_idle_checkout(machine, OP_SYNCHRONIZE);
27+
struct io_uring_sqe *sqe = um_get_sqe(machine, op);
28+
__s32 result = 0;
29+
30+
// submit futex_wait
31+
io_uring_prep_futex_wake(
32+
sqe, (uint32_t *)futex, num_waiters, FUTEX_BITSET_MATCH_ANY,
33+
FUTEX2_SIZE_U32, 0
34+
);
35+
um_await_op(machine, op, &result, NULL);
36+
um_raise_on_error_result(result);
37+
}
38+
39+
#define LOCKED 1
40+
#define UNLOCKED 0
41+
42+
void um_mutex_init(uint32_t *futex) {
43+
*futex = UNLOCKED;
44+
}
45+
46+
void um_mutex_lock(struct um *machine, uint32_t *futex) {
47+
while (*futex == LOCKED) {
48+
um_futex_wait(machine, futex, LOCKED);
49+
}
50+
*futex = LOCKED;
51+
}
52+
53+
void um_mutex_unlock(struct um *machine, uint32_t *futex) {
54+
*futex = UNLOCKED;
55+
// Wake up 1 waiting fiber
56+
um_futex_wake(machine, futex, 1);
57+
}
58+
59+
VALUE synchronize_begin(VALUE arg) {
60+
struct sync_ctx *ctx = (struct sync_ctx *)arg;
61+
um_mutex_lock(ctx->machine, ctx->futex);
62+
return rb_yield(Qnil);
63+
}
64+
65+
VALUE synchronize_ensure(VALUE arg) {
66+
struct sync_ctx *ctx = (struct sync_ctx *)arg;
67+
um_mutex_unlock(ctx->machine, ctx->futex);
68+
return Qnil;
69+
}
70+
71+
VALUE um_mutex_synchronize(struct um *machine, uint32_t *futex) {
72+
struct sync_ctx ctx = { .machine = machine, .futex = futex };
73+
return rb_ensure(synchronize_begin, (VALUE)&ctx, synchronize_ensure, (VALUE)&ctx);
74+
}

0 commit comments

Comments
 (0)