ebb 0.0.1

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/bin/ebb_rails ADDED
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../ruby_lib/ebb'
3
+ require 'optparse'
4
+ require 'rubygems'
5
+ require 'rack'
6
+
7
+ module Rack
8
+ module Adapter
9
+ autoload :Rails, Ebb::LIBDIR + '/rack/adapter/rails'
10
+ end
11
+ end
12
+
13
+ options = {
14
+ :root => Dir.pwd,
15
+ :env => 'development',
16
+ :hort => '0.0.0.0',
17
+ :port => 3000,
18
+ :timeout => 60,
19
+ :log_file => 'log/ebb.log',
20
+ :pid_file => 'tmp/pids/ebb.pid'
21
+ }
22
+
23
+
24
+ opts = OptionParser.new do |opts|
25
+ opts.banner = "Usage: ebb_rails [options] start|stop"
26
+
27
+ opts.separator ""
28
+ opts.separator "Server options:"
29
+
30
+ opts.on("-s", "--socket SOCKET", "listen on socket") { |socket| options[:socket] = socket }
31
+ opts.on("-p", "--port PORT", "use PORT (default: 3000)") { |port| options[:port] = port }
32
+ opts.on("-e", "--env ENV", "Rails environment (default: development)") { |env| options[:env] = env }
33
+ opts.on("-c", "--chdir PATH", "Rails root dir (default: current dir)") { |dir| options[:root] = dir }
34
+ opts.on("-d", "--daemonize", "Daemonize") { options[:daemonize] = true }
35
+ opts.on("-l", "--log-file FILE", "File to redirect output",
36
+ "(default: #{options[:log_file]})") { |file| options[:log_file] = file }
37
+ opts.on("-P", "--pid-file FILE", "File to store PID",
38
+ "(default: #{options[:pid_file]})") { |file| options[:pid_file] = file }
39
+ opts.on("-t", "--timeout SEC", "Request or command timeout in sec",
40
+ "(default: #{options[:timeout]})") { |sec| options[:timeout] = sec; raise NotImplementedError } # TODO: fix me
41
+ opts.on("-u", "--user NAME", "User to run daemon as (use with -g)") { |user| options[:user] = user }
42
+ opts.on("-g", "--group NAME", "Group to run daemon as (use with -u)") { |group| options[:group] = group }
43
+
44
+ opts.separator ""
45
+ opts.separator "Common options:"
46
+
47
+ opts.on_tail("-h", "--help", "Show this message") do
48
+ puts opts
49
+ exit
50
+ end
51
+
52
+ opts.on_tail('-v', '--version', "Show version") do
53
+ puts "Ebb #{Ebb::VERSION}"
54
+ exit
55
+ end
56
+
57
+ opts.parse! ARGV
58
+ end
59
+
60
+ case ARGV[0]
61
+
62
+ when 'start'
63
+ app = Rack::Adapter::Rails.new(options)
64
+ server = Ebb::Server.new(app, options)
65
+
66
+ server.pid_file = options[:pid_file]
67
+ server.log_file = options[:log_file]
68
+ # server.timeout = options[:timeout]
69
+
70
+ if options[:daemonize]
71
+ server.change_privilege options[:user], options[:group] if options[:user] && options[:group]
72
+ server.daemonize
73
+ end
74
+
75
+ server.start
76
+
77
+ when 'stop'
78
+ Ebb::Server.kill options[:pid_file], options[:timeout]
79
+
80
+ when nil
81
+ puts "Command required"
82
+ puts opts
83
+ exit 1
84
+
85
+ else
86
+ abort "Invalid command : #{ARGV[0]}"
87
+
88
+ end
data/libev/ev.c ADDED
@@ -0,0 +1,2440 @@
1
+ /*
2
+ * libev event processing core, watcher management
3
+ *
4
+ * Copyright (c) 2007 Marc Alexander Lehmann <libev@schmorp.de>
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are
9
+ * met:
10
+ *
11
+ * * Redistributions of source code must retain the above copyright
12
+ * notice, this list of conditions and the following disclaimer.
13
+ *
14
+ * * Redistributions in binary form must reproduce the above
15
+ * copyright notice, this list of conditions and the following
16
+ * disclaimer in the documentation and/or other materials provided
17
+ * with the distribution.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ */
31
+
32
+ #ifdef __cplusplus
33
+ extern "C" {
34
+ #endif
35
+
36
+ #ifndef EV_STANDALONE
37
+ # ifdef EV_CONFIG_H
38
+ # include EV_CONFIG_H
39
+ # else
40
+ # include "config.h"
41
+ # endif
42
+
43
+ # if HAVE_CLOCK_GETTIME
44
+ # ifndef EV_USE_MONOTONIC
45
+ # define EV_USE_MONOTONIC 1
46
+ # endif
47
+ # ifndef EV_USE_REALTIME
48
+ # define EV_USE_REALTIME 1
49
+ # endif
50
+ # else
51
+ # ifndef EV_USE_MONOTONIC
52
+ # define EV_USE_MONOTONIC 0
53
+ # endif
54
+ # ifndef EV_USE_REALTIME
55
+ # define EV_USE_REALTIME 0
56
+ # endif
57
+ # endif
58
+
59
+ # ifndef EV_USE_NANOSLEEP
60
+ # if HAVE_NANOSLEEP
61
+ # define EV_USE_NANOSLEEP 1
62
+ # else
63
+ # define EV_USE_NANOSLEEP 0
64
+ # endif
65
+ # endif
66
+
67
+ # ifndef EV_USE_SELECT
68
+ # if HAVE_SELECT && HAVE_SYS_SELECT_H
69
+ # define EV_USE_SELECT 1
70
+ # else
71
+ # define EV_USE_SELECT 0
72
+ # endif
73
+ # endif
74
+
75
+ # ifndef EV_USE_POLL
76
+ # if HAVE_POLL && HAVE_POLL_H
77
+ # define EV_USE_POLL 1
78
+ # else
79
+ # define EV_USE_POLL 0
80
+ # endif
81
+ # endif
82
+
83
+ # ifndef EV_USE_EPOLL
84
+ # if HAVE_EPOLL_CTL && HAVE_SYS_EPOLL_H
85
+ # define EV_USE_EPOLL 1
86
+ # else
87
+ # define EV_USE_EPOLL 0
88
+ # endif
89
+ # endif
90
+
91
+ # ifndef EV_USE_KQUEUE
92
+ # if HAVE_KQUEUE && HAVE_SYS_EVENT_H && HAVE_SYS_QUEUE_H
93
+ # define EV_USE_KQUEUE 1
94
+ # else
95
+ # define EV_USE_KQUEUE 0
96
+ # endif
97
+ # endif
98
+
99
+ # ifndef EV_USE_PORT
100
+ # if HAVE_PORT_H && HAVE_PORT_CREATE
101
+ # define EV_USE_PORT 1
102
+ # else
103
+ # define EV_USE_PORT 0
104
+ # endif
105
+ # endif
106
+
107
+ # ifndef EV_USE_INOTIFY
108
+ # if HAVE_INOTIFY_INIT && HAVE_SYS_INOTIFY_H
109
+ # define EV_USE_INOTIFY 1
110
+ # else
111
+ # define EV_USE_INOTIFY 0
112
+ # endif
113
+ # endif
114
+
115
+ #endif
116
+
117
+ #include <math.h>
118
+ #include <stdlib.h>
119
+ #include <fcntl.h>
120
+ #include <stddef.h>
121
+
122
+ #include <stdio.h>
123
+
124
+ #include <assert.h>
125
+ #include <errno.h>
126
+ #include <sys/types.h>
127
+ #include <time.h>
128
+
129
+ #include <signal.h>
130
+
131
+ #ifdef EV_H
132
+ # include EV_H
133
+ #else
134
+ # include "ev.h"
135
+ #endif
136
+
137
+ #ifndef _WIN32
138
+ # include <sys/time.h>
139
+ # include <sys/wait.h>
140
+ # include <unistd.h>
141
+ #else
142
+ # define WIN32_LEAN_AND_MEAN
143
+ # include <windows.h>
144
+ # ifndef EV_SELECT_IS_WINSOCKET
145
+ # define EV_SELECT_IS_WINSOCKET 1
146
+ # endif
147
+ #endif
148
+
149
+ /**/
150
+
151
+ #ifndef EV_USE_MONOTONIC
152
+ # define EV_USE_MONOTONIC 0
153
+ #endif
154
+
155
+ #ifndef EV_USE_REALTIME
156
+ # define EV_USE_REALTIME 0
157
+ #endif
158
+
159
+ #ifndef EV_USE_NANOSLEEP
160
+ # define EV_USE_NANOSLEEP 0
161
+ #endif
162
+
163
+ #ifndef EV_USE_SELECT
164
+ # define EV_USE_SELECT 1
165
+ #endif
166
+
167
+ #ifndef EV_USE_POLL
168
+ # ifdef _WIN32
169
+ # define EV_USE_POLL 0
170
+ # else
171
+ # define EV_USE_POLL 1
172
+ # endif
173
+ #endif
174
+
175
+ #ifndef EV_USE_EPOLL
176
+ # define EV_USE_EPOLL 0
177
+ #endif
178
+
179
+ #ifndef EV_USE_KQUEUE
180
+ # define EV_USE_KQUEUE 0
181
+ #endif
182
+
183
+ #ifndef EV_USE_PORT
184
+ # define EV_USE_PORT 0
185
+ #endif
186
+
187
+ #ifndef EV_USE_INOTIFY
188
+ # define EV_USE_INOTIFY 0
189
+ #endif
190
+
191
+ #ifndef EV_PID_HASHSIZE
192
+ # if EV_MINIMAL
193
+ # define EV_PID_HASHSIZE 1
194
+ # else
195
+ # define EV_PID_HASHSIZE 16
196
+ # endif
197
+ #endif
198
+
199
+ #ifndef EV_INOTIFY_HASHSIZE
200
+ # if EV_MINIMAL
201
+ # define EV_INOTIFY_HASHSIZE 1
202
+ # else
203
+ # define EV_INOTIFY_HASHSIZE 16
204
+ # endif
205
+ #endif
206
+
207
+ /**/
208
+
209
+ #ifndef CLOCK_MONOTONIC
210
+ # undef EV_USE_MONOTONIC
211
+ # define EV_USE_MONOTONIC 0
212
+ #endif
213
+
214
+ #ifndef CLOCK_REALTIME
215
+ # undef EV_USE_REALTIME
216
+ # define EV_USE_REALTIME 0
217
+ #endif
218
+
219
+ #if !EV_STAT_ENABLE
220
+ # undef EV_USE_INOTIFY
221
+ # define EV_USE_INOTIFY 0
222
+ #endif
223
+
224
+ #if !EV_USE_NANOSLEEP
225
+ # ifndef _WIN32
226
+ # include <sys/select.h>
227
+ # endif
228
+ #endif
229
+
230
+ #if EV_USE_INOTIFY
231
+ # include <sys/inotify.h>
232
+ #endif
233
+
234
+ #if EV_SELECT_IS_WINSOCKET
235
+ # include <winsock.h>
236
+ #endif
237
+
238
+ /**/
239
+
240
+ /*
241
+ * This is used to avoid floating point rounding problems.
242
+ * It is added to ev_rt_now when scheduling periodics
243
+ * to ensure progress, time-wise, even when rounding
244
+ * errors are against us.
245
+ * This value is good at least till the year 4000.
246
+ * Better solutions welcome.
247
+ */
248
+ #define TIME_EPSILON 0.0001220703125 /* 1/8192 */
249
+
250
+ #define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */
251
+ #define MAX_BLOCKTIME 59.743 /* never wait longer than this time (to detect time jumps) */
252
+ /*#define CLEANUP_INTERVAL (MAX_BLOCKTIME * 5.) /* how often to try to free memory and re-check fds, TODO */
253
+
254
+ #if __GNUC__ >= 4
255
+ # define expect(expr,value) __builtin_expect ((expr),(value))
256
+ # define noinline __attribute__ ((noinline))
257
+ #else
258
+ # define expect(expr,value) (expr)
259
+ # define noinline
260
+ # if __STDC_VERSION__ < 199901L
261
+ # define inline
262
+ # endif
263
+ #endif
264
+
265
+ #define expect_false(expr) expect ((expr) != 0, 0)
266
+ #define expect_true(expr) expect ((expr) != 0, 1)
267
+ #define inline_size static inline
268
+
269
+ #if EV_MINIMAL
270
+ # define inline_speed static noinline
271
+ #else
272
+ # define inline_speed static inline
273
+ #endif
274
+
275
+ #define NUMPRI (EV_MAXPRI - EV_MINPRI + 1)
276
+ #define ABSPRI(w) (((W)w)->priority - EV_MINPRI)
277
+
278
+ #define EMPTY /* required for microsofts broken pseudo-c compiler */
279
+ #define EMPTY2(a,b) /* used to suppress some warnings */
280
+
281
+ typedef ev_watcher *W;
282
+ typedef ev_watcher_list *WL;
283
+ typedef ev_watcher_time *WT;
284
+
285
+ /* sig_atomic_t is used to avoid per-thread variables or locking but still */
286
+ /* giving it a reasonably high chance of working on typical architetcures */
287
+ static sig_atomic_t have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? */
288
+
289
+ #ifdef _WIN32
290
+ # include "ev_win32.c"
291
+ #endif
292
+
293
+ /*****************************************************************************/
294
+
295
+ static void (*syserr_cb)(const char *msg);
296
+
297
+ void
298
+ ev_set_syserr_cb (void (*cb)(const char *msg))
299
+ {
300
+ syserr_cb = cb;
301
+ }
302
+
303
+ static void noinline
304
+ syserr (const char *msg)
305
+ {
306
+ if (!msg)
307
+ msg = "(libev) system error";
308
+
309
+ if (syserr_cb)
310
+ syserr_cb (msg);
311
+ else
312
+ {
313
+ perror (msg);
314
+ abort ();
315
+ }
316
+ }
317
+
318
+ static void *(*alloc)(void *ptr, long size);
319
+
320
+ void
321
+ ev_set_allocator (void *(*cb)(void *ptr, long size))
322
+ {
323
+ alloc = cb;
324
+ }
325
+
326
+ inline_speed void *
327
+ ev_realloc (void *ptr, long size)
328
+ {
329
+ ptr = alloc ? alloc (ptr, size) : realloc (ptr, size);
330
+
331
+ if (!ptr && size)
332
+ {
333
+ fprintf (stderr, "libev: cannot allocate %ld bytes, aborting.", size);
334
+ abort ();
335
+ }
336
+
337
+ return ptr;
338
+ }
339
+
340
+ #define ev_malloc(size) ev_realloc (0, (size))
341
+ #define ev_free(ptr) ev_realloc ((ptr), 0)
342
+
343
+ /*****************************************************************************/
344
+
345
+ typedef struct
346
+ {
347
+ WL head;
348
+ unsigned char events;
349
+ unsigned char reify;
350
+ #if EV_SELECT_IS_WINSOCKET
351
+ SOCKET handle;
352
+ #endif
353
+ } ANFD;
354
+
355
+ typedef struct
356
+ {
357
+ W w;
358
+ int events;
359
+ } ANPENDING;
360
+
361
+ #if EV_USE_INOTIFY
362
+ typedef struct
363
+ {
364
+ WL head;
365
+ } ANFS;
366
+ #endif
367
+
368
+ #if EV_MULTIPLICITY
369
+
370
+ struct ev_loop
371
+ {
372
+ ev_tstamp ev_rt_now;
373
+ #define ev_rt_now ((loop)->ev_rt_now)
374
+ #define VAR(name,decl) decl;
375
+ #include "ev_vars.h"
376
+ #undef VAR
377
+ };
378
+ #include "ev_wrap.h"
379
+
380
+ static struct ev_loop default_loop_struct;
381
+ struct ev_loop *ev_default_loop_ptr;
382
+
383
+ #else
384
+
385
+ ev_tstamp ev_rt_now;
386
+ #define VAR(name,decl) static decl;
387
+ #include "ev_vars.h"
388
+ #undef VAR
389
+
390
+ static int ev_default_loop_ptr;
391
+
392
+ #endif
393
+
394
+ /*****************************************************************************/
395
+
396
+ ev_tstamp
397
+ ev_time (void)
398
+ {
399
+ #if EV_USE_REALTIME
400
+ struct timespec ts;
401
+ clock_gettime (CLOCK_REALTIME, &ts);
402
+ return ts.tv_sec + ts.tv_nsec * 1e-9;
403
+ #else
404
+ struct timeval tv;
405
+ gettimeofday (&tv, 0);
406
+ return tv.tv_sec + tv.tv_usec * 1e-6;
407
+ #endif
408
+ }
409
+
410
+ ev_tstamp inline_size
411
+ get_clock (void)
412
+ {
413
+ #if EV_USE_MONOTONIC
414
+ if (expect_true (have_monotonic))
415
+ {
416
+ struct timespec ts;
417
+ clock_gettime (CLOCK_MONOTONIC, &ts);
418
+ return ts.tv_sec + ts.tv_nsec * 1e-9;
419
+ }
420
+ #endif
421
+
422
+ return ev_time ();
423
+ }
424
+
425
+ #if EV_MULTIPLICITY
426
+ ev_tstamp
427
+ ev_now (EV_P)
428
+ {
429
+ return ev_rt_now;
430
+ }
431
+ #endif
432
+
433
+ void
434
+ ev_sleep (ev_tstamp delay)
435
+ {
436
+ if (delay > 0.)
437
+ {
438
+ #if EV_USE_NANOSLEEP
439
+ struct timespec ts;
440
+
441
+ ts.tv_sec = (time_t)delay;
442
+ ts.tv_nsec = (long)((delay - (ev_tstamp)(ts.tv_sec)) * 1e9);
443
+
444
+ nanosleep (&ts, 0);
445
+ #elif defined(_WIN32)
446
+ Sleep (delay * 1e3);
447
+ #else
448
+ struct timeval tv;
449
+
450
+ tv.tv_sec = (time_t)delay;
451
+ tv.tv_usec = (long)((delay - (ev_tstamp)(tv.tv_sec)) * 1e6);
452
+
453
+ select (0, 0, 0, 0, &tv);
454
+ #endif
455
+ }
456
+ }
457
+
458
+ /*****************************************************************************/
459
+
460
+ int inline_size
461
+ array_nextsize (int elem, int cur, int cnt)
462
+ {
463
+ int ncur = cur + 1;
464
+
465
+ do
466
+ ncur <<= 1;
467
+ while (cnt > ncur);
468
+
469
+ /* if size > 4096, round to 4096 - 4 * longs to accomodate malloc overhead */
470
+ if (elem * ncur > 4096)
471
+ {
472
+ ncur *= elem;
473
+ ncur = (ncur + elem + 4095 + sizeof (void *) * 4) & ~4095;
474
+ ncur = ncur - sizeof (void *) * 4;
475
+ ncur /= elem;
476
+ }
477
+
478
+ return ncur;
479
+ }
480
+
481
+ static noinline void *
482
+ array_realloc (int elem, void *base, int *cur, int cnt)
483
+ {
484
+ *cur = array_nextsize (elem, *cur, cnt);
485
+ return ev_realloc (base, elem * *cur);
486
+ }
487
+
488
+ #define array_needsize(type,base,cur,cnt,init) \
489
+ if (expect_false ((cnt) > (cur))) \
490
+ { \
491
+ int ocur_ = (cur); \
492
+ (base) = (type *)array_realloc \
493
+ (sizeof (type), (base), &(cur), (cnt)); \
494
+ init ((base) + (ocur_), (cur) - ocur_); \
495
+ }
496
+
497
+ #if 0
498
+ #define array_slim(type,stem) \
499
+ if (stem ## max < array_roundsize (stem ## cnt >> 2)) \
500
+ { \
501
+ stem ## max = array_roundsize (stem ## cnt >> 1); \
502
+ base = (type *)ev_realloc (base, sizeof (type) * (stem ## max));\
503
+ fprintf (stderr, "slimmed down " # stem " to %d\n", stem ## max);/*D*/\
504
+ }
505
+ #endif
506
+
507
+ #define array_free(stem, idx) \
508
+ ev_free (stem ## s idx); stem ## cnt idx = stem ## max idx = 0;
509
+
510
+ /*****************************************************************************/
511
+
512
+ void noinline
513
+ ev_feed_event (EV_P_ void *w, int revents)
514
+ {
515
+ W w_ = (W)w;
516
+ int pri = ABSPRI (w_);
517
+
518
+ if (expect_false (w_->pending))
519
+ pendings [pri][w_->pending - 1].events |= revents;
520
+ else
521
+ {
522
+ w_->pending = ++pendingcnt [pri];
523
+ array_needsize (ANPENDING, pendings [pri], pendingmax [pri], w_->pending, EMPTY2);
524
+ pendings [pri][w_->pending - 1].w = w_;
525
+ pendings [pri][w_->pending - 1].events = revents;
526
+ }
527
+ }
528
+
529
+ void inline_speed
530
+ queue_events (EV_P_ W *events, int eventcnt, int type)
531
+ {
532
+ int i;
533
+
534
+ for (i = 0; i < eventcnt; ++i)
535
+ ev_feed_event (EV_A_ events [i], type);
536
+ }
537
+
538
+ /*****************************************************************************/
539
+
540
+ void inline_size
541
+ anfds_init (ANFD *base, int count)
542
+ {
543
+ while (count--)
544
+ {
545
+ base->head = 0;
546
+ base->events = EV_NONE;
547
+ base->reify = 0;
548
+
549
+ ++base;
550
+ }
551
+ }
552
+
553
+ void inline_speed
554
+ fd_event (EV_P_ int fd, int revents)
555
+ {
556
+ ANFD *anfd = anfds + fd;
557
+ ev_io *w;
558
+
559
+ for (w = (ev_io *)anfd->head; w; w = (ev_io *)((WL)w)->next)
560
+ {
561
+ int ev = w->events & revents;
562
+
563
+ if (ev)
564
+ ev_feed_event (EV_A_ (W)w, ev);
565
+ }
566
+ }
567
+
568
+ void
569
+ ev_feed_fd_event (EV_P_ int fd, int revents)
570
+ {
571
+ if (fd >= 0 && fd < anfdmax)
572
+ fd_event (EV_A_ fd, revents);
573
+ }
574
+
575
+ void inline_size
576
+ fd_reify (EV_P)
577
+ {
578
+ int i;
579
+
580
+ for (i = 0; i < fdchangecnt; ++i)
581
+ {
582
+ int fd = fdchanges [i];
583
+ ANFD *anfd = anfds + fd;
584
+ ev_io *w;
585
+
586
+ unsigned char events = 0;
587
+
588
+ for (w = (ev_io *)anfd->head; w; w = (ev_io *)((WL)w)->next)
589
+ events |= (unsigned char)w->events;
590
+
591
+ #if EV_SELECT_IS_WINSOCKET
592
+ if (events)
593
+ {
594
+ unsigned long argp;
595
+ anfd->handle = _get_osfhandle (fd);
596
+ assert (("libev only supports socket fds in this configuration", ioctlsocket (anfd->handle, FIONREAD, &argp) == 0));
597
+ }
598
+ #endif
599
+
600
+ {
601
+ unsigned char o_events = anfd->events;
602
+ unsigned char o_reify = anfd->reify;
603
+
604
+ anfd->reify = 0;
605
+ anfd->events = events;
606
+
607
+ if (o_events != events || o_reify & EV_IOFDSET)
608
+ backend_modify (EV_A_ fd, o_events, events);
609
+ }
610
+ }
611
+
612
+ fdchangecnt = 0;
613
+ }
614
+
615
+ void inline_size
616
+ fd_change (EV_P_ int fd, int flags)
617
+ {
618
+ unsigned char reify = anfds [fd].reify;
619
+ anfds [fd].reify |= flags;
620
+
621
+ if (expect_true (!reify))
622
+ {
623
+ ++fdchangecnt;
624
+ array_needsize (int, fdchanges, fdchangemax, fdchangecnt, EMPTY2);
625
+ fdchanges [fdchangecnt - 1] = fd;
626
+ }
627
+ }
628
+
629
+ void inline_speed
630
+ fd_kill (EV_P_ int fd)
631
+ {
632
+ ev_io *w;
633
+
634
+ while ((w = (ev_io *)anfds [fd].head))
635
+ {
636
+ ev_io_stop (EV_A_ w);
637
+ ev_feed_event (EV_A_ (W)w, EV_ERROR | EV_READ | EV_WRITE);
638
+ }
639
+ }
640
+
641
+ int inline_size
642
+ fd_valid (int fd)
643
+ {
644
+ #ifdef _WIN32
645
+ return _get_osfhandle (fd) != -1;
646
+ #else
647
+ return fcntl (fd, F_GETFD) != -1;
648
+ #endif
649
+ }
650
+
651
+ /* called on EBADF to verify fds */
652
+ static void noinline
653
+ fd_ebadf (EV_P)
654
+ {
655
+ int fd;
656
+
657
+ for (fd = 0; fd < anfdmax; ++fd)
658
+ if (anfds [fd].events)
659
+ if (!fd_valid (fd) == -1 && errno == EBADF)
660
+ fd_kill (EV_A_ fd);
661
+ }
662
+
663
+ /* called on ENOMEM in select/poll to kill some fds and retry */
664
+ static void noinline
665
+ fd_enomem (EV_P)
666
+ {
667
+ int fd;
668
+
669
+ for (fd = anfdmax; fd--; )
670
+ if (anfds [fd].events)
671
+ {
672
+ fd_kill (EV_A_ fd);
673
+ return;
674
+ }
675
+ }
676
+
677
+ /* usually called after fork if backend needs to re-arm all fds from scratch */
678
+ static void noinline
679
+ fd_rearm_all (EV_P)
680
+ {
681
+ int fd;
682
+
683
+ for (fd = 0; fd < anfdmax; ++fd)
684
+ if (anfds [fd].events)
685
+ {
686
+ anfds [fd].events = 0;
687
+ fd_change (EV_A_ fd, EV_IOFDSET | 1);
688
+ }
689
+ }
690
+
691
+ /*****************************************************************************/
692
+
693
+ void inline_speed
694
+ upheap (WT *heap, int k)
695
+ {
696
+ WT w = heap [k];
697
+
698
+ while (k)
699
+ {
700
+ int p = (k - 1) >> 1;
701
+
702
+ if (heap [p]->at <= w->at)
703
+ break;
704
+
705
+ heap [k] = heap [p];
706
+ ((W)heap [k])->active = k + 1;
707
+ k = p;
708
+ }
709
+
710
+ heap [k] = w;
711
+ ((W)heap [k])->active = k + 1;
712
+ }
713
+
714
+ void inline_speed
715
+ downheap (WT *heap, int N, int k)
716
+ {
717
+ WT w = heap [k];
718
+
719
+ for (;;)
720
+ {
721
+ int c = (k << 1) + 1;
722
+
723
+ if (c >= N)
724
+ break;
725
+
726
+ c += c + 1 < N && heap [c]->at > heap [c + 1]->at
727
+ ? 1 : 0;
728
+
729
+ if (w->at <= heap [c]->at)
730
+ break;
731
+
732
+ heap [k] = heap [c];
733
+ ((W)heap [k])->active = k + 1;
734
+
735
+ k = c;
736
+ }
737
+
738
+ heap [k] = w;
739
+ ((W)heap [k])->active = k + 1;
740
+ }
741
+
742
+ void inline_size
743
+ adjustheap (WT *heap, int N, int k)
744
+ {
745
+ upheap (heap, k);
746
+ downheap (heap, N, k);
747
+ }
748
+
749
+ /*****************************************************************************/
750
+
751
+ typedef struct
752
+ {
753
+ WL head;
754
+ sig_atomic_t volatile gotsig;
755
+ } ANSIG;
756
+
757
+ static ANSIG *signals;
758
+ static int signalmax;
759
+
760
+ static int sigpipe [2];
761
+ static sig_atomic_t volatile gotsig;
762
+ static ev_io sigev;
763
+
764
+ void inline_size
765
+ signals_init (ANSIG *base, int count)
766
+ {
767
+ while (count--)
768
+ {
769
+ base->head = 0;
770
+ base->gotsig = 0;
771
+
772
+ ++base;
773
+ }
774
+ }
775
+
776
+ static void
777
+ sighandler (int signum)
778
+ {
779
+ #if _WIN32
780
+ signal (signum, sighandler);
781
+ #endif
782
+
783
+ signals [signum - 1].gotsig = 1;
784
+
785
+ if (!gotsig)
786
+ {
787
+ int old_errno = errno;
788
+ gotsig = 1;
789
+ write (sigpipe [1], &signum, 1);
790
+ errno = old_errno;
791
+ }
792
+ }
793
+
794
+ void noinline
795
+ ev_feed_signal_event (EV_P_ int signum)
796
+ {
797
+ WL w;
798
+
799
+ #if EV_MULTIPLICITY
800
+ assert (("feeding signal events is only supported in the default loop", loop == ev_default_loop_ptr));
801
+ #endif
802
+
803
+ --signum;
804
+
805
+ if (signum < 0 || signum >= signalmax)
806
+ return;
807
+
808
+ signals [signum].gotsig = 0;
809
+
810
+ for (w = signals [signum].head; w; w = w->next)
811
+ ev_feed_event (EV_A_ (W)w, EV_SIGNAL);
812
+ }
813
+
814
+ static void
815
+ sigcb (EV_P_ ev_io *iow, int revents)
816
+ {
817
+ int signum;
818
+
819
+ read (sigpipe [0], &revents, 1);
820
+ gotsig = 0;
821
+
822
+ for (signum = signalmax; signum--; )
823
+ if (signals [signum].gotsig)
824
+ ev_feed_signal_event (EV_A_ signum + 1);
825
+ }
826
+
827
+ void inline_speed
828
+ fd_intern (int fd)
829
+ {
830
+ #ifdef _WIN32
831
+ int arg = 1;
832
+ ioctlsocket (_get_osfhandle (fd), FIONBIO, &arg);
833
+ #else
834
+ fcntl (fd, F_SETFD, FD_CLOEXEC);
835
+ fcntl (fd, F_SETFL, O_NONBLOCK);
836
+ #endif
837
+ }
838
+
839
+ static void noinline
840
+ siginit (EV_P)
841
+ {
842
+ fd_intern (sigpipe [0]);
843
+ fd_intern (sigpipe [1]);
844
+
845
+ ev_io_set (&sigev, sigpipe [0], EV_READ);
846
+ ev_io_start (EV_A_ &sigev);
847
+ ev_unref (EV_A); /* child watcher should not keep loop alive */
848
+ }
849
+
850
+ /*****************************************************************************/
851
+
852
+ static WL childs [EV_PID_HASHSIZE];
853
+
854
+ #ifndef _WIN32
855
+
856
+ static ev_signal childev;
857
+
858
+ void inline_speed
859
+ child_reap (EV_P_ ev_signal *sw, int chain, int pid, int status)
860
+ {
861
+ ev_child *w;
862
+
863
+ for (w = (ev_child *)childs [chain & (EV_PID_HASHSIZE - 1)]; w; w = (ev_child *)((WL)w)->next)
864
+ if (w->pid == pid || !w->pid)
865
+ {
866
+ ev_set_priority (w, ev_priority (sw)); /* need to do it *now* */
867
+ w->rpid = pid;
868
+ w->rstatus = status;
869
+ ev_feed_event (EV_A_ (W)w, EV_CHILD);
870
+ }
871
+ }
872
+
873
+ #ifndef WCONTINUED
874
+ # define WCONTINUED 0
875
+ #endif
876
+
877
+ static void
878
+ childcb (EV_P_ ev_signal *sw, int revents)
879
+ {
880
+ int pid, status;
881
+
882
+ /* some systems define WCONTINUED but then fail to support it (linux 2.4) */
883
+ if (0 >= (pid = waitpid (-1, &status, WNOHANG | WUNTRACED | WCONTINUED)))
884
+ if (!WCONTINUED
885
+ || errno != EINVAL
886
+ || 0 >= (pid = waitpid (-1, &status, WNOHANG | WUNTRACED)))
887
+ return;
888
+
889
+ /* make sure we are called again until all childs have been reaped */
890
+ /* we need to do it this way so that the callback gets called before we continue */
891
+ ev_feed_event (EV_A_ (W)sw, EV_SIGNAL);
892
+
893
+ child_reap (EV_A_ sw, pid, pid, status);
894
+ if (EV_PID_HASHSIZE > 1)
895
+ child_reap (EV_A_ sw, 0, pid, status); /* this might trigger a watcher twice, but feed_event catches that */
896
+ }
897
+
898
+ #endif
899
+
900
+ /*****************************************************************************/
901
+
902
+ #if EV_USE_PORT
903
+ # include "ev_port.c"
904
+ #endif
905
+ #if EV_USE_KQUEUE
906
+ # include "ev_kqueue.c"
907
+ #endif
908
+ #if EV_USE_EPOLL
909
+ # include "ev_epoll.c"
910
+ #endif
911
+ #if EV_USE_POLL
912
+ # include "ev_poll.c"
913
+ #endif
914
+ #if EV_USE_SELECT
915
+ # include "ev_select.c"
916
+ #endif
917
+
918
+ int
919
+ ev_version_major (void)
920
+ {
921
+ return EV_VERSION_MAJOR;
922
+ }
923
+
924
+ int
925
+ ev_version_minor (void)
926
+ {
927
+ return EV_VERSION_MINOR;
928
+ }
929
+
930
+ /* return true if we are running with elevated privileges and should ignore env variables */
931
+ int inline_size
932
+ enable_secure (void)
933
+ {
934
+ #ifdef _WIN32
935
+ return 0;
936
+ #else
937
+ return getuid () != geteuid ()
938
+ || getgid () != getegid ();
939
+ #endif
940
+ }
941
+
942
+ unsigned int
943
+ ev_supported_backends (void)
944
+ {
945
+ unsigned int flags = 0;
946
+
947
+ if (EV_USE_PORT ) flags |= EVBACKEND_PORT;
948
+ if (EV_USE_KQUEUE) flags |= EVBACKEND_KQUEUE;
949
+ if (EV_USE_EPOLL ) flags |= EVBACKEND_EPOLL;
950
+ if (EV_USE_POLL ) flags |= EVBACKEND_POLL;
951
+ if (EV_USE_SELECT) flags |= EVBACKEND_SELECT;
952
+
953
+ return flags;
954
+ }
955
+
956
+ unsigned int
957
+ ev_recommended_backends (void)
958
+ {
959
+ unsigned int flags = ev_supported_backends ();
960
+
961
+ #ifndef __NetBSD__
962
+ /* kqueue is borked on everything but netbsd apparently */
963
+ /* it usually doesn't work correctly on anything but sockets and pipes */
964
+ flags &= ~EVBACKEND_KQUEUE;
965
+ #endif
966
+ #ifdef __APPLE__
967
+ // flags &= ~EVBACKEND_KQUEUE; for documentation
968
+ flags &= ~EVBACKEND_POLL;
969
+ #endif
970
+
971
+ return flags;
972
+ }
973
+
974
+ unsigned int
975
+ ev_embeddable_backends (void)
976
+ {
977
+ int flags = EVBACKEND_EPOLL | EVBACKEND_KQUEUE | EVBACKEND_PORT;
978
+
979
+ /* epoll embeddability broken on all linux versions up to at least 2.6.23 */
980
+ /* please fix it and tell me how to detect the fix */
981
+ flags &= ~EVBACKEND_EPOLL;
982
+
983
+ return flags;
984
+ }
985
+
986
+ unsigned int
987
+ ev_backend (EV_P)
988
+ {
989
+ return backend;
990
+ }
991
+
992
+ unsigned int
993
+ ev_loop_count (EV_P)
994
+ {
995
+ return loop_count;
996
+ }
997
+
998
+ void
999
+ ev_set_io_collect_interval (EV_P_ ev_tstamp interval)
1000
+ {
1001
+ io_blocktime = interval;
1002
+ }
1003
+
1004
+ void
1005
+ ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval)
1006
+ {
1007
+ timeout_blocktime = interval;
1008
+ }
1009
+
1010
+ static void noinline
1011
+ loop_init (EV_P_ unsigned int flags)
1012
+ {
1013
+ if (!backend)
1014
+ {
1015
+ #if EV_USE_MONOTONIC
1016
+ {
1017
+ struct timespec ts;
1018
+ if (!clock_gettime (CLOCK_MONOTONIC, &ts))
1019
+ have_monotonic = 1;
1020
+ }
1021
+ #endif
1022
+
1023
+ ev_rt_now = ev_time ();
1024
+ mn_now = get_clock ();
1025
+ now_floor = mn_now;
1026
+ rtmn_diff = ev_rt_now - mn_now;
1027
+
1028
+ io_blocktime = 0.;
1029
+ timeout_blocktime = 0.;
1030
+
1031
+ /* pid check not overridable via env */
1032
+ #ifndef _WIN32
1033
+ if (flags & EVFLAG_FORKCHECK)
1034
+ curpid = getpid ();
1035
+ #endif
1036
+
1037
+ if (!(flags & EVFLAG_NOENV)
1038
+ && !enable_secure ()
1039
+ && getenv ("LIBEV_FLAGS"))
1040
+ flags = atoi (getenv ("LIBEV_FLAGS"));
1041
+
1042
+ if (!(flags & 0x0000ffffUL))
1043
+ flags |= ev_recommended_backends ();
1044
+
1045
+ backend = 0;
1046
+ backend_fd = -1;
1047
+ #if EV_USE_INOTIFY
1048
+ fs_fd = -2;
1049
+ #endif
1050
+
1051
+ #if EV_USE_PORT
1052
+ if (!backend && (flags & EVBACKEND_PORT )) backend = port_init (EV_A_ flags);
1053
+ #endif
1054
+ #if EV_USE_KQUEUE
1055
+ if (!backend && (flags & EVBACKEND_KQUEUE)) backend = kqueue_init (EV_A_ flags);
1056
+ #endif
1057
+ #if EV_USE_EPOLL
1058
+ if (!backend && (flags & EVBACKEND_EPOLL )) backend = epoll_init (EV_A_ flags);
1059
+ #endif
1060
+ #if EV_USE_POLL
1061
+ if (!backend && (flags & EVBACKEND_POLL )) backend = poll_init (EV_A_ flags);
1062
+ #endif
1063
+ #if EV_USE_SELECT
1064
+ if (!backend && (flags & EVBACKEND_SELECT)) backend = select_init (EV_A_ flags);
1065
+ #endif
1066
+
1067
+ ev_init (&sigev, sigcb);
1068
+ ev_set_priority (&sigev, EV_MAXPRI);
1069
+ }
1070
+ }
1071
+
1072
+ static void noinline
1073
+ loop_destroy (EV_P)
1074
+ {
1075
+ int i;
1076
+
1077
+ #if EV_USE_INOTIFY
1078
+ if (fs_fd >= 0)
1079
+ close (fs_fd);
1080
+ #endif
1081
+
1082
+ if (backend_fd >= 0)
1083
+ close (backend_fd);
1084
+
1085
+ #if EV_USE_PORT
1086
+ if (backend == EVBACKEND_PORT ) port_destroy (EV_A);
1087
+ #endif
1088
+ #if EV_USE_KQUEUE
1089
+ if (backend == EVBACKEND_KQUEUE) kqueue_destroy (EV_A);
1090
+ #endif
1091
+ #if EV_USE_EPOLL
1092
+ if (backend == EVBACKEND_EPOLL ) epoll_destroy (EV_A);
1093
+ #endif
1094
+ #if EV_USE_POLL
1095
+ if (backend == EVBACKEND_POLL ) poll_destroy (EV_A);
1096
+ #endif
1097
+ #if EV_USE_SELECT
1098
+ if (backend == EVBACKEND_SELECT) select_destroy (EV_A);
1099
+ #endif
1100
+
1101
+ for (i = NUMPRI; i--; )
1102
+ {
1103
+ array_free (pending, [i]);
1104
+ #if EV_IDLE_ENABLE
1105
+ array_free (idle, [i]);
1106
+ #endif
1107
+ }
1108
+
1109
+ ev_free (anfds); anfdmax = 0;
1110
+
1111
+ /* have to use the microsoft-never-gets-it-right macro */
1112
+ array_free (fdchange, EMPTY);
1113
+ array_free (timer, EMPTY);
1114
+ #if EV_PERIODIC_ENABLE
1115
+ array_free (periodic, EMPTY);
1116
+ #endif
1117
+ #if EV_FORK_ENABLE
1118
+ array_free (fork, EMPTY);
1119
+ #endif
1120
+ array_free (prepare, EMPTY);
1121
+ array_free (check, EMPTY);
1122
+
1123
+ backend = 0;
1124
+ }
1125
+
1126
+ void inline_size infy_fork (EV_P);
1127
+
1128
+ void inline_size
1129
+ loop_fork (EV_P)
1130
+ {
1131
+ #if EV_USE_PORT
1132
+ if (backend == EVBACKEND_PORT ) port_fork (EV_A);
1133
+ #endif
1134
+ #if EV_USE_KQUEUE
1135
+ if (backend == EVBACKEND_KQUEUE) kqueue_fork (EV_A);
1136
+ #endif
1137
+ #if EV_USE_EPOLL
1138
+ if (backend == EVBACKEND_EPOLL ) epoll_fork (EV_A);
1139
+ #endif
1140
+ #if EV_USE_INOTIFY
1141
+ infy_fork (EV_A);
1142
+ #endif
1143
+
1144
+ if (ev_is_active (&sigev))
1145
+ {
1146
+ /* default loop */
1147
+
1148
+ ev_ref (EV_A);
1149
+ ev_io_stop (EV_A_ &sigev);
1150
+ close (sigpipe [0]);
1151
+ close (sigpipe [1]);
1152
+
1153
+ while (pipe (sigpipe))
1154
+ syserr ("(libev) error creating pipe");
1155
+
1156
+ siginit (EV_A);
1157
+ }
1158
+
1159
+ postfork = 0;
1160
+ }
1161
+
1162
+ #if EV_MULTIPLICITY
1163
+ struct ev_loop *
1164
+ ev_loop_new (unsigned int flags)
1165
+ {
1166
+ struct ev_loop *loop = (struct ev_loop *)ev_malloc (sizeof (struct ev_loop));
1167
+
1168
+ memset (loop, 0, sizeof (struct ev_loop));
1169
+
1170
+ loop_init (EV_A_ flags);
1171
+
1172
+ if (ev_backend (EV_A))
1173
+ return loop;
1174
+
1175
+ return 0;
1176
+ }
1177
+
1178
+ void
1179
+ ev_loop_destroy (EV_P)
1180
+ {
1181
+ loop_destroy (EV_A);
1182
+ ev_free (loop);
1183
+ }
1184
+
1185
+ void
1186
+ ev_loop_fork (EV_P)
1187
+ {
1188
+ postfork = 1;
1189
+ }
1190
+
1191
+ #endif
1192
+
1193
+ #if EV_MULTIPLICITY
1194
+ struct ev_loop *
1195
+ ev_default_loop_init (unsigned int flags)
1196
+ #else
1197
+ int
1198
+ ev_default_loop (unsigned int flags)
1199
+ #endif
1200
+ {
1201
+ if (sigpipe [0] == sigpipe [1])
1202
+ if (pipe (sigpipe))
1203
+ return 0;
1204
+
1205
+ if (!ev_default_loop_ptr)
1206
+ {
1207
+ #if EV_MULTIPLICITY
1208
+ struct ev_loop *loop = ev_default_loop_ptr = &default_loop_struct;
1209
+ #else
1210
+ ev_default_loop_ptr = 1;
1211
+ #endif
1212
+
1213
+ loop_init (EV_A_ flags);
1214
+
1215
+ if (ev_backend (EV_A))
1216
+ {
1217
+ siginit (EV_A);
1218
+
1219
+ #ifndef _WIN32
1220
+ ev_signal_init (&childev, childcb, SIGCHLD);
1221
+ ev_set_priority (&childev, EV_MAXPRI);
1222
+ ev_signal_start (EV_A_ &childev);
1223
+ ev_unref (EV_A); /* child watcher should not keep loop alive */
1224
+ #endif
1225
+ }
1226
+ else
1227
+ ev_default_loop_ptr = 0;
1228
+ }
1229
+
1230
+ return ev_default_loop_ptr;
1231
+ }
1232
+
1233
+ void
1234
+ ev_default_destroy (void)
1235
+ {
1236
+ #if EV_MULTIPLICITY
1237
+ struct ev_loop *loop = ev_default_loop_ptr;
1238
+ #endif
1239
+
1240
+ #ifndef _WIN32
1241
+ ev_ref (EV_A); /* child watcher */
1242
+ ev_signal_stop (EV_A_ &childev);
1243
+ #endif
1244
+
1245
+ ev_ref (EV_A); /* signal watcher */
1246
+ ev_io_stop (EV_A_ &sigev);
1247
+
1248
+ close (sigpipe [0]); sigpipe [0] = 0;
1249
+ close (sigpipe [1]); sigpipe [1] = 0;
1250
+
1251
+ loop_destroy (EV_A);
1252
+ }
1253
+
1254
+ void
1255
+ ev_default_fork (void)
1256
+ {
1257
+ #if EV_MULTIPLICITY
1258
+ struct ev_loop *loop = ev_default_loop_ptr;
1259
+ #endif
1260
+
1261
+ if (backend)
1262
+ postfork = 1;
1263
+ }
1264
+
1265
+ /*****************************************************************************/
1266
+
1267
+ void
1268
+ ev_invoke (EV_P_ void *w, int revents)
1269
+ {
1270
+ EV_CB_INVOKE ((W)w, revents);
1271
+ }
1272
+
1273
+ void inline_speed
1274
+ call_pending (EV_P)
1275
+ {
1276
+ int pri;
1277
+
1278
+ for (pri = NUMPRI; pri--; )
1279
+ while (pendingcnt [pri])
1280
+ {
1281
+ ANPENDING *p = pendings [pri] + --pendingcnt [pri];
1282
+
1283
+ if (expect_true (p->w))
1284
+ {
1285
+ /*assert (("non-pending watcher on pending list", p->w->pending));*/
1286
+
1287
+ p->w->pending = 0;
1288
+ EV_CB_INVOKE (p->w, p->events);
1289
+ }
1290
+ }
1291
+ }
1292
+
1293
+ void inline_size
1294
+ timers_reify (EV_P)
1295
+ {
1296
+ while (timercnt && ((WT)timers [0])->at <= mn_now)
1297
+ {
1298
+ ev_timer *w = (ev_timer *)timers [0];
1299
+
1300
+ /*assert (("inactive timer on timer heap detected", ev_is_active (w)));*/
1301
+
1302
+ /* first reschedule or stop timer */
1303
+ if (w->repeat)
1304
+ {
1305
+ assert (("negative ev_timer repeat value found while processing timers", w->repeat > 0.));
1306
+
1307
+ ((WT)w)->at += w->repeat;
1308
+ if (((WT)w)->at < mn_now)
1309
+ ((WT)w)->at = mn_now;
1310
+
1311
+ downheap (timers, timercnt, 0);
1312
+ }
1313
+ else
1314
+ ev_timer_stop (EV_A_ w); /* nonrepeating: stop timer */
1315
+
1316
+ ev_feed_event (EV_A_ (W)w, EV_TIMEOUT);
1317
+ }
1318
+ }
1319
+
1320
+ #if EV_PERIODIC_ENABLE
1321
+ void inline_size
1322
+ periodics_reify (EV_P)
1323
+ {
1324
+ while (periodiccnt && ((WT)periodics [0])->at <= ev_rt_now)
1325
+ {
1326
+ ev_periodic *w = (ev_periodic *)periodics [0];
1327
+
1328
+ /*assert (("inactive timer on periodic heap detected", ev_is_active (w)));*/
1329
+
1330
+ /* first reschedule or stop timer */
1331
+ if (w->reschedule_cb)
1332
+ {
1333
+ ((WT)w)->at = w->reschedule_cb (w, ev_rt_now + TIME_EPSILON);
1334
+ assert (("ev_periodic reschedule callback returned time in the past", ((WT)w)->at > ev_rt_now));
1335
+ downheap (periodics, periodiccnt, 0);
1336
+ }
1337
+ else if (w->interval)
1338
+ {
1339
+ ((WT)w)->at = w->offset + ceil ((ev_rt_now - w->offset) / w->interval) * w->interval;
1340
+ if (((WT)w)->at - ev_rt_now <= TIME_EPSILON) ((WT)w)->at += w->interval;
1341
+ assert (("ev_periodic timeout in the past detected while processing timers, negative interval?", ((WT)w)->at > ev_rt_now));
1342
+ downheap (periodics, periodiccnt, 0);
1343
+ }
1344
+ else
1345
+ ev_periodic_stop (EV_A_ w); /* nonrepeating: stop timer */
1346
+
1347
+ ev_feed_event (EV_A_ (W)w, EV_PERIODIC);
1348
+ }
1349
+ }
1350
+
1351
+ static void noinline
1352
+ periodics_reschedule (EV_P)
1353
+ {
1354
+ int i;
1355
+
1356
+ /* adjust periodics after time jump */
1357
+ for (i = 0; i < periodiccnt; ++i)
1358
+ {
1359
+ ev_periodic *w = (ev_periodic *)periodics [i];
1360
+
1361
+ if (w->reschedule_cb)
1362
+ ((WT)w)->at = w->reschedule_cb (w, ev_rt_now);
1363
+ else if (w->interval)
1364
+ ((WT)w)->at = w->offset + ceil ((ev_rt_now - w->offset) / w->interval) * w->interval;
1365
+ }
1366
+
1367
+ /* now rebuild the heap */
1368
+ for (i = periodiccnt >> 1; i--; )
1369
+ downheap (periodics, periodiccnt, i);
1370
+ }
1371
+ #endif
1372
+
1373
+ #if EV_IDLE_ENABLE
1374
+ void inline_size
1375
+ idle_reify (EV_P)
1376
+ {
1377
+ if (expect_false (idleall))
1378
+ {
1379
+ int pri;
1380
+
1381
+ for (pri = NUMPRI; pri--; )
1382
+ {
1383
+ if (pendingcnt [pri])
1384
+ break;
1385
+
1386
+ if (idlecnt [pri])
1387
+ {
1388
+ queue_events (EV_A_ (W *)idles [pri], idlecnt [pri], EV_IDLE);
1389
+ break;
1390
+ }
1391
+ }
1392
+ }
1393
+ }
1394
+ #endif
1395
+
1396
+ void inline_speed
1397
+ time_update (EV_P_ ev_tstamp max_block)
1398
+ {
1399
+ int i;
1400
+
1401
+ #if EV_USE_MONOTONIC
1402
+ if (expect_true (have_monotonic))
1403
+ {
1404
+ ev_tstamp odiff = rtmn_diff;
1405
+
1406
+ mn_now = get_clock ();
1407
+
1408
+ /* only fetch the realtime clock every 0.5*MIN_TIMEJUMP seconds */
1409
+ /* interpolate in the meantime */
1410
+ if (expect_true (mn_now - now_floor < MIN_TIMEJUMP * .5))
1411
+ {
1412
+ ev_rt_now = rtmn_diff + mn_now;
1413
+ return;
1414
+ }
1415
+
1416
+ now_floor = mn_now;
1417
+ ev_rt_now = ev_time ();
1418
+
1419
+ /* loop a few times, before making important decisions.
1420
+ * on the choice of "4": one iteration isn't enough,
1421
+ * in case we get preempted during the calls to
1422
+ * ev_time and get_clock. a second call is almost guaranteed
1423
+ * to succeed in that case, though. and looping a few more times
1424
+ * doesn't hurt either as we only do this on time-jumps or
1425
+ * in the unlikely event of having been preempted here.
1426
+ */
1427
+ for (i = 4; --i; )
1428
+ {
1429
+ rtmn_diff = ev_rt_now - mn_now;
1430
+
1431
+ if (fabs (odiff - rtmn_diff) < MIN_TIMEJUMP)
1432
+ return; /* all is well */
1433
+
1434
+ ev_rt_now = ev_time ();
1435
+ mn_now = get_clock ();
1436
+ now_floor = mn_now;
1437
+ }
1438
+
1439
+ # if EV_PERIODIC_ENABLE
1440
+ periodics_reschedule (EV_A);
1441
+ # endif
1442
+ /* no timer adjustment, as the monotonic clock doesn't jump */
1443
+ /* timers_reschedule (EV_A_ rtmn_diff - odiff) */
1444
+ }
1445
+ else
1446
+ #endif
1447
+ {
1448
+ ev_rt_now = ev_time ();
1449
+
1450
+ if (expect_false (mn_now > ev_rt_now || ev_rt_now > mn_now + max_block + MIN_TIMEJUMP))
1451
+ {
1452
+ #if EV_PERIODIC_ENABLE
1453
+ periodics_reschedule (EV_A);
1454
+ #endif
1455
+ /* adjust timers. this is easy, as the offset is the same for all of them */
1456
+ for (i = 0; i < timercnt; ++i)
1457
+ ((WT)timers [i])->at += ev_rt_now - mn_now;
1458
+ }
1459
+
1460
+ mn_now = ev_rt_now;
1461
+ }
1462
+ }
1463
+
1464
+ void
1465
+ ev_ref (EV_P)
1466
+ {
1467
+ ++activecnt;
1468
+ }
1469
+
1470
+ void
1471
+ ev_unref (EV_P)
1472
+ {
1473
+ --activecnt;
1474
+ }
1475
+
1476
+ static int loop_done;
1477
+
1478
+ void
1479
+ ev_loop (EV_P_ int flags)
1480
+ {
1481
+ loop_done = flags & (EVLOOP_ONESHOT | EVLOOP_NONBLOCK)
1482
+ ? EVUNLOOP_ONE
1483
+ : EVUNLOOP_CANCEL;
1484
+
1485
+ call_pending (EV_A); /* in case we recurse, ensure ordering stays nice and clean */
1486
+
1487
+ do
1488
+ {
1489
+ #ifndef _WIN32
1490
+ if (expect_false (curpid)) /* penalise the forking check even more */
1491
+ if (expect_false (getpid () != curpid))
1492
+ {
1493
+ curpid = getpid ();
1494
+ postfork = 1;
1495
+ }
1496
+ #endif
1497
+
1498
+ #if EV_FORK_ENABLE
1499
+ /* we might have forked, so queue fork handlers */
1500
+ if (expect_false (postfork))
1501
+ if (forkcnt)
1502
+ {
1503
+ queue_events (EV_A_ (W *)forks, forkcnt, EV_FORK);
1504
+ call_pending (EV_A);
1505
+ }
1506
+ #endif
1507
+
1508
+ /* queue prepare watchers (and execute them) */
1509
+ if (expect_false (preparecnt))
1510
+ {
1511
+ queue_events (EV_A_ (W *)prepares, preparecnt, EV_PREPARE);
1512
+ call_pending (EV_A);
1513
+ }
1514
+
1515
+ if (expect_false (!activecnt))
1516
+ break;
1517
+
1518
+ /* we might have forked, so reify kernel state if necessary */
1519
+ if (expect_false (postfork))
1520
+ loop_fork (EV_A);
1521
+
1522
+ /* update fd-related kernel structures */
1523
+ fd_reify (EV_A);
1524
+
1525
+ /* calculate blocking time */
1526
+ {
1527
+ ev_tstamp waittime = 0.;
1528
+ ev_tstamp sleeptime = 0.;
1529
+
1530
+ if (expect_true (!(flags & EVLOOP_NONBLOCK || idleall || !activecnt)))
1531
+ {
1532
+ /* update time to cancel out callback processing overhead */
1533
+ time_update (EV_A_ 1e100);
1534
+
1535
+ waittime = MAX_BLOCKTIME;
1536
+
1537
+ if (timercnt)
1538
+ {
1539
+ ev_tstamp to = ((WT)timers [0])->at - mn_now + backend_fudge;
1540
+ if (waittime > to) waittime = to;
1541
+ }
1542
+
1543
+ #if EV_PERIODIC_ENABLE
1544
+ if (periodiccnt)
1545
+ {
1546
+ ev_tstamp to = ((WT)periodics [0])->at - ev_rt_now + backend_fudge;
1547
+ if (waittime > to) waittime = to;
1548
+ }
1549
+ #endif
1550
+
1551
+ if (expect_false (waittime < timeout_blocktime))
1552
+ waittime = timeout_blocktime;
1553
+
1554
+ sleeptime = waittime - backend_fudge;
1555
+
1556
+ if (expect_true (sleeptime > io_blocktime))
1557
+ sleeptime = io_blocktime;
1558
+
1559
+ if (sleeptime)
1560
+ {
1561
+ ev_sleep (sleeptime);
1562
+ waittime -= sleeptime;
1563
+ }
1564
+ }
1565
+
1566
+ ++loop_count;
1567
+ backend_poll (EV_A_ waittime);
1568
+
1569
+ /* update ev_rt_now, do magic */
1570
+ time_update (EV_A_ waittime + sleeptime);
1571
+ }
1572
+
1573
+ /* queue pending timers and reschedule them */
1574
+ timers_reify (EV_A); /* relative timers called last */
1575
+ #if EV_PERIODIC_ENABLE
1576
+ periodics_reify (EV_A); /* absolute timers called first */
1577
+ #endif
1578
+
1579
+ #if EV_IDLE_ENABLE
1580
+ /* queue idle watchers unless other events are pending */
1581
+ idle_reify (EV_A);
1582
+ #endif
1583
+
1584
+ /* queue check watchers, to be executed first */
1585
+ if (expect_false (checkcnt))
1586
+ queue_events (EV_A_ (W *)checks, checkcnt, EV_CHECK);
1587
+
1588
+ call_pending (EV_A);
1589
+
1590
+ }
1591
+ while (expect_true (activecnt && !loop_done));
1592
+
1593
+ if (loop_done == EVUNLOOP_ONE)
1594
+ loop_done = EVUNLOOP_CANCEL;
1595
+ }
1596
+
1597
+ void
1598
+ ev_unloop (EV_P_ int how)
1599
+ {
1600
+ loop_done = how;
1601
+ }
1602
+
1603
+ /*****************************************************************************/
1604
+
1605
+ void inline_size
1606
+ wlist_add (WL *head, WL elem)
1607
+ {
1608
+ elem->next = *head;
1609
+ *head = elem;
1610
+ }
1611
+
1612
+ void inline_size
1613
+ wlist_del (WL *head, WL elem)
1614
+ {
1615
+ while (*head)
1616
+ {
1617
+ if (*head == elem)
1618
+ {
1619
+ *head = elem->next;
1620
+ return;
1621
+ }
1622
+
1623
+ head = &(*head)->next;
1624
+ }
1625
+ }
1626
+
1627
+ void inline_speed
1628
+ clear_pending (EV_P_ W w)
1629
+ {
1630
+ if (w->pending)
1631
+ {
1632
+ pendings [ABSPRI (w)][w->pending - 1].w = 0;
1633
+ w->pending = 0;
1634
+ }
1635
+ }
1636
+
1637
+ int
1638
+ ev_clear_pending (EV_P_ void *w)
1639
+ {
1640
+ W w_ = (W)w;
1641
+ int pending = w_->pending;
1642
+
1643
+ if (expect_true (pending))
1644
+ {
1645
+ ANPENDING *p = pendings [ABSPRI (w_)] + pending - 1;
1646
+ w_->pending = 0;
1647
+ p->w = 0;
1648
+ return p->events;
1649
+ }
1650
+ else
1651
+ return 0;
1652
+ }
1653
+
1654
+ void inline_size
1655
+ pri_adjust (EV_P_ W w)
1656
+ {
1657
+ int pri = w->priority;
1658
+ pri = pri < EV_MINPRI ? EV_MINPRI : pri;
1659
+ pri = pri > EV_MAXPRI ? EV_MAXPRI : pri;
1660
+ w->priority = pri;
1661
+ }
1662
+
1663
+ void inline_speed
1664
+ ev_start (EV_P_ W w, int active)
1665
+ {
1666
+ pri_adjust (EV_A_ w);
1667
+ w->active = active;
1668
+ ev_ref (EV_A);
1669
+ }
1670
+
1671
+ void inline_size
1672
+ ev_stop (EV_P_ W w)
1673
+ {
1674
+ ev_unref (EV_A);
1675
+ w->active = 0;
1676
+ }
1677
+
1678
+ /*****************************************************************************/
1679
+
1680
+ void noinline
1681
+ ev_io_start (EV_P_ ev_io *w)
1682
+ {
1683
+ int fd = w->fd;
1684
+
1685
+ if (expect_false (ev_is_active (w)))
1686
+ return;
1687
+
1688
+ assert (("ev_io_start called with negative fd", fd >= 0));
1689
+
1690
+ ev_start (EV_A_ (W)w, 1);
1691
+ array_needsize (ANFD, anfds, anfdmax, fd + 1, anfds_init);
1692
+ wlist_add (&anfds[fd].head, (WL)w);
1693
+
1694
+ fd_change (EV_A_ fd, w->events & EV_IOFDSET | 1);
1695
+ w->events &= ~EV_IOFDSET;
1696
+ }
1697
+
1698
+ void noinline
1699
+ ev_io_stop (EV_P_ ev_io *w)
1700
+ {
1701
+ clear_pending (EV_A_ (W)w);
1702
+ if (expect_false (!ev_is_active (w)))
1703
+ return;
1704
+
1705
+ assert (("ev_io_start called with illegal fd (must stay constant after start!)", w->fd >= 0 && w->fd < anfdmax));
1706
+
1707
+ wlist_del (&anfds[w->fd].head, (WL)w);
1708
+ ev_stop (EV_A_ (W)w);
1709
+
1710
+ fd_change (EV_A_ w->fd, 1);
1711
+ }
1712
+
1713
+ void noinline
1714
+ ev_timer_start (EV_P_ ev_timer *w)
1715
+ {
1716
+ if (expect_false (ev_is_active (w)))
1717
+ return;
1718
+
1719
+ ((WT)w)->at += mn_now;
1720
+
1721
+ assert (("ev_timer_start called with negative timer repeat value", w->repeat >= 0.));
1722
+
1723
+ ev_start (EV_A_ (W)w, ++timercnt);
1724
+ array_needsize (WT, timers, timermax, timercnt, EMPTY2);
1725
+ timers [timercnt - 1] = (WT)w;
1726
+ upheap (timers, timercnt - 1);
1727
+
1728
+ /*assert (("internal timer heap corruption", timers [((W)w)->active - 1] == w));*/
1729
+ }
1730
+
1731
+ void noinline
1732
+ ev_timer_stop (EV_P_ ev_timer *w)
1733
+ {
1734
+ clear_pending (EV_A_ (W)w);
1735
+ if (expect_false (!ev_is_active (w)))
1736
+ return;
1737
+
1738
+ assert (("internal timer heap corruption", timers [((W)w)->active - 1] == (WT)w));
1739
+
1740
+ {
1741
+ int active = ((W)w)->active;
1742
+
1743
+ if (expect_true (--active < --timercnt))
1744
+ {
1745
+ timers [active] = timers [timercnt];
1746
+ adjustheap (timers, timercnt, active);
1747
+ }
1748
+ }
1749
+
1750
+ ((WT)w)->at -= mn_now;
1751
+
1752
+ ev_stop (EV_A_ (W)w);
1753
+ }
1754
+
1755
+ void noinline
1756
+ ev_timer_again (EV_P_ ev_timer *w)
1757
+ {
1758
+ if (ev_is_active (w))
1759
+ {
1760
+ if (w->repeat)
1761
+ {
1762
+ ((WT)w)->at = mn_now + w->repeat;
1763
+ adjustheap (timers, timercnt, ((W)w)->active - 1);
1764
+ }
1765
+ else
1766
+ ev_timer_stop (EV_A_ w);
1767
+ }
1768
+ else if (w->repeat)
1769
+ {
1770
+ w->at = w->repeat;
1771
+ ev_timer_start (EV_A_ w);
1772
+ }
1773
+ }
1774
+
1775
+ #if EV_PERIODIC_ENABLE
1776
+ void noinline
1777
+ ev_periodic_start (EV_P_ ev_periodic *w)
1778
+ {
1779
+ if (expect_false (ev_is_active (w)))
1780
+ return;
1781
+
1782
+ if (w->reschedule_cb)
1783
+ ((WT)w)->at = w->reschedule_cb (w, ev_rt_now);
1784
+ else if (w->interval)
1785
+ {
1786
+ assert (("ev_periodic_start called with negative interval value", w->interval >= 0.));
1787
+ /* this formula differs from the one in periodic_reify because we do not always round up */
1788
+ ((WT)w)->at = w->offset + ceil ((ev_rt_now - w->offset) / w->interval) * w->interval;
1789
+ }
1790
+ else
1791
+ ((WT)w)->at = w->offset;
1792
+
1793
+ ev_start (EV_A_ (W)w, ++periodiccnt);
1794
+ array_needsize (WT, periodics, periodicmax, periodiccnt, EMPTY2);
1795
+ periodics [periodiccnt - 1] = (WT)w;
1796
+ upheap (periodics, periodiccnt - 1);
1797
+
1798
+ /*assert (("internal periodic heap corruption", periodics [((W)w)->active - 1] == w));*/
1799
+ }
1800
+
1801
+ void noinline
1802
+ ev_periodic_stop (EV_P_ ev_periodic *w)
1803
+ {
1804
+ clear_pending (EV_A_ (W)w);
1805
+ if (expect_false (!ev_is_active (w)))
1806
+ return;
1807
+
1808
+ assert (("internal periodic heap corruption", periodics [((W)w)->active - 1] == (WT)w));
1809
+
1810
+ {
1811
+ int active = ((W)w)->active;
1812
+
1813
+ if (expect_true (--active < --periodiccnt))
1814
+ {
1815
+ periodics [active] = periodics [periodiccnt];
1816
+ adjustheap (periodics, periodiccnt, active);
1817
+ }
1818
+ }
1819
+
1820
+ ev_stop (EV_A_ (W)w);
1821
+ }
1822
+
1823
+ void noinline
1824
+ ev_periodic_again (EV_P_ ev_periodic *w)
1825
+ {
1826
+ /* TODO: use adjustheap and recalculation */
1827
+ ev_periodic_stop (EV_A_ w);
1828
+ ev_periodic_start (EV_A_ w);
1829
+ }
1830
+ #endif
1831
+
1832
+ #ifndef SA_RESTART
1833
+ # define SA_RESTART 0
1834
+ #endif
1835
+
1836
+ void noinline
1837
+ ev_signal_start (EV_P_ ev_signal *w)
1838
+ {
1839
+ #if EV_MULTIPLICITY
1840
+ assert (("signal watchers are only supported in the default loop", loop == ev_default_loop_ptr));
1841
+ #endif
1842
+ if (expect_false (ev_is_active (w)))
1843
+ return;
1844
+
1845
+ assert (("ev_signal_start called with illegal signal number", w->signum > 0));
1846
+
1847
+ {
1848
+ #ifndef _WIN32
1849
+ sigset_t full, prev;
1850
+ sigfillset (&full);
1851
+ sigprocmask (SIG_SETMASK, &full, &prev);
1852
+ #endif
1853
+
1854
+ array_needsize (ANSIG, signals, signalmax, w->signum, signals_init);
1855
+
1856
+ #ifndef _WIN32
1857
+ sigprocmask (SIG_SETMASK, &prev, 0);
1858
+ #endif
1859
+ }
1860
+
1861
+ ev_start (EV_A_ (W)w, 1);
1862
+ wlist_add (&signals [w->signum - 1].head, (WL)w);
1863
+
1864
+ if (!((WL)w)->next)
1865
+ {
1866
+ #if _WIN32
1867
+ signal (w->signum, sighandler);
1868
+ #else
1869
+ struct sigaction sa;
1870
+ sa.sa_handler = sighandler;
1871
+ sigfillset (&sa.sa_mask);
1872
+ sa.sa_flags = SA_RESTART; /* if restarting works we save one iteration */
1873
+ sigaction (w->signum, &sa, 0);
1874
+ #endif
1875
+ }
1876
+ }
1877
+
1878
+ void noinline
1879
+ ev_signal_stop (EV_P_ ev_signal *w)
1880
+ {
1881
+ clear_pending (EV_A_ (W)w);
1882
+ if (expect_false (!ev_is_active (w)))
1883
+ return;
1884
+
1885
+ wlist_del (&signals [w->signum - 1].head, (WL)w);
1886
+ ev_stop (EV_A_ (W)w);
1887
+
1888
+ if (!signals [w->signum - 1].head)
1889
+ signal (w->signum, SIG_DFL);
1890
+ }
1891
+
1892
+ void
1893
+ ev_child_start (EV_P_ ev_child *w)
1894
+ {
1895
+ #if EV_MULTIPLICITY
1896
+ assert (("child watchers are only supported in the default loop", loop == ev_default_loop_ptr));
1897
+ #endif
1898
+ if (expect_false (ev_is_active (w)))
1899
+ return;
1900
+
1901
+ ev_start (EV_A_ (W)w, 1);
1902
+ wlist_add (&childs [w->pid & (EV_PID_HASHSIZE - 1)], (WL)w);
1903
+ }
1904
+
1905
+ void
1906
+ ev_child_stop (EV_P_ ev_child *w)
1907
+ {
1908
+ clear_pending (EV_A_ (W)w);
1909
+ if (expect_false (!ev_is_active (w)))
1910
+ return;
1911
+
1912
+ wlist_del (&childs [w->pid & (EV_PID_HASHSIZE - 1)], (WL)w);
1913
+ ev_stop (EV_A_ (W)w);
1914
+ }
1915
+
1916
+ #if EV_STAT_ENABLE
1917
+
1918
+ # ifdef _WIN32
1919
+ # undef lstat
1920
+ # define lstat(a,b) _stati64 (a,b)
1921
+ # endif
1922
+
1923
+ #define DEF_STAT_INTERVAL 5.0074891
1924
+ #define MIN_STAT_INTERVAL 0.1074891
1925
+
1926
+ static void noinline stat_timer_cb (EV_P_ ev_timer *w_, int revents);
1927
+
1928
+ #if EV_USE_INOTIFY
1929
+ # define EV_INOTIFY_BUFSIZE 8192
1930
+
1931
+ static void noinline
1932
+ infy_add (EV_P_ ev_stat *w)
1933
+ {
1934
+ w->wd = inotify_add_watch (fs_fd, w->path, IN_ATTRIB | IN_DELETE_SELF | IN_MOVE_SELF | IN_MODIFY | IN_DONT_FOLLOW | IN_MASK_ADD);
1935
+
1936
+ if (w->wd < 0)
1937
+ {
1938
+ ev_timer_start (EV_A_ &w->timer); /* this is not race-free, so we still need to recheck periodically */
1939
+
1940
+ /* monitor some parent directory for speedup hints */
1941
+ if ((errno == ENOENT || errno == EACCES) && strlen (w->path) < 4096)
1942
+ {
1943
+ char path [4096];
1944
+ strcpy (path, w->path);
1945
+
1946
+ do
1947
+ {
1948
+ int mask = IN_MASK_ADD | IN_DELETE_SELF | IN_MOVE_SELF
1949
+ | (errno == EACCES ? IN_ATTRIB : IN_CREATE | IN_MOVED_TO);
1950
+
1951
+ char *pend = strrchr (path, '/');
1952
+
1953
+ if (!pend)
1954
+ break; /* whoops, no '/', complain to your admin */
1955
+
1956
+ *pend = 0;
1957
+ w->wd = inotify_add_watch (fs_fd, path, mask);
1958
+ }
1959
+ while (w->wd < 0 && (errno == ENOENT || errno == EACCES));
1960
+ }
1961
+ }
1962
+ else
1963
+ ev_timer_stop (EV_A_ &w->timer); /* we can watch this in a race-free way */
1964
+
1965
+ if (w->wd >= 0)
1966
+ wlist_add (&fs_hash [w->wd & (EV_INOTIFY_HASHSIZE - 1)].head, (WL)w);
1967
+ }
1968
+
1969
+ static void noinline
1970
+ infy_del (EV_P_ ev_stat *w)
1971
+ {
1972
+ int slot;
1973
+ int wd = w->wd;
1974
+
1975
+ if (wd < 0)
1976
+ return;
1977
+
1978
+ w->wd = -2;
1979
+ slot = wd & (EV_INOTIFY_HASHSIZE - 1);
1980
+ wlist_del (&fs_hash [slot].head, (WL)w);
1981
+
1982
+ /* remove this watcher, if others are watching it, they will rearm */
1983
+ inotify_rm_watch (fs_fd, wd);
1984
+ }
1985
+
1986
+ static void noinline
1987
+ infy_wd (EV_P_ int slot, int wd, struct inotify_event *ev)
1988
+ {
1989
+ if (slot < 0)
1990
+ /* overflow, need to check for all hahs slots */
1991
+ for (slot = 0; slot < EV_INOTIFY_HASHSIZE; ++slot)
1992
+ infy_wd (EV_A_ slot, wd, ev);
1993
+ else
1994
+ {
1995
+ WL w_;
1996
+
1997
+ for (w_ = fs_hash [slot & (EV_INOTIFY_HASHSIZE - 1)].head; w_; )
1998
+ {
1999
+ ev_stat *w = (ev_stat *)w_;
2000
+ w_ = w_->next; /* lets us remove this watcher and all before it */
2001
+
2002
+ if (w->wd == wd || wd == -1)
2003
+ {
2004
+ if (ev->mask & (IN_IGNORED | IN_UNMOUNT | IN_DELETE_SELF))
2005
+ {
2006
+ w->wd = -1;
2007
+ infy_add (EV_A_ w); /* re-add, no matter what */
2008
+ }
2009
+
2010
+ stat_timer_cb (EV_A_ &w->timer, 0);
2011
+ }
2012
+ }
2013
+ }
2014
+ }
2015
+
2016
+ static void
2017
+ infy_cb (EV_P_ ev_io *w, int revents)
2018
+ {
2019
+ char buf [EV_INOTIFY_BUFSIZE];
2020
+ struct inotify_event *ev = (struct inotify_event *)buf;
2021
+ int ofs;
2022
+ int len = read (fs_fd, buf, sizeof (buf));
2023
+
2024
+ for (ofs = 0; ofs < len; ofs += sizeof (struct inotify_event) + ev->len)
2025
+ infy_wd (EV_A_ ev->wd, ev->wd, ev);
2026
+ }
2027
+
2028
+ void inline_size
2029
+ infy_init (EV_P)
2030
+ {
2031
+ if (fs_fd != -2)
2032
+ return;
2033
+
2034
+ fs_fd = inotify_init ();
2035
+
2036
+ if (fs_fd >= 0)
2037
+ {
2038
+ ev_io_init (&fs_w, infy_cb, fs_fd, EV_READ);
2039
+ ev_set_priority (&fs_w, EV_MAXPRI);
2040
+ ev_io_start (EV_A_ &fs_w);
2041
+ }
2042
+ }
2043
+
2044
+ void inline_size
2045
+ infy_fork (EV_P)
2046
+ {
2047
+ int slot;
2048
+
2049
+ if (fs_fd < 0)
2050
+ return;
2051
+
2052
+ close (fs_fd);
2053
+ fs_fd = inotify_init ();
2054
+
2055
+ for (slot = 0; slot < EV_INOTIFY_HASHSIZE; ++slot)
2056
+ {
2057
+ WL w_ = fs_hash [slot].head;
2058
+ fs_hash [slot].head = 0;
2059
+
2060
+ while (w_)
2061
+ {
2062
+ ev_stat *w = (ev_stat *)w_;
2063
+ w_ = w_->next; /* lets us add this watcher */
2064
+
2065
+ w->wd = -1;
2066
+
2067
+ if (fs_fd >= 0)
2068
+ infy_add (EV_A_ w); /* re-add, no matter what */
2069
+ else
2070
+ ev_timer_start (EV_A_ &w->timer);
2071
+ }
2072
+
2073
+ }
2074
+ }
2075
+
2076
+ #endif
2077
+
2078
+ void
2079
+ ev_stat_stat (EV_P_ ev_stat *w)
2080
+ {
2081
+ if (lstat (w->path, &w->attr) < 0)
2082
+ w->attr.st_nlink = 0;
2083
+ else if (!w->attr.st_nlink)
2084
+ w->attr.st_nlink = 1;
2085
+ }
2086
+
2087
+ static void noinline
2088
+ stat_timer_cb (EV_P_ ev_timer *w_, int revents)
2089
+ {
2090
+ ev_stat *w = (ev_stat *)(((char *)w_) - offsetof (ev_stat, timer));
2091
+
2092
+ /* we copy this here each the time so that */
2093
+ /* prev has the old value when the callback gets invoked */
2094
+ w->prev = w->attr;
2095
+ ev_stat_stat (EV_A_ w);
2096
+
2097
+ /* memcmp doesn't work on netbsd, they.... do stuff to their struct stat */
2098
+ if (
2099
+ w->prev.st_dev != w->attr.st_dev
2100
+ || w->prev.st_ino != w->attr.st_ino
2101
+ || w->prev.st_mode != w->attr.st_mode
2102
+ || w->prev.st_nlink != w->attr.st_nlink
2103
+ || w->prev.st_uid != w->attr.st_uid
2104
+ || w->prev.st_gid != w->attr.st_gid
2105
+ || w->prev.st_rdev != w->attr.st_rdev
2106
+ || w->prev.st_size != w->attr.st_size
2107
+ || w->prev.st_atime != w->attr.st_atime
2108
+ || w->prev.st_mtime != w->attr.st_mtime
2109
+ || w->prev.st_ctime != w->attr.st_ctime
2110
+ ) {
2111
+ #if EV_USE_INOTIFY
2112
+ infy_del (EV_A_ w);
2113
+ infy_add (EV_A_ w);
2114
+ ev_stat_stat (EV_A_ w); /* avoid race... */
2115
+ #endif
2116
+
2117
+ ev_feed_event (EV_A_ w, EV_STAT);
2118
+ }
2119
+ }
2120
+
2121
+ void
2122
+ ev_stat_start (EV_P_ ev_stat *w)
2123
+ {
2124
+ if (expect_false (ev_is_active (w)))
2125
+ return;
2126
+
2127
+ /* since we use memcmp, we need to clear any padding data etc. */
2128
+ memset (&w->prev, 0, sizeof (ev_statdata));
2129
+ memset (&w->attr, 0, sizeof (ev_statdata));
2130
+
2131
+ ev_stat_stat (EV_A_ w);
2132
+
2133
+ if (w->interval < MIN_STAT_INTERVAL)
2134
+ w->interval = w->interval ? MIN_STAT_INTERVAL : DEF_STAT_INTERVAL;
2135
+
2136
+ ev_timer_init (&w->timer, stat_timer_cb, w->interval, w->interval);
2137
+ ev_set_priority (&w->timer, ev_priority (w));
2138
+
2139
+ #if EV_USE_INOTIFY
2140
+ infy_init (EV_A);
2141
+
2142
+ if (fs_fd >= 0)
2143
+ infy_add (EV_A_ w);
2144
+ else
2145
+ #endif
2146
+ ev_timer_start (EV_A_ &w->timer);
2147
+
2148
+ ev_start (EV_A_ (W)w, 1);
2149
+ }
2150
+
2151
+ void
2152
+ ev_stat_stop (EV_P_ ev_stat *w)
2153
+ {
2154
+ clear_pending (EV_A_ (W)w);
2155
+ if (expect_false (!ev_is_active (w)))
2156
+ return;
2157
+
2158
+ #if EV_USE_INOTIFY
2159
+ infy_del (EV_A_ w);
2160
+ #endif
2161
+ ev_timer_stop (EV_A_ &w->timer);
2162
+
2163
+ ev_stop (EV_A_ (W)w);
2164
+ }
2165
+ #endif
2166
+
2167
+ #if EV_IDLE_ENABLE
2168
+ void
2169
+ ev_idle_start (EV_P_ ev_idle *w)
2170
+ {
2171
+ if (expect_false (ev_is_active (w)))
2172
+ return;
2173
+
2174
+ pri_adjust (EV_A_ (W)w);
2175
+
2176
+ {
2177
+ int active = ++idlecnt [ABSPRI (w)];
2178
+
2179
+ ++idleall;
2180
+ ev_start (EV_A_ (W)w, active);
2181
+
2182
+ array_needsize (ev_idle *, idles [ABSPRI (w)], idlemax [ABSPRI (w)], active, EMPTY2);
2183
+ idles [ABSPRI (w)][active - 1] = w;
2184
+ }
2185
+ }
2186
+
2187
+ void
2188
+ ev_idle_stop (EV_P_ ev_idle *w)
2189
+ {
2190
+ clear_pending (EV_A_ (W)w);
2191
+ if (expect_false (!ev_is_active (w)))
2192
+ return;
2193
+
2194
+ {
2195
+ int active = ((W)w)->active;
2196
+
2197
+ idles [ABSPRI (w)][active - 1] = idles [ABSPRI (w)][--idlecnt [ABSPRI (w)]];
2198
+ ((W)idles [ABSPRI (w)][active - 1])->active = active;
2199
+
2200
+ ev_stop (EV_A_ (W)w);
2201
+ --idleall;
2202
+ }
2203
+ }
2204
+ #endif
2205
+
2206
+ void
2207
+ ev_prepare_start (EV_P_ ev_prepare *w)
2208
+ {
2209
+ if (expect_false (ev_is_active (w)))
2210
+ return;
2211
+
2212
+ ev_start (EV_A_ (W)w, ++preparecnt);
2213
+ array_needsize (ev_prepare *, prepares, preparemax, preparecnt, EMPTY2);
2214
+ prepares [preparecnt - 1] = w;
2215
+ }
2216
+
2217
+ void
2218
+ ev_prepare_stop (EV_P_ ev_prepare *w)
2219
+ {
2220
+ clear_pending (EV_A_ (W)w);
2221
+ if (expect_false (!ev_is_active (w)))
2222
+ return;
2223
+
2224
+ {
2225
+ int active = ((W)w)->active;
2226
+ prepares [active - 1] = prepares [--preparecnt];
2227
+ ((W)prepares [active - 1])->active = active;
2228
+ }
2229
+
2230
+ ev_stop (EV_A_ (W)w);
2231
+ }
2232
+
2233
+ void
2234
+ ev_check_start (EV_P_ ev_check *w)
2235
+ {
2236
+ if (expect_false (ev_is_active (w)))
2237
+ return;
2238
+
2239
+ ev_start (EV_A_ (W)w, ++checkcnt);
2240
+ array_needsize (ev_check *, checks, checkmax, checkcnt, EMPTY2);
2241
+ checks [checkcnt - 1] = w;
2242
+ }
2243
+
2244
+ void
2245
+ ev_check_stop (EV_P_ ev_check *w)
2246
+ {
2247
+ clear_pending (EV_A_ (W)w);
2248
+ if (expect_false (!ev_is_active (w)))
2249
+ return;
2250
+
2251
+ {
2252
+ int active = ((W)w)->active;
2253
+ checks [active - 1] = checks [--checkcnt];
2254
+ ((W)checks [active - 1])->active = active;
2255
+ }
2256
+
2257
+ ev_stop (EV_A_ (W)w);
2258
+ }
2259
+
2260
+ #if EV_EMBED_ENABLE
2261
+ void noinline
2262
+ ev_embed_sweep (EV_P_ ev_embed *w)
2263
+ {
2264
+ ev_loop (w->other, EVLOOP_NONBLOCK);
2265
+ }
2266
+
2267
+ static void
2268
+ embed_io_cb (EV_P_ ev_io *io, int revents)
2269
+ {
2270
+ ev_embed *w = (ev_embed *)(((char *)io) - offsetof (ev_embed, io));
2271
+
2272
+ if (ev_cb (w))
2273
+ ev_feed_event (EV_A_ (W)w, EV_EMBED);
2274
+ else
2275
+ ev_loop (w->other, EVLOOP_NONBLOCK);
2276
+ }
2277
+
2278
+ static void
2279
+ embed_prepare_cb (EV_P_ ev_prepare *prepare, int revents)
2280
+ {
2281
+ ev_embed *w = (ev_embed *)(((char *)prepare) - offsetof (ev_embed, prepare));
2282
+
2283
+ {
2284
+ struct ev_loop *loop = w->other;
2285
+
2286
+ while (fdchangecnt)
2287
+ {
2288
+ fd_reify (EV_A);
2289
+ ev_loop (EV_A_ EVLOOP_NONBLOCK);
2290
+ }
2291
+ }
2292
+ }
2293
+
2294
+ #if 0
2295
+ static void
2296
+ embed_idle_cb (EV_P_ ev_idle *idle, int revents)
2297
+ {
2298
+ ev_idle_stop (EV_A_ idle);
2299
+ }
2300
+ #endif
2301
+
2302
+ void
2303
+ ev_embed_start (EV_P_ ev_embed *w)
2304
+ {
2305
+ if (expect_false (ev_is_active (w)))
2306
+ return;
2307
+
2308
+ {
2309
+ struct ev_loop *loop = w->other;
2310
+ assert (("loop to be embedded is not embeddable", backend & ev_embeddable_backends ()));
2311
+ ev_io_init (&w->io, embed_io_cb, backend_fd, EV_READ);
2312
+ }
2313
+
2314
+ ev_set_priority (&w->io, ev_priority (w));
2315
+ ev_io_start (EV_A_ &w->io);
2316
+
2317
+ ev_prepare_init (&w->prepare, embed_prepare_cb);
2318
+ ev_set_priority (&w->prepare, EV_MINPRI);
2319
+ ev_prepare_start (EV_A_ &w->prepare);
2320
+
2321
+ /*ev_idle_init (&w->idle, e,bed_idle_cb);*/
2322
+
2323
+ ev_start (EV_A_ (W)w, 1);
2324
+ }
2325
+
2326
+ void
2327
+ ev_embed_stop (EV_P_ ev_embed *w)
2328
+ {
2329
+ clear_pending (EV_A_ (W)w);
2330
+ if (expect_false (!ev_is_active (w)))
2331
+ return;
2332
+
2333
+ ev_io_stop (EV_A_ &w->io);
2334
+ ev_prepare_stop (EV_A_ &w->prepare);
2335
+
2336
+ ev_stop (EV_A_ (W)w);
2337
+ }
2338
+ #endif
2339
+
2340
+ #if EV_FORK_ENABLE
2341
+ void
2342
+ ev_fork_start (EV_P_ ev_fork *w)
2343
+ {
2344
+ if (expect_false (ev_is_active (w)))
2345
+ return;
2346
+
2347
+ ev_start (EV_A_ (W)w, ++forkcnt);
2348
+ array_needsize (ev_fork *, forks, forkmax, forkcnt, EMPTY2);
2349
+ forks [forkcnt - 1] = w;
2350
+ }
2351
+
2352
+ void
2353
+ ev_fork_stop (EV_P_ ev_fork *w)
2354
+ {
2355
+ clear_pending (EV_A_ (W)w);
2356
+ if (expect_false (!ev_is_active (w)))
2357
+ return;
2358
+
2359
+ {
2360
+ int active = ((W)w)->active;
2361
+ forks [active - 1] = forks [--forkcnt];
2362
+ ((W)forks [active - 1])->active = active;
2363
+ }
2364
+
2365
+ ev_stop (EV_A_ (W)w);
2366
+ }
2367
+ #endif
2368
+
2369
+ /*****************************************************************************/
2370
+
2371
+ struct ev_once
2372
+ {
2373
+ ev_io io;
2374
+ ev_timer to;
2375
+ void (*cb)(int revents, void *arg);
2376
+ void *arg;
2377
+ };
2378
+
2379
+ static void
2380
+ once_cb (EV_P_ struct ev_once *once, int revents)
2381
+ {
2382
+ void (*cb)(int revents, void *arg) = once->cb;
2383
+ void *arg = once->arg;
2384
+
2385
+ ev_io_stop (EV_A_ &once->io);
2386
+ ev_timer_stop (EV_A_ &once->to);
2387
+ ev_free (once);
2388
+
2389
+ cb (revents, arg);
2390
+ }
2391
+
2392
+ static void
2393
+ once_cb_io (EV_P_ ev_io *w, int revents)
2394
+ {
2395
+ once_cb (EV_A_ (struct ev_once *)(((char *)w) - offsetof (struct ev_once, io)), revents);
2396
+ }
2397
+
2398
+ static void
2399
+ once_cb_to (EV_P_ ev_timer *w, int revents)
2400
+ {
2401
+ once_cb (EV_A_ (struct ev_once *)(((char *)w) - offsetof (struct ev_once, to)), revents);
2402
+ }
2403
+
2404
+ void
2405
+ ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg)
2406
+ {
2407
+ struct ev_once *once = (struct ev_once *)ev_malloc (sizeof (struct ev_once));
2408
+
2409
+ if (expect_false (!once))
2410
+ {
2411
+ cb (EV_ERROR | EV_READ | EV_WRITE | EV_TIMEOUT, arg);
2412
+ return;
2413
+ }
2414
+
2415
+ once->cb = cb;
2416
+ once->arg = arg;
2417
+
2418
+ ev_init (&once->io, once_cb_io);
2419
+ if (fd >= 0)
2420
+ {
2421
+ ev_io_set (&once->io, fd, events);
2422
+ ev_io_start (EV_A_ &once->io);
2423
+ }
2424
+
2425
+ ev_init (&once->to, once_cb_to);
2426
+ if (timeout >= 0.)
2427
+ {
2428
+ ev_timer_set (&once->to, timeout, 0.);
2429
+ ev_timer_start (EV_A_ &once->to);
2430
+ }
2431
+ }
2432
+
2433
+ #if EV_MULTIPLICITY
2434
+ #include "ev_wrap.h"
2435
+ #endif
2436
+
2437
+ #ifdef __cplusplus
2438
+ }
2439
+ #endif
2440
+