~ubuntu-branches/ubuntu/trusty/nodejs/trusty-proposed

« back to all changes in this revision

Viewing changes to .pc/1005_unbreak_bsd_builds.patch/deps/uv/src/unix/kqueue.c

  • Committer: Package Import Robot
  • Author(s): Jérémy Lal
  • Date: 2013-12-12 23:04:07 UTC
  • mfrom: (1.1.30)
  • Revision ID: package-import@ubuntu.com-20131212230407-xfa6gka4c6oatsx1
Tags: 0.10.23~dfsg1-1
* Upstream update.
* Refresh patches, remove 1005 patch, applied upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2
 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
3
 
 * of this software and associated documentation files (the "Software"), to
4
 
 * deal in the Software without restriction, including without limitation the
5
 
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
6
 
 * sell copies of the Software, and to permit persons to whom the Software is
7
 
 * furnished to do so, subject to the following conditions:
8
 
 *
9
 
 * The above copyright notice and this permission notice shall be included in
10
 
 * all copies or substantial portions of the Software.
11
 
 *
12
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13
 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14
 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15
 
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16
 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17
 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
18
 
 * IN THE SOFTWARE.
19
 
 */
20
 
 
21
 
#include "uv.h"
22
 
#include "internal.h"
23
 
 
24
 
#include <assert.h>
25
 
#include <stdlib.h>
26
 
#include <string.h>
27
 
#include <errno.h>
28
 
 
29
 
#include <sys/sysctl.h>
30
 
#include <sys/types.h>
31
 
#include <sys/event.h>
32
 
#include <sys/time.h>
33
 
#include <unistd.h>
34
 
#include <fcntl.h>
35
 
#include <time.h>
36
 
 
37
 
static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags);
38
 
 
39
 
 
40
 
int uv__kqueue_init(uv_loop_t* loop) {
41
 
  loop->backend_fd = kqueue();
42
 
 
43
 
  if (loop->backend_fd == -1)
44
 
    return -1;
45
 
 
46
 
  uv__cloexec(loop->backend_fd, 1);
47
 
 
48
 
  return 0;
49
 
}
50
 
 
51
 
 
52
 
void uv__io_poll(uv_loop_t* loop, int timeout) {
53
 
  struct kevent events[1024];
54
 
  struct kevent* ev;
55
 
  struct timespec spec;
56
 
  unsigned int nevents;
57
 
  unsigned int revents;
58
 
  ngx_queue_t* q;
59
 
  uint64_t base;
60
 
  uint64_t diff;
61
 
  uv__io_t* w;
62
 
  int filter;
63
 
  int fflags;
64
 
  int count;
65
 
  int nfds;
66
 
  int fd;
67
 
  int op;
68
 
  int i;
69
 
 
70
 
  if (loop->nfds == 0) {
71
 
    assert(ngx_queue_empty(&loop->watcher_queue));
72
 
    return;
73
 
  }
74
 
 
75
 
  nevents = 0;
76
 
 
77
 
  while (!ngx_queue_empty(&loop->watcher_queue)) {
78
 
    q = ngx_queue_head(&loop->watcher_queue);
79
 
    ngx_queue_remove(q);
80
 
    ngx_queue_init(q);
81
 
 
82
 
    w = ngx_queue_data(q, uv__io_t, watcher_queue);
83
 
    assert(w->pevents != 0);
84
 
    assert(w->fd >= 0);
85
 
    assert(w->fd < (int) loop->nwatchers);
86
 
 
87
 
    if ((w->events & UV__POLLIN) == 0 && (w->pevents & UV__POLLIN) != 0) {
88
 
      filter = EVFILT_READ;
89
 
      fflags = 0;
90
 
      op = EV_ADD;
91
 
 
92
 
      if (w->cb == uv__fs_event) {
93
 
        filter = EVFILT_VNODE;
94
 
        fflags = NOTE_ATTRIB | NOTE_WRITE  | NOTE_RENAME
95
 
               | NOTE_DELETE | NOTE_EXTEND | NOTE_REVOKE;
96
 
        op = EV_ADD | EV_ONESHOT; /* Stop the event from firing repeatedly. */
97
 
      }
98
 
 
99
 
      EV_SET(events + nevents, w->fd, filter, op, fflags, 0, 0);
100
 
 
101
 
      if (++nevents == ARRAY_SIZE(events)) {
102
 
        if (kevent(loop->backend_fd, events, nevents, NULL, 0, NULL))
103
 
          abort();
104
 
        nevents = 0;
105
 
      }
106
 
    }
107
 
 
108
 
    if ((w->events & UV__POLLOUT) == 0 && (w->pevents & UV__POLLOUT) != 0) {
109
 
      EV_SET(events + nevents, w->fd, EVFILT_WRITE, EV_ADD, 0, 0, 0);
110
 
 
111
 
      if (++nevents == ARRAY_SIZE(events)) {
112
 
        if (kevent(loop->backend_fd, events, nevents, NULL, 0, NULL))
113
 
          abort();
114
 
        nevents = 0;
115
 
      }
116
 
    }
117
 
 
118
 
    w->events = w->pevents;
119
 
  }
120
 
 
121
 
  assert(timeout >= -1);
122
 
  base = loop->time;
123
 
  count = 48; /* Benchmarks suggest this gives the best throughput. */
124
 
 
125
 
  for (;; nevents = 0) {
126
 
    if (timeout != -1) {
127
 
      spec.tv_sec = timeout / 1000;
128
 
      spec.tv_nsec = (timeout % 1000) * 1000000;
129
 
    }
130
 
 
131
 
    nfds = kevent(loop->backend_fd,
132
 
                  events,
133
 
                  nevents,
134
 
                  events,
135
 
                  ARRAY_SIZE(events),
136
 
                  timeout == -1 ? NULL : &spec);
137
 
 
138
 
    /* Update loop->time unconditionally. It's tempting to skip the update when
139
 
     * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
140
 
     * operating system didn't reschedule our process while in the syscall.
141
 
     */
142
 
    SAVE_ERRNO(uv__update_time(loop));
143
 
 
144
 
    if (nfds == 0) {
145
 
      assert(timeout != -1);
146
 
      return;
147
 
    }
148
 
 
149
 
    if (nfds == -1) {
150
 
      if (errno != EINTR)
151
 
        abort();
152
 
 
153
 
      if (timeout == 0)
154
 
        return;
155
 
 
156
 
      if (timeout == -1)
157
 
        continue;
158
 
 
159
 
      /* Interrupted by a signal. Update timeout and poll again. */
160
 
      goto update_timeout;
161
 
    }
162
 
 
163
 
    nevents = 0;
164
 
 
165
 
    assert(loop->watchers != NULL);
166
 
    loop->watchers[loop->nwatchers] = (void*) events;
167
 
    loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
168
 
    for (i = 0; i < nfds; i++) {
169
 
      ev = events + i;
170
 
      fd = ev->ident;
171
 
      w = loop->watchers[fd];
172
 
 
173
 
      /* Skip invalidated events, see uv__platform_invalidate_fd */
174
 
      if (fd == -1)
175
 
        continue;
176
 
 
177
 
      if (w == NULL) {
178
 
        /* File descriptor that we've stopped watching, disarm it. */
179
 
        /* TODO batch up */
180
 
        struct kevent events[1];
181
 
 
182
 
        EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0);
183
 
        if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL))
184
 
          if (errno != EBADF && errno != ENOENT)
185
 
            abort();
186
 
 
187
 
        continue;
188
 
      }
189
 
 
190
 
      if (ev->filter == EVFILT_VNODE) {
191
 
        assert(w->events == UV__POLLIN);
192
 
        assert(w->pevents == UV__POLLIN);
193
 
        w->cb(loop, w, ev->fflags); /* XXX always uv__fs_event() */
194
 
        nevents++;
195
 
        continue;
196
 
      }
197
 
 
198
 
      revents = 0;
199
 
 
200
 
      if (ev->filter == EVFILT_READ) {
201
 
        if (w->pevents & UV__POLLIN) {
202
 
          revents |= UV__POLLIN;
203
 
          w->rcount = ev->data;
204
 
        } else {
205
 
          /* TODO batch up */
206
 
          struct kevent events[1];
207
 
          EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0);
208
 
          if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL))
209
 
            if (errno != ENOENT)
210
 
              abort();
211
 
        }
212
 
      }
213
 
 
214
 
      if (ev->filter == EVFILT_WRITE) {
215
 
        if (w->pevents & UV__POLLOUT) {
216
 
          revents |= UV__POLLOUT;
217
 
          w->wcount = ev->data;
218
 
        } else {
219
 
          /* TODO batch up */
220
 
          struct kevent events[1];
221
 
          EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0);
222
 
          if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL))
223
 
            if (errno != ENOENT)
224
 
              abort();
225
 
        }
226
 
      }
227
 
 
228
 
      if (ev->flags & EV_ERROR)
229
 
        revents |= UV__POLLERR;
230
 
 
231
 
      if (revents == 0)
232
 
        continue;
233
 
 
234
 
      w->cb(loop, w, revents);
235
 
      nevents++;
236
 
    }
237
 
    loop->watchers[loop->nwatchers] = NULL;
238
 
    loop->watchers[loop->nwatchers + 1] = NULL;
239
 
 
240
 
    if (nevents != 0) {
241
 
      if (nfds == ARRAY_SIZE(events) && --count != 0) {
242
 
        /* Poll for more events but don't block this time. */
243
 
        timeout = 0;
244
 
        continue;
245
 
      }
246
 
      return;
247
 
    }
248
 
 
249
 
    if (timeout == 0)
250
 
      return;
251
 
 
252
 
    if (timeout == -1)
253
 
      continue;
254
 
 
255
 
update_timeout:
256
 
    assert(timeout > 0);
257
 
 
258
 
    diff = loop->time - base;
259
 
    if (diff >= (uint64_t) timeout)
260
 
      return;
261
 
 
262
 
    timeout -= diff;
263
 
  }
264
 
}
265
 
 
266
 
 
267
 
static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags) {
268
 
  uv_fs_event_t* handle;
269
 
  struct kevent ev;
270
 
  int events;
271
 
 
272
 
  handle = container_of(w, uv_fs_event_t, event_watcher);
273
 
 
274
 
  if (fflags & (NOTE_ATTRIB | NOTE_EXTEND))
275
 
    events = UV_CHANGE;
276
 
  else
277
 
    events = UV_RENAME;
278
 
 
279
 
  handle->cb(handle, NULL, events, 0);
280
 
 
281
 
  if (handle->event_watcher.fd == -1)
282
 
    return;
283
 
 
284
 
  /* Watcher operates in one-shot mode, re-arm it. */
285
 
  fflags = NOTE_ATTRIB | NOTE_WRITE  | NOTE_RENAME
286
 
         | NOTE_DELETE | NOTE_EXTEND | NOTE_REVOKE;
287
 
 
288
 
  EV_SET(&ev, w->fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, fflags, 0, 0);
289
 
 
290
 
  if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL))
291
 
    abort();
292
 
}
293
 
 
294
 
 
295
 
int uv_fs_event_init(uv_loop_t* loop,
296
 
                     uv_fs_event_t* handle,
297
 
                     const char* filename,
298
 
                     uv_fs_event_cb cb,
299
 
                     int flags) {
300
 
#if defined(__APPLE__)
301
 
  struct stat statbuf;
302
 
#endif /* defined(__APPLE__) */
303
 
  int fd;
304
 
 
305
 
  /* TODO open asynchronously - but how do we report back errors? */
306
 
  if ((fd = open(filename, O_RDONLY)) == -1) {
307
 
    uv__set_sys_error(loop, errno);
308
 
    return -1;
309
 
  }
310
 
 
311
 
  uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
312
 
  uv__handle_start(handle); /* FIXME shouldn't start automatically */
313
 
  uv__io_init(&handle->event_watcher, uv__fs_event, fd);
314
 
  handle->filename = strdup(filename);
315
 
  handle->cb = cb;
316
 
 
317
 
#if defined(__APPLE__)
318
 
  /* Nullify field to perform checks later */
319
 
  handle->cf_eventstream = NULL;
320
 
  handle->realpath = NULL;
321
 
  handle->realpath_len = 0;
322
 
  handle->cf_flags = flags;
323
 
 
324
 
  if (fstat(fd, &statbuf))
325
 
    goto fallback;
326
 
  /* FSEvents works only with directories */
327
 
  if (!(statbuf.st_mode & S_IFDIR))
328
 
    goto fallback;
329
 
 
330
 
  return uv__fsevents_init(handle);
331
 
 
332
 
fallback:
333
 
#endif /* defined(__APPLE__) */
334
 
 
335
 
  uv__io_start(loop, &handle->event_watcher, UV__POLLIN);
336
 
 
337
 
  return 0;
338
 
}
339
 
 
340
 
 
341
 
void uv__fs_event_close(uv_fs_event_t* handle) {
342
 
#if defined(__APPLE__)
343
 
  if (uv__fsevents_close(handle))
344
 
    uv__io_stop(handle->loop, &handle->event_watcher, UV__POLLIN);
345
 
#else
346
 
  uv__io_stop(handle->loop, &handle->event_watcher, UV__POLLIN);
347
 
#endif /* defined(__APPLE__) */
348
 
 
349
 
  uv__handle_stop(handle);
350
 
 
351
 
  free(handle->filename);
352
 
  handle->filename = NULL;
353
 
 
354
 
  close(handle->event_watcher.fd);
355
 
  handle->event_watcher.fd = -1;
356
 
}