1/* 2 * Copyright (c) 2009 Mark Heily <mark@heily.com> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17#ifndef _KQUEUE_PRIVATE_H 18#define _KQUEUE_PRIVATE_H 19 20#if defined (__SVR4) && defined (__sun) 21# define SOLARIS 22# include <port.h> 23 /* Used to set portev_events for PORT_SOURCE_USER */ 24# define X_PORT_SOURCE_SIGNAL 101 25# define X_PORT_SOURCE_USER 102 26#endif 27 28#include <errno.h> 29#include <pthread.h> 30#include <stdbool.h> 31#include <stdio.h> 32#include <string.h> 33#include <sys/select.h> 34#include "../../include/sys/event.h" 35 36#include "tree.h" 37 38/* GCC atomic builtins. 39 * See: http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html 40 */ 41#ifdef __sun 42# include <atomic.h> 43# define atomic_inc atomic_inc_32 44# define atomic_dec atomic_dec_32 45#else 46# define atomic_inc(p) __sync_add_and_fetch((p), 1) 47# define atomic_dec(p) __sync_sub_and_fetch((p), 1) 48#endif 49 50/* Maximum events returnable in a single kevent() call */ 51#define MAX_KEVENT 512 52 53 54#ifndef NDEBUG 55 56extern int KQUEUE_DEBUG; 57 58#define dbg_puts(str) do { \ 59 if (KQUEUE_DEBUG) \ 60 fprintf(stderr, "KQ: %s(): %s\n", __func__,str); \ 61} while (0) 62 63#define dbg_printf(fmt,...) do { \ 64 if (KQUEUE_DEBUG) \ 65 fprintf(stderr, "KQ: %s(): "fmt"\n", __func__,__VA_ARGS__); \ 66} while (0) 67 68#define dbg_perror(str) do { \ 69 if (KQUEUE_DEBUG) \ 70 fprintf(stderr, "KQ: %s(): %s: %s (errno=%d)\n", \ 71 __func__, str, strerror(errno), errno); \ 72} while (0) 73 74# define reset_errno() do { errno = 0; } while (0) 75 76#else /* NDEBUG */ 77# define dbg_puts(str) ; 78# define dbg_printf(fmt,...) ; 79# define dbg_perror(str) ; 80# define reset_errno() ; 81#endif 82 83 84struct kqueue; 85struct kevent; 86struct evfilt_data; 87 88/* 89 * Flags used by knote->flags 90 */ 91#define KNFL_PASSIVE_SOCKET (0x01) /* Socket is in listen(2) mode */ 92 93/* TODO: Make this a variable length structure and allow 94 each filter to add custom fields at the end. 95 */ 96struct knote { 97 struct kevent kev; 98 int flags; 99 union { 100 int pfd; /* Used by timerfd */ 101 int events; /* Used by socket */ 102 struct { 103 nlink_t nlink; /* Used by vnode */ 104 off_t size; /* Used by vnode */ 105 } vnode; 106 timer_t timerid; 107 pthread_t tid; /* Used by posix/timer.c */ 108 } data; 109 TAILQ_ENTRY(knote) event_ent; /* Used by filter->kf_event */ 110 RB_ENTRY(knote) kntree_ent; /* Used by filter->kntree */ 111}; 112LIST_HEAD(knotelist, knote); 113 114#define KNOTE_ENABLE(ent) do { \ 115 (ent)->kev.flags &= ~EV_DISABLE; \ 116} while (0/*CONSTCOND*/) 117 118#define KNOTE_DISABLE(ent) do { \ 119 (ent)->kev.flags |= EV_DISABLE; \ 120} while (0/*CONSTCOND*/) 121 122struct filter { 123 short kf_id; 124 125 /* filter operations */ 126 127 int (*kf_init)(struct filter *); 128 void (*kf_destroy)(struct filter *); 129 int (*kf_copyout)(struct filter *, struct kevent *, int); 130 131 /* knote operations */ 132 133 int (*kn_create)(struct filter *, struct knote *); 134 int (*kn_modify)(struct filter *, struct knote *, 135 const struct kevent *); 136 int (*kn_delete)(struct filter *, struct knote *); 137 int (*kn_enable)(struct filter *, struct knote *); 138 int (*kn_disable)(struct filter *, struct knote *); 139 140 struct eventfd *kf_efd; /* Used by user.c */ 141 int kf_pfd; /* fd to poll(2) for readiness */ 142 int kf_wfd; /* fd to write when an event occurs */ 143 sigset_t kf_sigmask; 144 struct evfilt_data *kf_data; /* filter-specific data */ 145 RB_HEAD(knt, knote) kf_knote; 146 TAILQ_HEAD(, knote) kf_event; /* events that have occurred */ 147 struct kqueue *kf_kqueue; 148}; 149 150/* Use this to declare a filter that is not implemented */ 151#define EVFILT_NOTIMPL { 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } 152 153struct kqueue { 154 int kq_sockfd[2]; 155 struct filter kq_filt[EVFILT_SYSCOUNT]; 156 fd_set kq_fds, kq_rfds; 157 int kq_nfds; 158 pthread_mutex_t kq_mtx; 159#ifdef __sun__ 160 int kq_port; /* see: port_create(2) */ 161 pthread_key_t kq_port_event; 162#endif 163 volatile uint32_t kq_ref; 164 RB_ENTRY(kqueue) entries; 165}; 166 167struct knote * knote_lookup(struct filter *, uintptr_t); 168struct knote * knote_lookup_data(struct filter *filt, intptr_t); 169struct knote * knote_new(void); 170void knote_free(struct filter *, struct knote *); 171void knote_free_all(struct filter *); 172void knote_insert(struct filter *, struct knote *); 173int knote_get_socket_type(struct knote *); 174 175/* TODO: these deal with the eventlist, should use a different prefix */ 176void knote_enqueue(struct filter *, struct knote *); 177struct knote * knote_dequeue(struct filter *); 178int knote_events_pending(struct filter *); 179 180struct eventfd * eventfd_create(void); 181void eventfd_free(struct eventfd *); 182int eventfd_raise(struct eventfd *); 183int eventfd_lower(struct eventfd *); 184int eventfd_reader(struct eventfd *); 185int eventfd_writer(struct eventfd *); 186 187int filter_lookup(struct filter **, struct kqueue *, short); 188int filter_socketpair(struct filter *); 189int filter_register_all(struct kqueue *); 190void filter_unregister_all(struct kqueue *); 191const char *filter_name(short); 192int filter_lower(struct filter *); 193int filter_raise(struct filter *); 194 195int kevent_wait(struct kqueue *, const struct timespec *); 196int kevent_copyout(struct kqueue *, int, struct kevent *, int); 197void kevent_free(struct kqueue *); 198const char *kevent_dump(const struct kevent *); 199 200struct kqueue * kqueue_get(int); 201void kqueue_put(struct kqueue *); 202#define kqueue_lock(kq) pthread_mutex_lock(&(kq)->kq_mtx) 203#define kqueue_unlock(kq) pthread_mutex_unlock(&(kq)->kq_mtx) 204int kqueue_validate(struct kqueue *); 205 206#endif /* ! _KQUEUE_PRIVATE_H */ 207