uringmachine 0.3 → 0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +2 -1
- data/CHANGELOG.md +23 -0
- data/README.md +128 -0
- data/TODO.md +14 -0
- data/examples/bm_snooze.rb +89 -0
- data/examples/bm_write.rb +56 -0
- data/examples/dns_client.rb +12 -0
- data/examples/echo_server.rb +18 -40
- data/examples/http_server.rb +42 -43
- data/examples/inout.rb +19 -0
- data/examples/nc.rb +36 -0
- data/examples/server_client.rb +64 -0
- data/examples/snooze.rb +44 -0
- data/examples/write_dev_null.rb +16 -0
- data/ext/um/extconf.rb +24 -23
- data/ext/um/um.c +524 -278
- data/ext/um/um.h +146 -44
- data/ext/um/um_buffer.c +49 -0
- data/ext/um/um_class.c +217 -106
- data/ext/um/um_const.c +213 -0
- data/ext/um/um_ext.c +4 -0
- data/ext/um/um_mutex_class.c +47 -0
- data/ext/um/um_op.c +86 -114
- data/ext/um/um_queue_class.c +58 -0
- data/ext/um/um_sync.c +273 -0
- data/ext/um/um_utils.c +49 -4
- data/lib/uringmachine/dns_resolver.rb +84 -0
- data/lib/uringmachine/version.rb +1 -1
- data/lib/uringmachine.rb +28 -0
- data/supressions/ruby.supp +71 -0
- data/test/helper.rb +8 -0
- data/test/test_um.rb +685 -46
- data/vendor/liburing/.github/workflows/build.yml +29 -1
- data/vendor/liburing/.gitignore +6 -0
- data/vendor/liburing/CHANGELOG +16 -0
- data/vendor/liburing/CONTRIBUTING.md +165 -0
- data/vendor/liburing/configure +64 -0
- data/vendor/liburing/examples/Makefile +9 -1
- data/vendor/liburing/examples/kdigest.c +405 -0
- data/vendor/liburing/examples/proxy.c +75 -8
- data/vendor/liburing/examples/reg-wait.c +159 -0
- data/vendor/liburing/liburing.pc.in +1 -1
- data/vendor/liburing/liburing.spec +1 -1
- data/vendor/liburing/src/Makefile +16 -2
- data/vendor/liburing/src/include/liburing/io_uring.h +77 -0
- data/vendor/liburing/src/include/liburing/sanitize.h +39 -0
- data/vendor/liburing/src/include/liburing.h +59 -6
- data/vendor/liburing/src/int_flags.h +10 -3
- data/vendor/liburing/src/liburing-ffi.map +16 -0
- data/vendor/liburing/src/liburing.map +10 -0
- data/vendor/liburing/src/queue.c +28 -16
- data/vendor/liburing/src/register.c +106 -1
- data/vendor/liburing/src/sanitize.c +176 -0
- data/vendor/liburing/src/setup.c +47 -19
- data/vendor/liburing/src/setup.h +6 -0
- data/vendor/liburing/test/35fa71a030ca.c +7 -0
- data/vendor/liburing/test/500f9fbadef8.c +2 -0
- data/vendor/liburing/test/7ad0e4b2f83c.c +0 -25
- data/vendor/liburing/test/917257daa0fe.c +7 -0
- data/vendor/liburing/test/Makefile +38 -4
- data/vendor/liburing/test/a0908ae19763.c +7 -0
- data/vendor/liburing/test/a4c0b3decb33.c +7 -0
- data/vendor/liburing/test/accept.c +14 -4
- data/vendor/liburing/test/b19062a56726.c +7 -0
- data/vendor/liburing/test/bind-listen.c +2 -2
- data/vendor/liburing/test/buf-ring-nommap.c +10 -3
- data/vendor/liburing/test/buf-ring.c +2 -0
- data/vendor/liburing/test/cmd-discard.c +427 -0
- data/vendor/liburing/test/coredump.c +7 -0
- data/vendor/liburing/test/cq-overflow.c +13 -1
- data/vendor/liburing/test/d4ae271dfaae.c +11 -3
- data/vendor/liburing/test/defer-taskrun.c +2 -2
- data/vendor/liburing/test/defer-tw-timeout.c +4 -1
- data/vendor/liburing/test/defer.c +2 -2
- data/vendor/liburing/test/double-poll-crash.c +1 -1
- data/vendor/liburing/test/eeed8b54e0df.c +2 -0
- data/vendor/liburing/test/eventfd.c +0 -1
- data/vendor/liburing/test/exit-no-cleanup.c +11 -0
- data/vendor/liburing/test/fadvise.c +9 -26
- data/vendor/liburing/test/fdinfo.c +9 -1
- data/vendor/liburing/test/fifo-nonblock-read.c +69 -0
- data/vendor/liburing/test/file-exit-unreg.c +48 -0
- data/vendor/liburing/test/file-register.c +14 -2
- data/vendor/liburing/test/file-update.c +1 -1
- data/vendor/liburing/test/file-verify.c +27 -16
- data/vendor/liburing/test/files-exit-hang-timeout.c +1 -2
- data/vendor/liburing/test/fixed-buf-iter.c +3 -1
- data/vendor/liburing/test/fixed-hugepage.c +12 -1
- data/vendor/liburing/test/fsnotify.c +1 -0
- data/vendor/liburing/test/futex.c +16 -4
- data/vendor/liburing/test/helpers.c +47 -0
- data/vendor/liburing/test/helpers.h +6 -0
- data/vendor/liburing/test/init-mem.c +5 -3
- data/vendor/liburing/test/io-cancel.c +0 -24
- data/vendor/liburing/test/io_uring_passthrough.c +4 -0
- data/vendor/liburing/test/io_uring_register.c +38 -8
- data/vendor/liburing/test/iopoll-leak.c +4 -0
- data/vendor/liburing/test/iopoll-overflow.c +1 -1
- data/vendor/liburing/test/iopoll.c +3 -3
- data/vendor/liburing/test/kallsyms.c +203 -0
- data/vendor/liburing/test/link-timeout.c +159 -0
- data/vendor/liburing/test/linked-defer-close.c +224 -0
- data/vendor/liburing/test/madvise.c +12 -25
- data/vendor/liburing/test/min-timeout-wait.c +0 -25
- data/vendor/liburing/test/min-timeout.c +0 -25
- data/vendor/liburing/test/mkdir.c +6 -0
- data/vendor/liburing/test/msg-ring.c +8 -2
- data/vendor/liburing/test/napi-test.c +16 -3
- data/vendor/liburing/test/no-mmap-inval.c +3 -1
- data/vendor/liburing/test/nop.c +44 -0
- data/vendor/liburing/test/ooo-file-unreg.c +1 -1
- data/vendor/liburing/test/open-close.c +40 -0
- data/vendor/liburing/test/openat2.c +37 -14
- data/vendor/liburing/test/poll-many.c +13 -7
- data/vendor/liburing/test/poll-mshot-update.c +17 -10
- data/vendor/liburing/test/poll-v-poll.c +6 -3
- data/vendor/liburing/test/pollfree.c +148 -0
- data/vendor/liburing/test/read-mshot-empty.c +158 -153
- data/vendor/liburing/test/read-mshot-stdin.c +121 -0
- data/vendor/liburing/test/read-mshot.c +282 -27
- data/vendor/liburing/test/read-write.c +78 -13
- data/vendor/liburing/test/recv-msgall-stream.c +3 -0
- data/vendor/liburing/test/recv-msgall.c +5 -0
- data/vendor/liburing/test/recvsend_bundle-inc.c +680 -0
- data/vendor/liburing/test/recvsend_bundle.c +94 -31
- data/vendor/liburing/test/reg-fd-only.c +15 -5
- data/vendor/liburing/test/reg-wait.c +251 -0
- data/vendor/liburing/test/regbuf-clone.c +645 -0
- data/vendor/liburing/test/regbuf-merge.c +7 -0
- data/vendor/liburing/test/register-restrictions.c +86 -85
- data/vendor/liburing/test/rename.c +59 -1
- data/vendor/liburing/test/resize-rings.c +643 -0
- data/vendor/liburing/test/ringbuf-read.c +5 -0
- data/vendor/liburing/test/ringbuf-status.c +5 -1
- data/vendor/liburing/test/rsrc_tags.c +1 -1
- data/vendor/liburing/test/runtests.sh +16 -1
- data/vendor/liburing/test/send-zerocopy.c +59 -0
- data/vendor/liburing/test/short-read.c +1 -0
- data/vendor/liburing/test/socket.c +43 -0
- data/vendor/liburing/test/splice.c +3 -1
- data/vendor/liburing/test/sq-poll-dup.c +1 -1
- data/vendor/liburing/test/sq-poll-share.c +2 -0
- data/vendor/liburing/test/sqpoll-disable-exit.c +8 -0
- data/vendor/liburing/test/sqpoll-exit-hang.c +1 -25
- data/vendor/liburing/test/sqpoll-sleep.c +40 -33
- data/vendor/liburing/test/sqwait.c +136 -0
- data/vendor/liburing/test/statx.c +89 -0
- data/vendor/liburing/test/stdout.c +2 -0
- data/vendor/liburing/test/submit-and-wait.c +1 -25
- data/vendor/liburing/test/submit-reuse.c +4 -26
- data/vendor/liburing/test/symlink.c +12 -1
- data/vendor/liburing/test/sync-cancel.c +56 -22
- data/vendor/liburing/test/thread-exit.c +5 -0
- data/vendor/liburing/test/timeout-new.c +1 -26
- data/vendor/liburing/test/timeout.c +25 -34
- data/vendor/liburing/test/unlink.c +94 -1
- data/vendor/liburing/test/uring_cmd_ublk.c +1252 -0
- data/vendor/liburing/test/waitid.c +62 -8
- data/vendor/liburing/test/wq-aff.c +35 -0
- data/vendor/liburing/test/xfail_prep_link_timeout_out_of_scope.c +46 -0
- data/vendor/liburing/test/xfail_register_buffers_out_of_scope.c +51 -0
- metadata +37 -6
- data/examples/event_loop.rb +0 -69
- data/examples/fibers.rb +0 -105
- data/examples/http_server_multishot.rb +0 -57
- data/examples/http_server_simpler.rb +0 -34
data/ext/um/um.h
CHANGED
@@ -20,38 +20,64 @@
|
|
20
20
|
#define likely(cond) __builtin_expect(!!(cond), 1)
|
21
21
|
#endif
|
22
22
|
|
23
|
-
enum
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
23
|
+
enum op_kind {
|
24
|
+
OP_TIMEOUT,
|
25
|
+
OP_SCHEDULE,
|
26
|
+
|
27
|
+
OP_SLEEP,
|
28
|
+
OP_READ,
|
29
|
+
OP_WRITE,
|
30
|
+
OP_CLOSE,
|
31
|
+
OP_ACCEPT,
|
32
|
+
OP_RECV,
|
33
|
+
OP_SEND,
|
34
|
+
OP_SOCKET,
|
35
|
+
OP_CONNECT,
|
36
|
+
OP_BIND,
|
37
|
+
OP_LISTEN,
|
38
|
+
OP_GETSOCKOPT,
|
39
|
+
OP_SETSOCKOPT,
|
40
|
+
|
41
|
+
OP_FUTEX_WAIT,
|
42
|
+
OP_FUTEX_WAKE,
|
43
|
+
|
44
|
+
OP_ACCEPT_MULTISHOT,
|
45
|
+
OP_READ_MULTISHOT,
|
46
|
+
OP_RECV_MULTISHOT
|
30
47
|
};
|
31
48
|
|
32
|
-
|
33
|
-
|
49
|
+
#define OP_F_COMPLETED (1U << 0)
|
50
|
+
#define OP_F_TRANSIENT (1U << 1)
|
51
|
+
#define OP_F_IGNORE_CANCELED (1U << 2)
|
52
|
+
#define OP_F_MULTISHOT (1U << 3)
|
34
53
|
|
35
|
-
|
36
|
-
|
54
|
+
struct um_op_result {
|
55
|
+
__s32 res;
|
56
|
+
__u32 flags;
|
57
|
+
struct um_op_result *next;
|
37
58
|
};
|
38
59
|
|
39
60
|
struct um_op {
|
40
|
-
enum op_state state;
|
41
61
|
struct um_op *prev;
|
42
62
|
struct um_op *next;
|
43
63
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
64
|
+
enum op_kind kind;
|
65
|
+
unsigned flags;
|
66
|
+
|
48
67
|
VALUE fiber;
|
49
|
-
VALUE
|
50
|
-
|
51
|
-
struct
|
52
|
-
|
53
|
-
|
54
|
-
|
68
|
+
VALUE value;
|
69
|
+
|
70
|
+
struct um_op_result result;
|
71
|
+
struct um_op_result *multishot_result_tail;
|
72
|
+
unsigned multishot_result_count;
|
73
|
+
|
74
|
+
struct __kernel_timespec ts; // used for timeout operation
|
75
|
+
};
|
76
|
+
|
77
|
+
struct um_buffer {
|
78
|
+
struct um_buffer *next;
|
79
|
+
void *ptr;
|
80
|
+
long len;
|
55
81
|
};
|
56
82
|
|
57
83
|
struct buf_ring_descriptor {
|
@@ -59,17 +85,17 @@ struct buf_ring_descriptor {
|
|
59
85
|
size_t br_size;
|
60
86
|
unsigned buf_count;
|
61
87
|
unsigned buf_size;
|
62
|
-
|
88
|
+
unsigned buf_mask;
|
89
|
+
void *buf_base;
|
63
90
|
};
|
64
91
|
|
65
92
|
#define BUFFER_RING_MAX_COUNT 10
|
66
93
|
|
67
94
|
struct um {
|
68
|
-
|
69
|
-
|
95
|
+
VALUE self;
|
96
|
+
VALUE poll_fiber;
|
70
97
|
|
71
|
-
struct
|
72
|
-
struct um_op *runqueue_tail;
|
98
|
+
struct um_buffer *buffer_freelist;
|
73
99
|
|
74
100
|
struct io_uring ring;
|
75
101
|
|
@@ -79,47 +105,123 @@ struct um {
|
|
79
105
|
|
80
106
|
struct buf_ring_descriptor buffer_rings[BUFFER_RING_MAX_COUNT];
|
81
107
|
unsigned int buffer_ring_count;
|
108
|
+
|
109
|
+
struct um_op *transient_head;
|
110
|
+
struct um_op *runqueue_head;
|
111
|
+
struct um_op *runqueue_tail;
|
112
|
+
|
113
|
+
struct um_op *op_freelist;
|
114
|
+
struct um_op_result *result_freelist;
|
115
|
+
};
|
116
|
+
|
117
|
+
struct um_mutex {
|
118
|
+
VALUE self;
|
119
|
+
uint32_t state;
|
120
|
+
};
|
121
|
+
|
122
|
+
struct um_queue_entry {
|
123
|
+
struct um_queue_entry *prev;
|
124
|
+
struct um_queue_entry *next;
|
125
|
+
VALUE value;
|
126
|
+
};
|
127
|
+
|
128
|
+
struct um_queue {
|
129
|
+
VALUE self;
|
130
|
+
|
131
|
+
struct um_queue_entry *head;
|
132
|
+
struct um_queue_entry *tail;
|
133
|
+
struct um_queue_entry *free_head;
|
134
|
+
|
135
|
+
uint32_t num_waiters;
|
136
|
+
uint32_t state;
|
137
|
+
uint32_t count;
|
82
138
|
};
|
83
139
|
|
84
140
|
extern VALUE cUM;
|
141
|
+
extern VALUE cMutex;
|
142
|
+
extern VALUE cQueue;
|
85
143
|
|
86
|
-
void um_setup(struct um *machine);
|
144
|
+
void um_setup(VALUE self, struct um *machine);
|
87
145
|
void um_teardown(struct um *machine);
|
88
|
-
|
89
|
-
|
146
|
+
|
147
|
+
struct um_op *um_op_alloc(struct um *machine);
|
148
|
+
void um_op_free(struct um *machine, struct um_op *op);
|
149
|
+
void um_op_clear(struct um *machine, struct um_op *op);
|
150
|
+
void um_op_transient_add(struct um *machine, struct um_op *op);
|
151
|
+
void um_op_transient_remove(struct um *machine, struct um_op *op);
|
152
|
+
void um_op_list_mark(struct um *machine, struct um_op *head);
|
153
|
+
void um_op_list_compact(struct um *machine, struct um_op *head);
|
154
|
+
|
155
|
+
void um_op_multishot_results_push(struct um *machine, struct um_op *op, __s32 res, __u32 flags);
|
156
|
+
void um_op_multishot_results_clear(struct um *machine, struct um_op *op);
|
157
|
+
|
158
|
+
void um_runqueue_push(struct um *machine, struct um_op *op);
|
159
|
+
struct um_op *um_runqueue_shift(struct um *machine);
|
160
|
+
|
161
|
+
struct um_buffer *um_buffer_checkout(struct um *machine, int len);
|
162
|
+
void um_buffer_checkin(struct um *machine, struct um_buffer *buffer);
|
163
|
+
void um_free_buffer_linked_list(struct um *machine);
|
90
164
|
|
91
165
|
struct __kernel_timespec um_double_to_timespec(double value);
|
92
166
|
int um_value_is_exception_p(VALUE v);
|
93
167
|
VALUE um_raise_exception(VALUE v);
|
94
|
-
void um_raise_on_system_error(int result);
|
95
168
|
|
169
|
+
#define raise_if_exception(v) (um_value_is_exception_p(v) ? um_raise_exception(v) : v)
|
170
|
+
|
171
|
+
void um_prep_op(struct um *machine, struct um_op *op, enum op_kind kind);
|
172
|
+
void um_raise_on_error_result(int result);
|
96
173
|
void * um_prepare_read_buffer(VALUE buffer, unsigned len, int ofs);
|
97
|
-
void um_update_read_buffer(struct um *machine, VALUE buffer, int buffer_offset,
|
98
|
-
|
174
|
+
void um_update_read_buffer(struct um *machine, VALUE buffer, int buffer_offset, __s32 result, __u32 flags);
|
175
|
+
int um_setup_buffer_ring(struct um *machine, unsigned size, unsigned count);
|
176
|
+
VALUE um_get_string_from_buffer_ring(struct um *machine, int bgid, __s32 result, __u32 flags);
|
177
|
+
|
178
|
+
struct io_uring_sqe *um_get_sqe(struct um *machine, struct um_op *op);
|
99
179
|
|
100
180
|
VALUE um_fiber_switch(struct um *machine);
|
101
181
|
VALUE um_await(struct um *machine);
|
182
|
+
void um_cancel_and_wait(struct um *machine, struct um_op *op);
|
183
|
+
int um_check_completion(struct um *machine, struct um_op *op);
|
102
184
|
|
103
|
-
|
104
|
-
struct um_op* um_op_checkout(struct um *machine);
|
105
|
-
void um_op_result_push(struct um *machine, struct um_op *op, int result, int flags);
|
106
|
-
int um_op_result_shift(struct um *machine, struct um_op *op, int *result, int *flags);
|
107
|
-
|
108
|
-
struct um_op *um_runqueue_find_by_fiber(struct um *machine, VALUE fiber);
|
109
|
-
void um_runqueue_push(struct um *machine, struct um_op *op);
|
110
|
-
struct um_op *um_runqueue_shift(struct um *machine);
|
111
|
-
void um_runqueue_unshift(struct um *machine, struct um_op *op);
|
185
|
+
#define um_op_completed_p(op) ((op)->flags & OP_F_COMPLETED)
|
112
186
|
|
113
187
|
void um_schedule(struct um *machine, VALUE fiber, VALUE value);
|
114
|
-
void um_interrupt(struct um *machine, VALUE fiber, VALUE value);
|
115
188
|
VALUE um_timeout(struct um *machine, VALUE interval, VALUE class);
|
116
189
|
|
117
190
|
VALUE um_sleep(struct um *machine, double duration);
|
118
191
|
VALUE um_read(struct um *machine, int fd, VALUE buffer, int maxlen, int buffer_offset);
|
119
192
|
VALUE um_read_each(struct um *machine, int fd, int bgid);
|
120
|
-
VALUE um_write(struct um *machine, int fd, VALUE
|
193
|
+
VALUE um_write(struct um *machine, int fd, VALUE str, int len);
|
194
|
+
VALUE um_close(struct um *machine, int fd);
|
195
|
+
VALUE um_open(struct um *machine, VALUE pathname, int flags, int mode);
|
196
|
+
VALUE um_waitpid(struct um *machine, int pid, int options);
|
121
197
|
|
122
198
|
VALUE um_accept(struct um *machine, int fd);
|
123
199
|
VALUE um_accept_each(struct um *machine, int fd);
|
200
|
+
VALUE um_socket(struct um *machine, int domain, int type, int protocol, uint flags);
|
201
|
+
VALUE um_connect(struct um *machine, int fd, const struct sockaddr *addr, socklen_t addrlen);
|
202
|
+
VALUE um_send(struct um *machine, int fd, VALUE buffer, int len, int flags);
|
203
|
+
VALUE um_recv(struct um *machine, int fd, VALUE buffer, int maxlen, int flags);
|
204
|
+
VALUE um_recv_each(struct um *machine, int fd, int bgid, int flags);
|
205
|
+
VALUE um_bind(struct um *machine, int fd, struct sockaddr *addr, socklen_t addrlen);
|
206
|
+
VALUE um_listen(struct um *machine, int fd, int backlog);
|
207
|
+
VALUE um_getsockopt(struct um *machine, int fd, int level, int opt);
|
208
|
+
VALUE um_setsockopt(struct um *machine, int fd, int level, int opt, int value);
|
209
|
+
|
210
|
+
struct um_mutex *Mutex_data(VALUE self);
|
211
|
+
struct um_queue *Queue_data(VALUE self);
|
212
|
+
|
213
|
+
void um_mutex_init(struct um_mutex *mutex);
|
214
|
+
VALUE um_mutex_synchronize(struct um *machine, uint32_t *state);
|
215
|
+
|
216
|
+
void um_queue_init(struct um_queue *queue);
|
217
|
+
void um_queue_free(struct um_queue *queue);
|
218
|
+
void um_queue_mark(struct um_queue *queue);
|
219
|
+
void um_queue_compact(struct um_queue *queue);
|
220
|
+
VALUE um_queue_push(struct um *machine, struct um_queue *queue, VALUE value);
|
221
|
+
VALUE um_queue_pop(struct um *machine, struct um_queue *queue);
|
222
|
+
VALUE um_queue_unshift(struct um *machine, struct um_queue *queue, VALUE value);
|
223
|
+
VALUE um_queue_shift(struct um *machine, struct um_queue *queue);
|
224
|
+
|
225
|
+
void um_define_net_constants(VALUE mod);
|
124
226
|
|
125
227
|
#endif // UM_H
|
data/ext/um/um_buffer.c
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
#include "um.h"
|
2
|
+
|
3
|
+
inline long buffer_size(long len) {
|
4
|
+
len--;
|
5
|
+
len |= len >> 1;
|
6
|
+
len |= len >> 2;
|
7
|
+
len |= len >> 4;
|
8
|
+
len |= len >> 8;
|
9
|
+
len |= len >> 16;
|
10
|
+
len++;
|
11
|
+
return (len > 4096) ? len : 4096;
|
12
|
+
}
|
13
|
+
|
14
|
+
inline struct um_buffer *um_buffer_checkout(struct um *machine, int len) {
|
15
|
+
struct um_buffer *buffer = machine->buffer_freelist;
|
16
|
+
if (buffer)
|
17
|
+
machine->buffer_freelist = buffer->next;
|
18
|
+
else {
|
19
|
+
buffer = malloc(sizeof(struct um_buffer));
|
20
|
+
memset(buffer, 0, sizeof(struct um_buffer));
|
21
|
+
}
|
22
|
+
|
23
|
+
if (buffer->len < len) {
|
24
|
+
if (buffer->ptr) {
|
25
|
+
free(buffer->ptr);
|
26
|
+
buffer->ptr = NULL;
|
27
|
+
}
|
28
|
+
|
29
|
+
buffer->len = buffer_size(len);
|
30
|
+
if (posix_memalign(&buffer->ptr, 4096, buffer->len))
|
31
|
+
rb_raise(rb_eRuntimeError, "Failed to allocate buffer");
|
32
|
+
}
|
33
|
+
return buffer;
|
34
|
+
}
|
35
|
+
|
36
|
+
inline void um_buffer_checkin(struct um *machine, struct um_buffer *buffer) {
|
37
|
+
buffer->next = machine->buffer_freelist;
|
38
|
+
machine->buffer_freelist = buffer;
|
39
|
+
}
|
40
|
+
|
41
|
+
inline void um_free_buffer_linked_list(struct um *machine) {
|
42
|
+
struct um_buffer *buffer = machine->buffer_freelist;
|
43
|
+
while (buffer) {
|
44
|
+
struct um_buffer *next = buffer->next;
|
45
|
+
if (buffer->ptr) free(buffer->ptr);
|
46
|
+
free(buffer);
|
47
|
+
buffer = next;
|
48
|
+
}
|
49
|
+
}
|