mirror of
https://github.com/darlinghq/darling-libkqueue.git
synced 2024-11-23 11:49:50 +00:00
Merge new files from the trunk
git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/branches/stable@564 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7
This commit is contained in:
parent
eb1f64505b
commit
01da712896
385
src/linux/platform.c
Normal file
385
src/linux/platform.c
Normal file
@ -0,0 +1,385 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Mark Heily <mark@heily.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../common/private.h"
|
||||||
|
|
||||||
|
//XXX-FIXME TEMP
|
||||||
|
const struct filter evfilt_proc = EVFILT_NOTIMPL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Per-thread epoll event buffer used to ferry data between
|
||||||
|
* kevent_wait() and kevent_copyout().
|
||||||
|
*/
|
||||||
|
static __thread struct epoll_event epevt[MAX_KEVENT];
|
||||||
|
|
||||||
|
const struct kqueue_vtable kqops = {
|
||||||
|
linux_kqueue_init,
|
||||||
|
linux_kqueue_free,
|
||||||
|
linux_kevent_wait,
|
||||||
|
linux_kevent_copyout,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
linux_eventfd_init,
|
||||||
|
linux_eventfd_close,
|
||||||
|
linux_eventfd_raise,
|
||||||
|
linux_eventfd_lower,
|
||||||
|
linux_eventfd_descriptor
|
||||||
|
};
|
||||||
|
|
||||||
|
// NOT USED YET: taken from trunk
|
||||||
|
#ifdef TODO
|
||||||
|
int
|
||||||
|
linux_kqueue_init(struct kqueue *kq)
|
||||||
|
{
|
||||||
|
kq->kq_id = epoll_create(1);
|
||||||
|
if (kq->kq_id < 0) {
|
||||||
|
dbg_perror("epoll_create(2)");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter_register_all(kq) < 0) {
|
||||||
|
close(kq->kq_id);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if DEADWOOD
|
||||||
|
//might be useful in posix
|
||||||
|
|
||||||
|
/* Add each filter's pollable descriptor to the epollset */
|
||||||
|
for (i = 0; i < EVFILT_SYSCOUNT; i++) {
|
||||||
|
filt = &kq->kq_filt[i];
|
||||||
|
|
||||||
|
if (filt->kf_id == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
memset(&ev, 0, sizeof(ev));
|
||||||
|
ev.events = EPOLLIN;
|
||||||
|
ev.data.ptr = filt;
|
||||||
|
|
||||||
|
if (epoll_ctl(kq->kq_id, EPOLL_CTL_ADD, filt->kf_pfd, &ev) < 0) {
|
||||||
|
dbg_perror("epoll_ctl(2)");
|
||||||
|
close(kq->kq_id);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
linux_kqueue_free(struct kqueue *kq UNUSED)
|
||||||
|
{
|
||||||
|
abort();//FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
linux_kevent_wait_hires(
|
||||||
|
struct kqueue *kq,
|
||||||
|
const struct timespec *timeout)
|
||||||
|
{
|
||||||
|
fd_set fds;
|
||||||
|
int n;
|
||||||
|
int epfd;
|
||||||
|
|
||||||
|
dbg_printf("waiting for events (timeout=%ld sec %ld nsec)",
|
||||||
|
timeout->tv_sec, timeout->tv_nsec);
|
||||||
|
epfd = kqueue_epfd(kq);
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(epfd, &fds);
|
||||||
|
n = pselect(epfd + 1, &fds, NULL , NULL, timeout, NULL);
|
||||||
|
if (n < 0) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
dbg_puts("signal caught");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
dbg_perror("pselect(2)");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (n);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
linux_kevent_wait(
|
||||||
|
struct kqueue *kq,
|
||||||
|
int nevents,
|
||||||
|
const struct timespec *ts)
|
||||||
|
{
|
||||||
|
int timeout, nret;
|
||||||
|
|
||||||
|
/* Use pselect() if the timeout value is less than one millisecond. */
|
||||||
|
if (ts != NULL && ts->tv_sec == 0 && ts->tv_nsec < 1000000) {
|
||||||
|
nret = linux_kevent_wait_hires(kq, ts);
|
||||||
|
|
||||||
|
/* Otherwise, use epoll_wait() directly */
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Convert timeout to the format used by epoll_wait() */
|
||||||
|
if (ts == NULL)
|
||||||
|
timeout = -1;
|
||||||
|
else
|
||||||
|
timeout = (1000 * ts->tv_sec) + (ts->tv_nsec / 1000000);
|
||||||
|
|
||||||
|
dbg_puts("waiting for events");
|
||||||
|
nret = epoll_wait(kqueue_epfd(kq), &epevt[0], nevents, timeout);
|
||||||
|
if (nret < 0) {
|
||||||
|
dbg_perror("epoll_wait");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (nret);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
linux_kevent_copyout(struct kqueue *kq, int nready,
|
||||||
|
struct kevent *eventlist, int nevents UNUSED)
|
||||||
|
{
|
||||||
|
struct epoll_event *ev;
|
||||||
|
struct filter *filt;
|
||||||
|
struct knote *kn;
|
||||||
|
int i, nret, rv;
|
||||||
|
|
||||||
|
nret = nready;
|
||||||
|
for (i = 0; i < nready; i++) {
|
||||||
|
ev = &epevt[i];
|
||||||
|
kn = (struct knote *) ev->data.ptr;
|
||||||
|
knote_lock(kn);
|
||||||
|
filt = &kq->kq_filt[~(kn->kev.filter)];
|
||||||
|
rv = filt->kf_copyout(eventlist, kn, ev);
|
||||||
|
if (slowpath(rv < 0)) {
|
||||||
|
dbg_puts("knote_copyout failed");
|
||||||
|
/* XXX-FIXME: hard to handle this without losing events */
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Certain flags cause the associated knote to be deleted
|
||||||
|
* or disabled.
|
||||||
|
*/
|
||||||
|
if (eventlist->flags & EV_DISPATCH)
|
||||||
|
knote_disable(filt, kn); //FIXME: Error checking
|
||||||
|
if (eventlist->flags & EV_ONESHOT) {
|
||||||
|
knote_delete(filt, kn); //FIXME: Error checking
|
||||||
|
} else {
|
||||||
|
knote_unlock(kn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If an empty kevent structure is returned, the event is discarded. */
|
||||||
|
/* TODO: add these semantics to windows + solaris platform.c */
|
||||||
|
if (fastpath(eventlist->filter != 0)) {
|
||||||
|
eventlist++;
|
||||||
|
} else {
|
||||||
|
dbg_puts("spurious wakeup, discarding event");
|
||||||
|
nret--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (nret);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //NOT USED
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
linux_eventfd_init(struct eventfd *e)
|
||||||
|
{
|
||||||
|
int evfd;
|
||||||
|
|
||||||
|
if ((evfd = eventfd(0, 0)) < 0) {
|
||||||
|
dbg_perror("eventfd");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (fcntl(evfd, F_SETFL, O_NONBLOCK) < 0) {
|
||||||
|
dbg_perror("fcntl");
|
||||||
|
close(evfd);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
e->ef_id = evfd;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
linux_eventfd_close(struct eventfd *e)
|
||||||
|
{
|
||||||
|
close(e->ef_id);
|
||||||
|
e->ef_id = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
linux_eventfd_raise(struct eventfd *e)
|
||||||
|
{
|
||||||
|
uint64_t counter;
|
||||||
|
int rv = 0;
|
||||||
|
|
||||||
|
dbg_puts("raising event level");
|
||||||
|
counter = 1;
|
||||||
|
if (write(e->ef_id, &counter, sizeof(counter)) < 0) {
|
||||||
|
switch (errno) {
|
||||||
|
case EAGAIN:
|
||||||
|
/* Not considered an error */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EINTR:
|
||||||
|
rv = -EINTR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
dbg_printf("write(2): %s", strerror(errno));
|
||||||
|
rv = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
linux_eventfd_lower(struct eventfd *e)
|
||||||
|
{
|
||||||
|
uint64_t cur;
|
||||||
|
ssize_t n;
|
||||||
|
int rv = 0;
|
||||||
|
|
||||||
|
/* Reset the counter */
|
||||||
|
dbg_puts("lowering event level");
|
||||||
|
n = read(e->ef_id, &cur, sizeof(cur));
|
||||||
|
if (n < 0) {
|
||||||
|
switch (errno) {
|
||||||
|
case EAGAIN:
|
||||||
|
/* Not considered an error */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EINTR:
|
||||||
|
rv = -EINTR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
dbg_printf("read(2): %s", strerror(errno));
|
||||||
|
rv = -1;
|
||||||
|
}
|
||||||
|
} else if (n != sizeof(cur)) {
|
||||||
|
dbg_puts("short read");
|
||||||
|
rv = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
linux_eventfd_descriptor(struct eventfd *e)
|
||||||
|
{
|
||||||
|
return (e->ef_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
linux_get_descriptor_type(struct knote *kn)
|
||||||
|
{
|
||||||
|
socklen_t slen;
|
||||||
|
struct stat sb;
|
||||||
|
int i, lsock;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test if the descriptor is a socket.
|
||||||
|
*/
|
||||||
|
if (fstat(kn->kev.ident, &sb) < 0) {
|
||||||
|
dbg_perror("fstat(2)");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (! S_ISSOCK(sb.st_mode)) {
|
||||||
|
//FIXME: could be a pipe, device file, or other non-regular file
|
||||||
|
kn->kn_flags |= KNFL_REGULAR_FILE;
|
||||||
|
dbg_printf("fd %d is a regular file\n", (int)kn->kev.ident);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test if the socket is active or passive.
|
||||||
|
*/
|
||||||
|
slen = sizeof(lsock);
|
||||||
|
lsock = 0;
|
||||||
|
i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_ACCEPTCONN, (char *) &lsock, &slen);
|
||||||
|
if (i < 0) {
|
||||||
|
switch (errno) {
|
||||||
|
case ENOTSOCK: /* same as lsock = 0 */
|
||||||
|
return (0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dbg_perror("getsockopt(3)");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (lsock)
|
||||||
|
kn->kn_flags |= KNFL_PASSIVE_SOCKET;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
epoll_event_dump(struct epoll_event *evt)
|
||||||
|
{
|
||||||
|
static __thread char buf[128];
|
||||||
|
|
||||||
|
if (evt == NULL)
|
||||||
|
return "(null)";
|
||||||
|
|
||||||
|
#define EPEVT_DUMP(attrib) \
|
||||||
|
if (evt->events & attrib) \
|
||||||
|
strcat(&buf[0], #attrib" ");
|
||||||
|
|
||||||
|
snprintf(&buf[0], 128, " { data = %p, events = ", evt->data.ptr);
|
||||||
|
EPEVT_DUMP(EPOLLIN);
|
||||||
|
EPEVT_DUMP(EPOLLOUT);
|
||||||
|
#if defined(HAVE_EPOLLRDHUP)
|
||||||
|
EPEVT_DUMP(EPOLLRDHUP);
|
||||||
|
#endif
|
||||||
|
EPEVT_DUMP(EPOLLONESHOT);
|
||||||
|
EPEVT_DUMP(EPOLLET);
|
||||||
|
strcat(&buf[0], "}\n");
|
||||||
|
|
||||||
|
return (&buf[0]);
|
||||||
|
#undef EPEVT_DUMP
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
epoll_update(int op, struct filter *filt, struct knote *kn, struct epoll_event *ev)
|
||||||
|
{
|
||||||
|
dbg_printf("op=%d fd=%d events=%s", op, (int)kn->kev.ident,
|
||||||
|
epoll_event_dump(ev));
|
||||||
|
if (epoll_ctl(filter_epfd(filt), op, kn->kev.ident, ev) < 0) {
|
||||||
|
dbg_printf("epoll_ctl(2): %s", strerror(errno));
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a file descriptor, return the path to the file it refers to.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
linux_fd_to_path(char *buf, size_t bufsz, int fd)
|
||||||
|
{
|
||||||
|
char path[1024]; //TODO: Maxpathlen, etc.
|
||||||
|
|
||||||
|
if (snprintf(&path[0], sizeof(path), "/proc/%d/fd/%d", getpid(), fd) < 0)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
memset(buf, 0, bufsz);
|
||||||
|
return (readlink(path, buf, bufsz));
|
||||||
|
}
|
||||||
|
|
86
src/linux/platform.h
Normal file
86
src/linux/platform.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Mark Heily <mark@heily.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _KQUEUE_LINUX_PLATFORM_H
|
||||||
|
#define _KQUEUE_LINUX_PLATFORM_H
|
||||||
|
|
||||||
|
struct filter;
|
||||||
|
|
||||||
|
#include <sys/epoll.h>
|
||||||
|
#include <sys/queue.h>
|
||||||
|
#include <sys/inotify.h>
|
||||||
|
#include <sys/eventfd.h>
|
||||||
|
#include <sys/signalfd.h>
|
||||||
|
#include <sys/timerfd.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the current thread ID
|
||||||
|
*/
|
||||||
|
# define _GNU_SOURCE
|
||||||
|
# include <linux/unistd.h>
|
||||||
|
# include <sys/syscall.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
extern long int syscall (long int __sysno, ...);
|
||||||
|
|
||||||
|
/* Convenience macros to access the epoll descriptor for the kqueue */
|
||||||
|
#define kqueue_epfd(kq) ((kq)->kq_id)
|
||||||
|
#define filter_epfd(filt) ((filt)->kf_kqueue->kq_id)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Additional members of struct filter
|
||||||
|
*/
|
||||||
|
#undef FILTER_PLATFORM_SPECIFIC
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Additional members of struct knote
|
||||||
|
*/
|
||||||
|
#define KNOTE_PLATFORM_SPECIFIC \
|
||||||
|
int kn_epollfd; /* A copy of filter->epfd */ \
|
||||||
|
union { \
|
||||||
|
int kn_timerfd; \
|
||||||
|
int kn_signalfd; \
|
||||||
|
int kn_inotifyfd; \
|
||||||
|
int kn_eventfd; \
|
||||||
|
} kdata
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Additional members of struct kqueue
|
||||||
|
*/
|
||||||
|
#define KQUEUE_PLATFORM_SPECIFIC \
|
||||||
|
struct epoll_event kq_plist[MAX_KEVENT]; \
|
||||||
|
size_t kq_nplist
|
||||||
|
|
||||||
|
int linux_kqueue_init(struct kqueue *);
|
||||||
|
void linux_kqueue_free(struct kqueue *);
|
||||||
|
|
||||||
|
int linux_kevent_wait(struct kqueue *, int, const struct timespec *);
|
||||||
|
int linux_kevent_copyout(struct kqueue *, int, struct kevent *, int);
|
||||||
|
|
||||||
|
int linux_knote_copyout(struct kevent *, struct knote *);
|
||||||
|
|
||||||
|
int linux_eventfd_init(struct eventfd *);
|
||||||
|
void linux_eventfd_close(struct eventfd *);
|
||||||
|
int linux_eventfd_raise(struct eventfd *);
|
||||||
|
int linux_eventfd_lower(struct eventfd *);
|
||||||
|
int linux_eventfd_descriptor(struct eventfd *);
|
||||||
|
|
||||||
|
/* utility functions */
|
||||||
|
|
||||||
|
int linux_get_descriptor_type(struct knote *);
|
||||||
|
int linux_fd_to_path(char *, size_t, int);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ! _KQUEUE_LINUX_PLATFORM_H */
|
90
src/posix/platform.c
Normal file
90
src/posix/platform.c
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Mark Heily <mark@heily.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../common/private.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
posix_kqueue_init(struct kqueue *kq UNUSED)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
posix_kqueue_free(struct kqueue *kq UNUSED)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
posix_eventfd_init(struct eventfd *e)
|
||||||
|
{
|
||||||
|
int sd[2];
|
||||||
|
|
||||||
|
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sd) < 0) {
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if ((fcntl(sd[0], F_SETFL, O_NONBLOCK) < 0) ||
|
||||||
|
(fcntl(sd[1], F_SETFL, O_NONBLOCK) < 0)) {
|
||||||
|
close(sd[0]);
|
||||||
|
close(sd[1]);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
e->ef_wfd = sd[0];
|
||||||
|
e->ef_id = sd[1];
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
posix_eventfd_close(struct eventfd *e)
|
||||||
|
{
|
||||||
|
close(e->ef_id);
|
||||||
|
close(e->ef_wfd);
|
||||||
|
e->ef_id = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
posix_eventfd_raise(struct eventfd *e)
|
||||||
|
{
|
||||||
|
dbg_puts("raising event level");
|
||||||
|
if (write(e->ef_wfd, ".", 1) < 0) {
|
||||||
|
/* FIXME: handle EAGAIN and EINTR */
|
||||||
|
dbg_printf("write(2) on fd %d: %s", e->ef_wfd, strerror(errno));
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
posix_eventfd_lower(struct eventfd *e)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
/* Reset the counter */
|
||||||
|
dbg_puts("lowering event level");
|
||||||
|
if (read(e->ef_id, &buf, sizeof(buf)) < 0) {
|
||||||
|
/* FIXME: handle EAGAIN and EINTR */
|
||||||
|
/* FIXME: loop so as to consume all data.. may need mutex */
|
||||||
|
dbg_printf("read(2): %s", strerror(errno));
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
posix_eventfd_descriptor(struct eventfd *e)
|
||||||
|
{
|
||||||
|
return (e->ef_id);
|
||||||
|
}
|
86
src/posix/platform.h
Normal file
86
src/posix/platform.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Mark Heily <mark@heily.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _KQUEUE_POSIX_PLATFORM_H
|
||||||
|
#define _KQUEUE_POSIX_PLATFORM_H
|
||||||
|
|
||||||
|
/* Required by glibc for MAP_ANON */
|
||||||
|
#define __USE_MISC 1
|
||||||
|
|
||||||
|
#include "../../include/sys/event.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GCC-compatible atomic operations
|
||||||
|
*/
|
||||||
|
#define atomic_inc(p) __sync_add_and_fetch((p), 1)
|
||||||
|
#define atomic_dec(p) __sync_sub_and_fetch((p), 1)
|
||||||
|
#define atomic_cas(p, oval, nval) __sync_val_compare_and_swap(p, oval, nval)
|
||||||
|
#define atomic_ptr_cas(p, oval, nval) __sync_val_compare_and_swap(p, oval, nval)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GCC-compatible branch prediction macros
|
||||||
|
*/
|
||||||
|
#define fastpath(x) __builtin_expect((x), 1)
|
||||||
|
#define slowpath(x) __builtin_expect((x), 0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GCC-compatible attributes
|
||||||
|
*/
|
||||||
|
#ifdef MAKE_STATIC
|
||||||
|
# define CONSTRUCTOR
|
||||||
|
#else
|
||||||
|
# define CONSTRUCTOR __attribute__ ((constructor))
|
||||||
|
#endif
|
||||||
|
#define VISIBLE __attribute__((visibility("default")))
|
||||||
|
#define HIDDEN __attribute__((visibility("hidden")))
|
||||||
|
#define UNUSED __attribute__((unused))
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Additional members of 'struct eventfd'
|
||||||
|
*/
|
||||||
|
#define EVENTFD_PLATFORM_SPECIFIC \
|
||||||
|
int ef_wfd
|
||||||
|
|
||||||
|
void posix_kqueue_free(struct kqueue *);
|
||||||
|
int posix_kqueue_init(struct kqueue *);
|
||||||
|
|
||||||
|
int posix_kevent_wait(struct kqueue *, const struct timespec *);
|
||||||
|
int posix_kevent_copyout(struct kqueue *, int, struct kevent *, int);
|
||||||
|
|
||||||
|
int posix_eventfd_init(struct eventfd *);
|
||||||
|
void posix_eventfd_close(struct eventfd *);
|
||||||
|
int posix_eventfd_raise(struct eventfd *);
|
||||||
|
int posix_eventfd_lower(struct eventfd *);
|
||||||
|
int posix_eventfd_descriptor(struct eventfd *);
|
||||||
|
|
||||||
|
#endif /* ! _KQUEUE_POSIX_PLATFORM_H */
|
Loading…
Reference in New Issue
Block a user