Remove the dependency on pthreads, and move dispatching to a separate translation unit

git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@663 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7
This commit is contained in:
mheily 2013-11-20 02:07:58 +00:00
parent 08a79a3aec
commit a125325ca4
3 changed files with 76 additions and 32 deletions

View File

@ -1,5 +1,12 @@
test-lite: test-lite.c kqlite.c lite.h
gcc -D_GNU_SOURCE=1 -g -O0 -std=c99 -Wall -Werror -fopenmp -o test-lite test-lite.c kqlite.c
gcc -D_GNU_SOURCE=1 -g -O0 -std=c99 -Wall -Werror -o test-lite test-lite.c kqlite.c
#TODO:
test-dispatch: test-dispatch.c lite.h
gcc -D_GNU_SOURCE=1 -g -O0 -std=c99 -Wall -Werror -fopenmp -o test-dispatch kqlite.c test-dispatch.c dispatch.c
check: test-lite
./test-lite
clean:
rm -f test-lite *.o

47
kqlite/dispatch.c Normal file
View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2013 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 <pthread.h>
#ifdef _OPENMP
#include <omp.h>
#endif /* _OPENMP */
/*
* EXPERIMENTAL dispatching API
*/
void
kq_dispatch(kqueue_t kq, void (*cb)(kqueue_t, struct kevent))
{
const int maxevents = 64; /* Should be more like 2xNCPU */
struct kevent events[maxevents];
ssize_t nevents;
int i;
for (;;) {
nevents = kq_event(kq, NULL, 0, (struct kevent *) &events, maxevents, NULL);
if (nevents < 0)
abort();
#pragma omp parallel
{
for (i = 0; i < nevents; i++) {
#pragma omp single nowait
(*cb)(kq, events[i]);
}
}
}
}

View File

@ -19,10 +19,6 @@
#include <stdio.h>
#include <string.h>
#ifdef _OPENMP
#include <omp.h>
#endif /* _OPENMP */
#include "./lite.h"
#include "./utarray.h"
@ -44,7 +40,6 @@
#include <sys/event.h>
#elif defined(__linux__)
#define USE_EPOLL
#include <pthread.h>
#include <sys/epoll.h>
#include <sys/inotify.h>
#include <sys/signalfd.h>
@ -52,6 +47,10 @@
#include <stdlib.h>
#include <string.h>
#ifdef KQ_THREADSAFE
#include <pthread.h>
#endif
static char * epoll_event_to_str(struct epoll_event *);
#else
#error Unsupported operating system type
@ -70,7 +69,17 @@ struct kqueue {
the 'ident' parameter of the 'struct kevent' in the knote.
*/
UT_array *knote[EVFILT_SYSCOUNT];
/* This allows all kevents to share a single inotify descriptor.
* Key: inotify watch descriptor returned by inotify_add_watch()
* Value: pointer to knote
*/
UT_array *ino_knote;
#ifdef KQ_THREADSAFE
pthread_mutex_t kq_mtx;
#endif
#else
#error Undefined event system
#endif
@ -84,7 +93,7 @@ struct knote {
struct kevent kev;
union {
int timerfd; /* Each EVFILT_TIMER kevent has a timerfd */
int inofd; /* Each EVFILT_VNODE kevent has an inotify fd */
int ino_wd; /* EVFILT_VNODE: index within kq->ino_knote */
} aux;
int deleted; /* When EV_DELETE is used, it marks the knote deleted instead of freeing the object. This helps with threadsafety by ensuring that threads don't try to access a freed object. It doesn't help with memory usage, as the memory is never reclaimed. */
};
@ -92,15 +101,19 @@ struct knote {
static inline void
kq_lock(kqueue_t kq)
{
#ifdef KQ_THREADSAFE
if (pthread_mutex_lock(&kq->kq_mtx) != 0)
abort();
#endif
}
static inline void
kq_unlock(kqueue_t kq)
{
#ifdef KQ_THREADSAFE
if (pthread_mutex_unlock(&kq->kq_mtx) != 0)
abort();
#endif
}
UT_icd knote_icd = { sizeof(struct knote), NULL, NULL, NULL };
@ -127,8 +140,10 @@ kq_init(void)
if ((kq = malloc(sizeof(*kq))) == NULL)
return (NULL);
#ifdef KQ_THREADSAFE
if (pthread_mutex_init(&kq->kq_mtx, NULL) != 0)
goto errout;
#endif
/* Create an index of kevents to allow lookups from epev.data.u32 */
@ -457,31 +472,6 @@ int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges,
#endif
}
/*
* EXPERIMENTAL dispatching API
*/
void
kq_dispatch(kqueue_t kq, void (*cb)(kqueue_t, struct kevent))
{
const int maxevents = 64; /* Should be more like 2xNCPU */
struct kevent events[maxevents];
ssize_t nevents;
int i;
for (;;) {
nevents = kq_event(kq, NULL, 0, (struct kevent *) &events, maxevents, NULL);
if (nevents < 0)
abort();
#pragma omp parallel
{
for (i = 0; i < nevents; i++) {
#pragma omp single nowait
(*cb)(kq, events[i]);
}
}
}
}
#if defined(USE_EPOLL)
static char *
epoll_event_to_str(struct epoll_event *evt)