root/platform/mysql/mycached/trunk/picoev_kqueue.c @ 35019

Revision 35019, 4.6 kB (checked in by kazuho, 4 years ago)

update picoev

Line 
1/*
2 * Copyright (c) 2009, Cybozu Labs, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 *   this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 *   this list of conditions and the following disclaimer in the documentation
12 *   and/or other materials provided with the distribution.
13 * * Neither the name of the <ORGANIZATION> nor the names of its contributors
14 *   may be used to endorse or promote products derived from this software
15 *   without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include <errno.h>
31#include <sys/types.h>
32#include <sys/event.h>
33#include <sys/time.h>
34#include <unistd.h>
35#include "picoev.h"
36
37#define EV_QUEUE_SZ 128
38
39typedef struct picoev_loop_kqueue_st {
40  picoev_loop loop;
41  int kq;
42  struct kevent ev_queue[EV_QUEUE_SZ];
43  size_t ev_queue_off;
44  struct kevent events[1024];
45} picoev_loop_kqueue;
46
47picoev_globals picoev;
48
49picoev_loop* picoev_create_loop(int max_timeout)
50{
51  picoev_loop_kqueue* loop;
52 
53  /* init parent */
54  assert(PICOEV_IS_INITED);
55  if ((loop = (picoev_loop_kqueue*)malloc(sizeof(picoev_loop_kqueue)))
56      == NULL) {
57    return NULL;
58  }
59  if (picoev_init_loop_internal(&loop->loop, max_timeout) != 0) {
60    free(loop);
61    return NULL;
62  }
63 
64  /* init kqueue */
65  if ((loop->kq = kqueue()) == -1) {
66    picoev_deinit_loop_internal(&loop->loop);
67    free(loop);
68    return NULL;
69  }
70 
71  return &loop->loop;
72}
73
74int picoev_destroy_loop(picoev_loop* _loop)
75{
76  picoev_loop_kqueue* loop = (picoev_loop_kqueue*)_loop;
77 
78  if (close(loop->kq) != 0) {
79    return -1;
80  }
81  picoev_deinit_loop_internal(&loop->loop);
82  free(loop);
83  return 0;
84}
85
86int picoev_init_backend()
87{
88  return 0;
89}
90
91int picoev_deinit_backend()
92{
93  return 0;
94}
95
96int picoev_update_events_internal(picoev_loop* _loop, int fd, int events)
97{
98  picoev_loop_kqueue* loop = (picoev_loop_kqueue*)_loop;
99 
100  assert(PICOEV_FD_BELONGS_TO_LOOP(&loop->loop, fd));
101 
102#define SET(ev, cmd)                                      \
103  EV_SET(loop->ev_queue + loop->ev_queue_off++, fd,       \
104         ((ev & PICOEV_READ) != 0 ? EVFILT_READ : 0)      \
105         | ((ev & PICOEV_WRITE) != 0 ? EVFILT_WRITE : 0), \
106         cmd, 0, 0, NULL)
107 
108  if (picoev.fds[fd].events != 0) {
109    SET(picoev.fds[fd].events, EV_ADD | EV_ENABLE);
110  }
111  if (events != 0) {
112    SET(events, EV_ADD);
113  }
114 
115#undef SET
116 
117  /* should call imediately if the user might be going to close the socket */
118  if (events == 0 || loop->ev_queue_off + 2 >= EV_QUEUE_SZ) {
119    int r = kevent(loop->kq, loop->ev_queue, loop->ev_queue_off, NULL, 0, NULL);
120    assert(r == 0);
121    loop->ev_queue_off = 0;
122  }
123 
124  picoev.fds[fd].events = events;
125  return 0;
126}
127
128int picoev_poll_once_internal(picoev_loop* _loop, int max_wait)
129{
130  picoev_loop_kqueue* loop = (picoev_loop_kqueue*)_loop;
131  struct timespec ts;
132  int nevents, i;
133 
134  ts.tv_sec = max_wait;
135  ts.tv_nsec = 0;
136  nevents = kevent(loop->kq, loop->ev_queue, loop->ev_queue_off, loop->events,
137                   sizeof(loop->events) / sizeof(loop->events[0]), &ts);
138  loop->ev_queue_off = 0;
139  if (nevents == -1) {
140    /* the errors we can only rescue */
141    assert(errno == EACCES || errno == EFAULT || errno == EINTR);
142    return -1;
143  }
144  for (i = 0; i < nevents; ++i) {
145    struct kevent* event = loop->events + i;
146    picoev_fd* target = picoev.fds + event->ident;
147    assert((event->flags & EV_ERROR) == 0); /* changelist errors are fatal */
148    if (loop->loop.loop_id == target->loop_id
149        && (event->flags & (EVFILT_READ | EVFILT_WRITE)) != 0) {
150      int revents = ((event->flags & EVFILT_READ) != 0 ? PICOEV_READ : 0)
151        | ((event->flags & EVFILT_WRITE) != 0 ? PICOEV_WRITE : 0);
152      (*target->callback)(&loop->loop, event->ident, revents,
153                          target->cb_arg);
154    }
155  }
156  return 0;
157}
Note: See TracBrowser for help on using the browser.