sleepy_penguin.git  about / heads / tags
Linux I/O events for Ruby
blob 860c5f5f6ef100a74d8a59d665fce55f20fb89dc 1558 bytes (raw)
$ git show pu:ext/sleepy_penguin/cfr.c	# shows this blob on the CLI

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
 
#include "sleepy_penguin.h"
#include "sp_copy.h"
#include <unistd.h>

#ifdef __NR_copy_file_range
static ssize_t my_cfr(int fd_in, off_t *off_in, int fd_out, off_t *off_out,
		       size_t len, unsigned int flags)
{
	long n = syscall(__NR_copy_file_range,
			fd_in, off_in, fd_out, off_out, len, flags);

	return (ssize_t)n;
}
#  define copy_file_range(fd_in,off_in,fd_out,off_out,len,flags) \
		my_cfr((fd_in),(off_in),(fd_out),(off_out),(len),(flags))
#endif

#if defined(HAVE_COPY_FILE_RANGE) || \
    (defined(__linux__) && defined(__NR_copy_file_range))
static void *nogvl_cfr(void *ptr)
{
	struct copy_args *a = ptr;

	return (void *)copy_file_range(a->fd_in, a->off_in,
				a->fd_out, a->off_out, a->len, a->flags);
}

/* :nodoc: */
static VALUE rb_sp_cfr(VALUE mod, VALUE io_in, VALUE off_in,
			VALUE io_out, VALUE off_out,
			VALUE len, VALUE flags)
{
	off_t i = 0, o = 0;
	struct copy_args a;
	ssize_t bytes;

	a.off_in = NIL_P(off_in) ? NULL : (i = NUM2OFFT(off_in), &i);
	a.off_out = NIL_P(off_out) ? NULL : (o = NUM2OFFT(off_out), &o);
	a.len = NUM2SIZET(len);
	a.flags = NUM2UINT(flags);

	for (;;) {
		a.fd_in = rb_sp_fileno(io_in);
		a.fd_out = rb_sp_fileno(io_out);
		bytes = (ssize_t)IO_RUN(nogvl_cfr, &a);
		if (bytes < 0) {
			switch (errno) {
			case EINTR: continue;
			default: rb_sys_fail("copy_file_range");
			}
		}
		return SSIZET2NUM(bytes);
	}
}

void sleepy_penguin_init_cfr(void)
{
	VALUE mod = rb_define_module("SleepyPenguin");

	rb_define_singleton_method(mod, "__cfr", rb_sp_cfr, 6);
}
#endif /* !HAVE_COPY_FILE_RANGE */

git clone https://yhbt.net/sleepy_penguin.git