sleepy_penguin 3.2.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
  }