sleepy_penguin 3.2.0 → 3.3.0

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.
data/GIT-VERSION-GEN CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/bin/sh
2
2
 
3
3
  GVF=GIT-VERSION-FILE
4
- DEF_VER=v3.2.0
4
+ DEF_VER=v3.3.0
5
5
  GVH=ext/sleepy_penguin/git_version.h
6
6
 
7
7
  LF='
data/GNUmakefile CHANGED
@@ -6,7 +6,6 @@ include pkg.mk
6
6
  pkg_extra += ext/sleepy_penguin/git_version.h
7
7
  ifneq ($(VERSION),)
8
8
  release::
9
- $(RAKE) raa_update VERSION=$(VERSION)
10
9
  $(RAKE) publish_news VERSION=$(VERSION)
11
10
  endif
12
11
  .PHONY: .FORCE-GIT-VERSION-FILE doc test $(test_units) manifest
data/Rakefile CHANGED
@@ -31,40 +31,3 @@ task :publish_news do
31
31
  rf.login
32
32
  rf.post_news('rainbows', subject, body)
33
33
  end
34
-
35
- desc "post to RAA"
36
- task :raa_update do
37
- require 'net/http'
38
- require 'net/netrc'
39
- rc = Net::Netrc.locate('sleepy_penguin-raa') or abort "~/.netrc not found"
40
- password = rc.password
41
-
42
- s = Gem::Specification.load('sleepy_penguin.gemspec')
43
- desc = [ s.description.strip ]
44
- desc << ""
45
- desc << "* #{s.email}"
46
- desc << "* #{git_url}"
47
- desc << "* #{cgit_url}"
48
- desc = desc.join("\n")
49
- uri = URI.parse('http://raa.ruby-lang.org/regist.rhtml')
50
- form = {
51
- :name => s.name,
52
- :short_description => s.summary,
53
- :version => s.version.to_s,
54
- :status => 'experimental',
55
- :owner => s.authors.first,
56
- :email => s.email,
57
- :category_major => 'Library',
58
- :category_minor => 'System',
59
- :url => s.homepage,
60
- :download => 'http://rubyforge.org/frs/?group_id=8977',
61
- :license => "LGPL",
62
- :description_style => 'Plain',
63
- :description => desc,
64
- :pass => password,
65
- :submit => 'Update',
66
- }
67
- res = Net::HTTP.post_form(uri, form)
68
- p res
69
- puts res.body
70
- end
@@ -1,8 +1,8 @@
1
1
  #include "sleepy_penguin.h"
2
2
  #ifdef HAVE_SYS_EPOLL_H
3
3
  #include <sys/epoll.h>
4
- #include <unistd.h>
5
4
  #include <time.h>
5
+ #include "missing_clock_gettime.h"
6
6
  #include "missing_epoll.h"
7
7
  #include "missing_rb_thread_fd_close.h"
8
8
  #include "missing_rb_update_max_fd.h"
@@ -51,10 +51,8 @@ static int ep_fd_check(struct ep_per_thread *ept)
51
51
 
52
52
  static struct ep_per_thread *ept_get(VALUE self, int maxevents)
53
53
  {
54
- static __thread struct ep_per_thread *ept;
54
+ struct ep_per_thread *ept;
55
55
  size_t size;
56
- int err;
57
- void *ptr;
58
56
 
59
57
  /* error check here to prevent OOM from posix_memalign */
60
58
  if (maxevents <= 0) {
@@ -62,21 +60,11 @@ static struct ep_per_thread *ept_get(VALUE self, int maxevents)
62
60
  rb_sys_fail("epoll_wait maxevents <= 0");
63
61
  }
64
62
 
65
- if (ept && ept->capa >= maxevents)
66
- goto out;
67
-
68
63
  size = sizeof(struct ep_per_thread) +
69
64
  sizeof(struct epoll_event) * maxevents;
70
65
 
71
- free(ept); /* free(NULL) is POSIX and works on glibc */
72
- err = posix_memalign(&ptr, rb_sp_l1_cache_line_size, size);
73
- if (err) {
74
- errno = err;
75
- rb_memerror();
76
- }
77
- ept = ptr;
66
+ ept = rb_sp_gettlsbuf(&size);
78
67
  ept->capa = maxevents;
79
- out:
80
68
  ept->maxevents = maxevents;
81
69
  ept->io = self;
82
70
  ept->fd = rb_sp_fileno(ept->io);
@@ -1,8 +1,9 @@
1
1
  require 'mkmf'
2
2
  have_header('sys/epoll.h')
3
3
  dir_config('kqueue')
4
- have_library('kqueue')
5
- have_header('sys/event.h')
4
+ if have_header('sys/event.h')
5
+ have_library('kqueue')
6
+ end
6
7
  have_header('sys/mount.h')
7
8
  have_header('sys/eventfd.h')
8
9
 
@@ -13,6 +14,11 @@ have_header('sys/eventfd.h')
13
14
  have_header('sys/timerfd.h')
14
15
  have_header('sys/inotify.h')
15
16
  have_header('ruby/io.h') and have_struct_member('rb_io_t', 'fd', 'ruby/io.h')
17
+ unless have_macro('CLOCK_MONOTONIC', 'time.h')
18
+ have_func('CLOCK_MONOTONIC', 'time.h')
19
+ end
20
+ have_type('clockid_t', 'time.h')
21
+ have_func('clock_gettime', 'time.h')
16
22
  have_func('epoll_create1', %w(sys/epoll.h))
17
23
  have_func('rb_thread_call_without_gvl')
18
24
  have_func('rb_thread_blocking_region')
@@ -20,4 +26,5 @@ have_func('rb_thread_io_blocking_region')
20
26
  have_func('rb_thread_fd_close')
21
27
  have_func('rb_update_max_fd')
22
28
  have_func('rb_fd_fix_cloexec')
29
+ have_func('rb_io_get_io')
23
30
  create_makefile('sleepy_penguin_ext')
@@ -1,10 +1,20 @@
1
- #define _GNU_SOURCE
2
1
  #include <ruby.h>
2
+ #ifndef _GNU_SOURCE
3
+ # define _GNU_SOURCE /* TODO: confirm this is needed */
4
+ #endif
5
+
3
6
  #include <unistd.h>
7
+ #include <pthread.h>
4
8
  #include <sys/types.h>
5
9
  #include "git_version.h"
10
+ #include "sleepy_penguin.h"
6
11
  #define L1_CACHE_LINE_MAX 128 /* largest I've seen (Pentium 4) */
7
12
  size_t rb_sp_l1_cache_line_size;
13
+ static pthread_key_t rb_sp_key;
14
+ struct rb_sp_tlsbuf {
15
+ size_t capa;
16
+ unsigned char ptr[FLEX_ARRAY];
17
+ };
8
18
 
9
19
  #ifdef HAVE_SYS_EVENT_H
10
20
  void sleepy_penguin_init_kqueue(void);
@@ -53,9 +63,57 @@ static size_t l1_cache_line_size_detect(void)
53
63
  return L1_CACHE_LINE_MAX;
54
64
  }
55
65
 
66
+ static void sp_once(void)
67
+ {
68
+ int err = pthread_key_create(&rb_sp_key, free);
69
+
70
+ if (err) {
71
+ errno = err;
72
+ rb_sys_fail( "pthread_key_create");
73
+ }
74
+ }
75
+
76
+ void *rb_sp_gettlsbuf(size_t *size)
77
+ {
78
+ struct rb_sp_tlsbuf *buf = pthread_getspecific(rb_sp_key);
79
+ void *ptr;
80
+ int err;
81
+ size_t bytes;
82
+
83
+ if (buf && buf->capa >= *size) {
84
+ *size = buf->capa;
85
+ goto out;
86
+ }
87
+
88
+ free(buf);
89
+ bytes = *size + sizeof(struct rb_sp_tlsbuf);
90
+ err = posix_memalign(&ptr, rb_sp_l1_cache_line_size, bytes);
91
+ if (err) {
92
+ errno = err;
93
+ rb_memerror(); /* fatal */
94
+ }
95
+
96
+ buf = ptr;
97
+ buf->capa = *size;
98
+ err = pthread_setspecific(rb_sp_key, buf);
99
+ if (err != 0) {
100
+ errno = err;
101
+ rb_sys_fail("BUG: pthread_setspecific");
102
+ }
103
+ out:
104
+ return buf->ptr;
105
+ }
106
+
56
107
  void Init_sleepy_penguin_ext(void)
57
108
  {
58
109
  VALUE mSleepyPenguin;
110
+ static pthread_once_t once = PTHREAD_ONCE_INIT;
111
+ int err = pthread_once(&once, sp_once);
112
+
113
+ if (err) {
114
+ errno = err;
115
+ rb_sys_fail("pthread_once");
116
+ }
59
117
 
60
118
  rb_sp_l1_cache_line_size = l1_cache_line_size_detect();
61
119
 
@@ -4,11 +4,6 @@
4
4
  #include <sys/ioctl.h>
5
5
  #include "missing_inotify.h"
6
6
 
7
- struct inbuf {
8
- size_t capa;
9
- void *ptr;
10
- };
11
-
12
7
  static ID id_inotify_tmp, id_mask;
13
8
  static VALUE cEvent, checks;
14
9
 
@@ -137,43 +132,31 @@ static VALUE event_new(struct inotify_event *e)
137
132
 
138
133
  struct inread_args {
139
134
  int fd;
140
- struct inbuf *inbuf;
135
+ size_t size;
136
+ void *buf;
141
137
  };
142
138
 
143
139
  static VALUE inread(void *ptr)
144
140
  {
145
141
  struct inread_args *args = ptr;
146
142
 
147
- return (VALUE)read(args->fd, args->inbuf->ptr, args->inbuf->capa);
148
- }
149
-
150
- static void inbuf_grow(struct inbuf *inbuf, size_t size)
151
- {
152
- int err;
153
-
154
- if (inbuf->capa >= size)
155
- return;
156
- free(inbuf->ptr);
157
- err = posix_memalign(&inbuf->ptr, rb_sp_l1_cache_line_size, size);
158
- if (err) {
159
- errno = err;
160
- rb_memerror();
161
- }
162
- inbuf->capa = size;
143
+ return (VALUE)read(args->fd, args->buf, args->size);
163
144
  }
164
145
 
165
146
  static void resize_internal_buffer(struct inread_args *args)
166
147
  {
167
148
  int newlen;
168
149
 
169
- if (args->inbuf->capa > 0x10000)
150
+ if (args->size > 0x10000)
170
151
  rb_raise(rb_eRuntimeError, "path too long");
171
152
 
172
153
  if (ioctl(args->fd, FIONREAD, &newlen) != 0)
173
154
  rb_sys_fail("ioctl(inotify,FIONREAD)");
174
155
 
175
- if (newlen > 0)
176
- inbuf_grow(args->inbuf, (size_t)newlen);
156
+ if (newlen > 0) {
157
+ args->size = (size_t)newlen;
158
+ args->buf = rb_sp_gettlsbuf(&args->size);
159
+ }
177
160
 
178
161
  if (newlen == 0) /* race: some other thread grabbed the data */
179
162
  return;
@@ -192,8 +175,6 @@ static void resize_internal_buffer(struct inread_args *args)
192
175
  */
193
176
  static VALUE take(int argc, VALUE *argv, VALUE self)
194
177
  {
195
- static __thread struct inbuf inbuf;
196
-
197
178
  struct inread_args args;
198
179
  VALUE tmp = rb_ivar_get(self, id_inotify_tmp);
199
180
  struct inotify_event *e, *end;
@@ -206,9 +187,9 @@ static VALUE take(int argc, VALUE *argv, VALUE self)
206
187
 
207
188
  rb_scan_args(argc, argv, "01", &nonblock);
208
189
 
209
- inbuf_grow(&inbuf, 128);
210
190
  args.fd = rb_sp_fileno(self);
211
- args.inbuf = &inbuf;
191
+ args.size = 128;
192
+ args.buf = rb_sp_gettlsbuf(&args.size);
212
193
 
213
194
  if (RTEST(nonblock))
214
195
  rb_sp_set_nonblock(args.fd);
@@ -228,9 +209,8 @@ static VALUE take(int argc, VALUE *argv, VALUE self)
228
209
  rb_sys_fail("read(inotify)");
229
210
  } else {
230
211
  /* buffer in userspace to minimize read() calls */
231
- end = (struct inotify_event *)
232
- ((char *)args.inbuf->ptr + r);
233
- for (e = args.inbuf->ptr; e < end; ) {
212
+ end = (struct inotify_event *)((char *)args.buf + r);
213
+ for (e = args.buf; e < end; ) {
234
214
  VALUE event = event_new(e);
235
215
  if (NIL_P(rv))
236
216
  rv = event;
@@ -255,15 +235,15 @@ static VALUE take(int argc, VALUE *argv, VALUE self)
255
235
  static VALUE events(VALUE self)
256
236
  {
257
237
  long len = RARRAY_LEN(checks);
258
- VALUE *ptr = RARRAY_PTR(checks);
238
+ long i;
259
239
  VALUE sym;
260
240
  VALUE rv = rb_ary_new();
261
241
  uint32_t mask;
262
242
  uint32_t event_mask = NUM2UINT(rb_funcall(self, id_mask, 0));
263
243
 
264
- for (; (len -= 2) >= 0;) {
265
- sym = *ptr++;
266
- mask = NUM2UINT(*ptr++);
244
+ for (i = 0; i < len; ) {
245
+ sym = rb_ary_entry(checks, i++);
246
+ mask = NUM2UINT(rb_ary_entry(checks, i++));
267
247
  if ((event_mask & mask) == mask)
268
248
  rb_ary_push(rv, sym);
269
249
  }
@@ -5,6 +5,7 @@
5
5
  #include <sys/time.h>
6
6
  #include <unistd.h>
7
7
  #include <time.h>
8
+ #include "missing_clock_gettime.h"
8
9
  #include "missing_rb_thread_fd_close.h"
9
10
  #include "missing_rb_update_max_fd.h"
10
11
  #include "value2timespec.h"
@@ -73,10 +74,8 @@ static int kq_fd_check(struct kq_per_thread *kpt)
73
74
 
74
75
  static struct kq_per_thread *kpt_get(VALUE self, int nchanges, int nevents)
75
76
  {
76
- static __thread struct kq_per_thread *kpt;
77
+ struct kq_per_thread *kpt;
77
78
  size_t size;
78
- void *ptr;
79
- int err;
80
79
  int max = nchanges > nevents ? nchanges : nevents;
81
80
 
82
81
  /* error check here to prevent OOM from posix_memalign */
@@ -85,20 +84,9 @@ static struct kq_per_thread *kpt_get(VALUE self, int nchanges, int nevents)
85
84
  rb_sys_fail("kevent got negative events < 0");
86
85
  }
87
86
 
88
- if (kpt && kpt->capa >= max)
89
- goto out;
90
-
91
87
  size = sizeof(struct kq_per_thread) + sizeof(struct kevent) * max;
92
-
93
- free(kpt); /* free(NULL) is POSIX */
94
- err = posix_memalign(&ptr, rb_sp_l1_cache_line_size, size);
95
- if (err) {
96
- errno = err;
97
- rb_memerror();
98
- }
99
- kpt = ptr;
88
+ kpt = rb_sp_gettlsbuf(&size);
100
89
  kpt->capa = max;
101
- out:
102
90
  kpt->nchanges = nchanges;
103
91
  kpt->nevents = nevents;
104
92
  kpt->io = self;
@@ -0,0 +1,36 @@
1
+ /*
2
+ * this header includes functions to support broken systems
3
+ * without clock_gettime() or CLOCK_MONOTONIC
4
+ */
5
+
6
+ #ifndef HAVE_TYPE_CLOCKID_T
7
+ typedef int clockid_t;
8
+ #endif
9
+
10
+ #ifndef HAVE_CLOCK_GETTIME
11
+ # ifndef CLOCK_REALTIME
12
+ # define CLOCK_REALTIME 0 /* whatever */
13
+ # endif
14
+ static int fake_clock_gettime(clockid_t clk_id, struct timespec *res)
15
+ {
16
+ struct timeval tv;
17
+ int r = gettimeofday(&tv, NULL);
18
+
19
+ assert(0 == r && "gettimeofday() broke!?");
20
+ res->tv_sec = tv.tv_sec;
21
+ res->tv_nsec = tv.tv_usec * 1000;
22
+
23
+ return r;
24
+ }
25
+ # define clock_gettime fake_clock_gettime
26
+ #endif /* broken systems w/o clock_gettime() */
27
+
28
+ /*
29
+ * UGH
30
+ * CLOCK_MONOTONIC is not guaranteed to be a macro, either
31
+ */
32
+ #ifndef CLOCK_MONOTONIC
33
+ # if (!defined(_POSIX_MONOTONIC_CLOCK) || !defined(HAVE_CLOCK_MONOTONIC))
34
+ # define CLOCK_MONOTONIC CLOCK_REALTIME
35
+ # endif
36
+ #endif
@@ -77,6 +77,7 @@ static inline VALUE fake_blocking_region(VALUE (*fn)(void *), void *data)
77
77
 
78
78
  typedef int rb_sp_waitfn(int fd);
79
79
  int rb_sp_wait(rb_sp_waitfn waiter, VALUE obj, int *fd);
80
+ void *rb_sp_gettlsbuf(size_t *size);
80
81
 
81
82
  /* Flexible array elements are standard in C99 */
82
83
  #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
@@ -1,5 +1,13 @@
1
1
  #include "sleepy_penguin.h"
2
2
 
3
+ #ifndef HAVE_RB_IO_GET_IO
4
+ static VALUE my_io_get_io(VALUE io)
5
+ {
6
+ return rb_convert_type(io, T_FILE, "IO", "to_io");
7
+ }
8
+ # define rb_io_get_io(io) my_io_get_io((io))
9
+ #endif /* HAVE_RB_IO_GET_IO */
10
+
3
11
  static VALUE klass_for(VALUE klass)
4
12
  {
5
13
  return (TYPE(klass) == T_CLASS) ? klass : CLASS_OF(klass);
@@ -14,13 +22,13 @@ int rb_sp_get_flags(VALUE klass, VALUE flags, int default_flags)
14
22
  case T_SYMBOL:
15
23
  return NUM2INT(rb_const_get(klass_for(klass), SYM2ID(flags)));
16
24
  case T_ARRAY: {
17
- VALUE *ptr = RARRAY_PTR(flags);
25
+ long i;
18
26
  long len = RARRAY_LEN(flags);
19
27
  int rv = 0;
20
28
 
21
29
  klass = klass_for(klass);
22
- while (--len >= 0) {
23
- VALUE tmp = *ptr++;
30
+ for (i = 0; i < len; i++) {
31
+ VALUE tmp = rb_ary_entry(flags, i);
24
32
 
25
33
  Check_Type(tmp, T_SYMBOL);
26
34
  tmp = rb_const_get(klass, SYM2ID(tmp));
@@ -42,13 +50,13 @@ unsigned rb_sp_get_uflags(VALUE klass, VALUE flags)
42
50
  case T_SYMBOL:
43
51
  return NUM2UINT(rb_const_get(klass_for(klass), SYM2ID(flags)));
44
52
  case T_ARRAY: {
45
- VALUE *ptr = RARRAY_PTR(flags);
53
+ long i;
46
54
  long len = RARRAY_LEN(flags);
47
55
  unsigned rv = 0;
48
56
 
49
57
  klass = klass_for(klass);
50
- while (--len >= 0) {
51
- VALUE tmp = *ptr++;
58
+ for (i = 0; i < len; i++) {
59
+ VALUE tmp = rb_ary_entry(flags, i);
52
60
 
53
61
  Check_Type(tmp, T_SYMBOL);
54
62
  tmp = rb_const_get(klass, SYM2ID(tmp));
@@ -100,7 +108,7 @@ int rb_sp_io_closed(VALUE io)
100
108
  case T_FILE:
101
109
  break;
102
110
  default:
103
- io = rb_convert_type(io, T_FILE, "IO", "to_io");
111
+ io = rb_io_get_io(io);
104
112
  }
105
113
 
106
114
  return my_rb_io_closed(io);
@@ -110,7 +118,7 @@ int rb_sp_fileno(VALUE io)
110
118
  {
111
119
  rb_io_t *fptr;
112
120
 
113
- io = rb_convert_type(io, T_FILE, "IO", "to_io");
121
+ io = rb_io_get_io(io);
114
122
  GetOpenFile(io, fptr);
115
123
  return FPTR_TO_FD(fptr);
116
124
  }