diff --git a/libkqueue.vcxproj b/libkqueue.vcxproj
index 752b198..092e51d 100644
--- a/libkqueue.vcxproj
+++ b/libkqueue.vcxproj
@@ -50,6 +50,7 @@
MachineX86
true
Windows
+ msvcrtd.lib;Libcmtd.lib;%(AdditionalDependencies)
@@ -72,12 +73,14 @@
+
+
diff --git a/src/common/alloc.h b/src/common/alloc.h
index 56c3900..f82628c 100644
--- a/src/common/alloc.h
+++ b/src/common/alloc.h
@@ -34,7 +34,10 @@
*/
#include
-#include
+
+#ifndef _WIN32
+# include
+#endif
static __thread struct {
void **ac_cache; /* An array of reusable memory objects */
diff --git a/src/common/debug.h b/src/common/debug.h
index 00db529..983a907 100644
--- a/src/common/debug.h
+++ b/src/common/debug.h
@@ -19,7 +19,7 @@
#include
-extern int DEBUG;
+extern int DEBUG_ACTIVE;
extern char *DEBUG_IDENT;
#if defined(__linux__)
@@ -27,7 +27,7 @@ extern char *DEBUG_IDENT;
#elif defined(__sun)
# define THREAD_ID (pthread_self())
#elif defined(_WIN32)
-# define THREAD_ID (GetCurrentThreadId())
+# define THREAD_ID (int)(GetCurrentThreadId())
#else
# error Unsupported platform
#endif
@@ -35,19 +35,19 @@ extern char *DEBUG_IDENT;
#ifndef NDEBUG
#define dbg_puts(str) do { \
- if (DEBUG) \
+ if (DEBUG_ACTIVE) \
fprintf(stderr, "%s [%d]: %s(): %s\n", \
DEBUG_IDENT, THREAD_ID, __func__, str); \
} while (0)
#define dbg_printf(fmt,...) do { \
- if (DEBUG) \
+ if (DEBUG_ACTIVE) \
fprintf(stderr, "%s [%d]: %s(): "fmt"\n", \
DEBUG_IDENT, THREAD_ID, __func__, __VA_ARGS__); \
} while (0)
#define dbg_perror(str) do { \
- if (DEBUG) \
+ if (DEBUG_ACTIVE) \
fprintf(stderr, "%s [%d]: %s(): %s: %s (errno=%d)\n", \
DEBUG_IDENT, THREAD_ID, __func__, str, \
strerror(errno), errno); \
@@ -57,9 +57,9 @@ extern char *DEBUG_IDENT;
# if defined(_WIN32)
# define dbg_lasterror(str) do { \
- if (DEBUG) \
+ if (DEBUG_ACTIVE) \
fprintf(stderr, "%s: [%d] %s(): %s: (LastError=%d)\n", \
- THREAD_ID, __func__, str, GetLastError()); \
+ DEBUG_IDENT, THREAD_ID, __func__, str, (int)GetLastError()); \
} while (0)
# else
# define dbg_lasterror(str) ;
diff --git a/src/common/kevent.c b/src/common/kevent.c
index b207697..9e063d2 100644
--- a/src/common/kevent.c
+++ b/src/common/kevent.c
@@ -250,7 +250,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges,
return (-1);
}
- if (DEBUG) {
+ if (DEBUG_ACTIVE) {
myid = atomic_inc(&_kevent_counter);
dbg_printf("--- kevent %u --- (nchanges = %d, nevents = %d)", myid, nchanges, nevents);
} else {
@@ -291,7 +291,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges,
}
}
- if (DEBUG) {
+ if (DEBUG_ACTIVE) {
int n;
dbg_printf("(%u) returning %d events", myid, rv);
diff --git a/src/common/knote.c b/src/common/knote.c
index e8f8746..a43d2d4 100644
--- a/src/common/knote.c
+++ b/src/common/knote.c
@@ -19,6 +19,7 @@
#include
#include "private.h"
+
#include "alloc.h"
static void knote_free(struct filter *, struct knote *);
@@ -45,11 +46,15 @@ knote_new(void)
struct knote* res = malloc(sizeof(struct knote));
if(!res) return NULL;
+#ifdef _WIN32
+ pthread_mutex_init(&res->mtx, NULL);
+#else
if(pthread_mutex_init(&res->mtx, NULL)){
dbg_perror("pthread_mutex_init");
free(res);
return NULL;
}
+#endif
return res;
}
diff --git a/src/common/kqueue.c b/src/common/kqueue.c
index be6b91f..9c1c029 100644
--- a/src/common/kqueue.c
+++ b/src/common/kqueue.c
@@ -24,12 +24,20 @@
#include "private.h"
-int DEBUG = 0;
+int DEBUG_ACTIVE = 0;
char *DEBUG_IDENT = "KQ";
static unsigned int
get_fd_limit(void)
{
+#ifdef _WIN32
+ /* actually windows should be able to hold
+ way more, as they use HANDLEs for everything.
+ Still this number should still be sufficient for
+ the provided number of kqueue fds.
+ */
+ return 65536;
+#else
struct rlimit rlim;
if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
@@ -38,6 +46,7 @@ get_fd_limit(void)
} else {
return (rlim.rlim_max);
}
+#endif
}
static struct map *kqmap;
@@ -46,14 +55,22 @@ int CONSTRUCTOR
_libkqueue_init(void)
{
#ifdef NDEBUG
- DEBUG = 0;
+ DEBUG_ACTIVE = 0;
#elif _WIN32
/* Experimental port, always debug */
- DEBUG = 1;
+ DEBUG_ACTIVE = 1;
+# ifndef __GNUC__
+ /* Enable heap surveillance */
+ {
+ int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
+ tmpFlag |= _CRTDBG_CHECK_ALWAYS_DF;
+ _CrtSetDbgFlag(tmpFlag);
+ }
+# endif
#else
char *s = getenv("KQUEUE_DEBUG");
if (s != NULL && strlen(s) > 0)
- DEBUG = 1;
+ DEBUG_ACTIVE = 1;
#endif
kqmap = map_new(get_fd_limit()); // INT_MAX
diff --git a/src/common/map.c b/src/common/map.c
index 98e9360..50ba0cf 100644
--- a/src/common/map.c
+++ b/src/common/map.c
@@ -26,9 +26,18 @@ map_new(size_t len)
{
struct map *dst;
- dst = calloc(1, sizeof(*dst));
+ dst = calloc(1, sizeof(struct map));
if (dst == NULL)
return (NULL);
+#ifdef _WIN32
+ dst->data = calloc(len, sizeof(void*));
+ if(dst->data == NULL) {
+ dbg_perror("calloc()");
+ free(dst);
+ return NULL;
+ }
+ dst->len = len;
+#else
dst->data = mmap(NULL, len * sizeof(void *), PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_NORESERVE | MAP_ANON, -1, 0);
if (dst->data == MAP_FAILED) {
@@ -37,6 +46,7 @@ map_new(size_t len)
return (NULL);
}
dst->len = len;
+#endif
return (dst);
}
@@ -44,10 +54,10 @@ map_new(size_t len)
int
map_insert(struct map *m, int idx, void *ptr)
{
- if (slowpath(idx < 0 || idx > m->len))
+ if (slowpath(idx < 0 || idx > (int)m->len))
return (-1);
- if (atomic_cas(&(m->data[idx]), 0, ptr) == NULL) {
+ if (atomic_ptr_cas(&(m->data[idx]), 0, ptr) == NULL) {
dbg_printf("inserted %p in location %d", ptr, idx);
return (0);
} else {
@@ -61,10 +71,10 @@ map_insert(struct map *m, int idx, void *ptr)
int
map_remove(struct map *m, int idx, void *ptr)
{
- if (slowpath(idx < 0 || idx > m->len))
+ if (slowpath(idx < 0 || idx > (int)m->len))
return (-1);
- if (atomic_cas(&(m->data[idx]), ptr, 0) == NULL) {
+ if (atomic_ptr_cas(&(m->data[idx]), ptr, 0) == NULL) {
dbg_printf("removed %p from location %d", ptr, idx);
return (0);
} else {
@@ -78,10 +88,10 @@ map_replace(struct map *m, int idx, void *oldp, void *newp)
{
void *tmp;
- if (slowpath(idx < 0 || idx > m->len))
+ if (slowpath(idx < 0 || idx > (int)m->len))
return (-1);
- tmp = atomic_cas(&(m->data[idx]), oldp, newp);
+ tmp = atomic_ptr_cas(&(m->data[idx]), oldp, newp);
if (tmp == oldp) {
dbg_printf("replaced value %p in location %d with value %p",
oldp, idx, newp);
@@ -96,7 +106,7 @@ map_replace(struct map *m, int idx, void *oldp, void *newp)
void *
map_lookup(struct map *m, int idx)
{
- if (slowpath(idx < 0 || idx > m->len))
+ if (slowpath(idx < 0 || idx > (int)m->len))
return (NULL);
return m->data[idx];
@@ -108,13 +118,13 @@ map_delete(struct map *m, int idx)
void *oval;
void *nval;
- if (slowpath(idx < 0 || idx > m->len))
+ if (slowpath(idx < 0 || idx > (int)m->len))
return ((void *)-1);
/* Hopefully we aren't racing with another thread, but you never know.. */
do {
oval = m->data[idx];
- nval = atomic_cas(&(m->data[idx]), oval, NULL);
+ nval = atomic_ptr_cas(&(m->data[idx]), oval, NULL);
} while (nval != oval);
m->data[idx] = NULL;
diff --git a/src/common/private.h b/src/common/private.h
index 9de0f6f..c35cea6 100644
--- a/src/common/private.h
+++ b/src/common/private.h
@@ -35,6 +35,9 @@ struct evfilt_data;
#if defined(_WIN32)
# include "../windows/platform.h"
# include "../common/queue.h"
+# if !defined(NDEBUG) && !defined(__GNUC__)
+# include
+# endif
#elif defined(__linux__)
# include "../posix/platform.h"
# include "../linux/platform.h"
@@ -141,7 +144,15 @@ struct kqueue {
struct kqueue_vtable {
int (*kqueue_init)(struct kqueue *);
void (*kqueue_free)(struct kqueue *);
+ // @param timespec can be given as timeout
+ // @param int the number of events to wait for
+ // @param kqueue the queue to wait on
int (*kevent_wait)(struct kqueue *, int, const struct timespec *);
+ // @param kqueue the queue to look at
+ // @param int The number of events that should be ready
+ // @param kevent the structure to copy the events into
+ // @param int The number of events to copy
+ // @return the actual number of events copied
int (*kevent_copyout)(struct kqueue *, int, struct kevent *, int);
int (*filter_init)(struct kqueue *, struct filter *);
void (*filter_free)(struct kqueue *, struct filter *);
diff --git a/src/windows/platform.c b/src/windows/platform.c
index 3a95c33..a775e37 100644
--- a/src/windows/platform.c
+++ b/src/windows/platform.c
@@ -51,7 +51,9 @@ BOOL WINAPI DllMain(
break;
case DLL_PROCESS_DETACH:
+#if XXX
WSACleanup();
+#endif
break;
}
@@ -67,6 +69,11 @@ windows_kqueue_init(struct kqueue *kq)
return (-1);
}
+ if(filter_register_all(kq) < 0) {
+ CloseHandle(kq->kq_handle);
+ return (-1);
+ }
+
return (0);
}
@@ -78,7 +85,7 @@ windows_kqueue_free(struct kqueue *kq)
}
int
-windows_kevent_wait(struct kqueue *kq, const struct timespec *timeout)
+windows_kevent_wait(struct kqueue *kq, int no, const struct timespec *timeout)
{
int retval;
DWORD rv, timeout_ms;
@@ -96,7 +103,7 @@ windows_kevent_wait(struct kqueue *kq, const struct timespec *timeout)
}
/* Wait for an event */
- dbg_printf("waiting for %u events (timeout=%u ms)", kq->kq_filt_count, timeout_ms);
+ dbg_printf("waiting for %u events (timeout=%u ms)", kq->kq_filt_count, (unsigned int)timeout_ms);
rv = WaitForMultipleObjectsEx(kq->kq_filt_count, kq->kq_filt_handle, FALSE, timeout_ms, TRUE);
switch (rv) {
case WAIT_TIMEOUT:
@@ -121,6 +128,7 @@ windows_kevent_copyout(struct kqueue *kq, int nready,
struct kevent *eventlist, int nevents)
{
struct filter *filt;
+ struct knote* kn;
int rv;
/* KLUDGE: We are abusing the WAIT_FAILED constant to mean
@@ -129,8 +137,13 @@ windows_kevent_copyout(struct kqueue *kq, int nready,
if (kq->kq_filt_signalled == WAIT_FAILED)
return (0);
filt = kq->kq_filt_ref[kq->kq_filt_signalled];
+ kn = knote_lookup(filt, eventlist->ident);
+ if(kn == NULL) {
+ dbg_puts("knote_lookup failed");
+ return (-1);
+ }
kq->kq_filt_signalled = WAIT_FAILED;
- rv = filt->kf_copyout(filt, eventlist, nevents);
+ rv = filt->kf_copyout(eventlist, kn, filt);
if (rv < 0) {
dbg_puts("kevent_copyout failed");
return (-1);
diff --git a/src/windows/platform.h b/src/windows/platform.h
index 7af7739..18ee425 100644
--- a/src/windows/platform.h
+++ b/src/windows/platform.h
@@ -27,12 +27,12 @@
#include
#include
#include
-
-#pragma comment(lib, "Ws2_32.lib")
-/* The #define doesn't seem to work, but the #pragma does.. */
#define _CRT_SECURE_NO_WARNINGS 1
-#pragma warning( disable : 4996 )
+/* The #define doesn't seem to work, but the #pragma does.. */
+#ifdef _MSC_VER
+# pragma warning( disable : 4996 )
+#endif
#include "../../include/sys/event.h"
@@ -40,8 +40,17 @@
/*
* Atomic integer operations
*/
-#define atomic_inc InterlockedIncrement
-#define atomic_dec InterlockedDecrement
+#ifdef __GNUC__
+# 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)
+#else
+# define atomic_inc InterlockedIncrement
+# define atomic_dec InterlockedDecrement
+# define atomic_cas(p, oval, nval) InterlockedCompareExchange(p, nval, oval)
+# define atomic_ptr_cas(p, oval, nval) InterlockedCompareExchangePointer(p, nval, oval)
+#endif
/*
* Additional members of struct kqueue
@@ -62,12 +71,18 @@
#define FILTER_PLATFORM_SPECIFIC \
HANDLE kf_event_handle
+/*
+ * Some datatype forward declarations
+ */
+struct filter;
+struct kqueue;
+
/*
* Hooks and prototypes
*/
int windows_kqueue_init(struct kqueue *);
void windows_kqueue_free(struct kqueue *);
-int windows_kevent_wait(struct kqueue *, const struct timespec *);
+int windows_kevent_wait(struct kqueue *, int, const struct timespec *);
int windows_kevent_copyout(struct kqueue *, int, struct kevent *, int);
int windows_filter_init(struct kqueue *, struct filter *);
void windows_filter_free(struct kqueue *, struct filter *);
@@ -78,17 +93,29 @@ void windows_filter_free(struct kqueue *, struct filter *);
*/
#define CONSTRUCTOR
+/*
+ * GCC-compatible branch prediction macros
+ */
+#ifdef __GNUC__
+# define fastpath(x) __builtin_expect((x), 1)
+# define slowpath(x) __builtin_expect((x), 0)
+#else
+# define fastpath(x) (x)
+# define slowpath(x) (x)
+#endif
+
/* Function visibility macros */
#define VISIBLE __declspec(dllexport)
#define HIDDEN
-#ifndef __func__
+#if !defined(__func__) && !defined(__GNUC__)
#define __func__ __FUNCDNAME__
#endif
#define snprintf _snprintf
#define ssize_t SSIZE_T
#define sleep(x) Sleep((x) * 1000)
+#define inline __inline
/* For POSIX compatibility when compiling, not for actual use */
typedef int socklen_t;
@@ -98,7 +125,9 @@ typedef int pthread_t;
typedef int sigset_t;
typedef int pid_t;
-#define __thread __declspec(thread)
+#ifndef __GNUC__
+# define __thread __declspec(thread)
+#endif
/* Emulation of pthreads mutex functionality */
#define PTHREAD_PROCESS_SHARED 1
@@ -116,6 +145,7 @@ typedef CRITICAL_SECTION pthread_rwlock_t;
#define pthread_spin_unlock _cs_unlock
#define pthread_spin_init(x,y) _cs_init((x))
#define pthread_mutex_init(x,y) _cs_init((x))
+#define pthread_mutex_destroy(x)
#define pthread_rwlock_rdlock _cs_lock
#define pthread_rwlock_wrlock _cs_lock
#define pthread_rwlock_unlock _cs_unlock
diff --git a/src/windows/timer.c b/src/windows/timer.c
index 39a5df9..d06266d 100644
--- a/src/windows/timer.c
+++ b/src/windows/timer.c
@@ -54,62 +54,16 @@ evfilt_timer_destroy(struct filter *filt)
}
int
-evfilt_timer_copyout(struct filter *filt,
- struct kevent *dst,
- int nevents)
+evfilt_timer_copyout(struct kevent* dst, struct knote* src, void* ptr)
{
-#if FIXME
- struct epoll_event epevt[MAX_KEVENT];
- struct epoll_event *ev;
- struct knote *kn;
- uint64_t expired;
- int i, nret;
- ssize_t n;
+ memcpy(dst, &src->kev, sizeof(struct kevent*));
+ // TODO: Timer error handling
+
+ /* We have no way to determine the number of times
+ the timer triggered, thus we assume it was only once
+ */
+ dst->data = 1;
- for (;;) {
- nret = epoll_wait(filt->kf_pfd, &epevt[0], nevents, 0);
- if (nret < 0) {
- if (errno == EINTR)
- continue;
- dbg_perror("epoll_wait");
- return (-1);
- } else {
- break;
- }
- }
-
- for (i = 0, nevents = 0; i < nret; i++) {
- ev = &epevt[i];
- /* TODO: put in generic debug.c: epoll_event_dump(ev); */
- kn = ev->data.ptr;
- memcpy(dst, &kn->kev, sizeof(*dst));
- if (ev->events & EPOLLERR)
- dst->fflags = 1; /* FIXME: Return the actual timer error */
-
- /* On return, data contains the number of times the
- timer has been trigered.
- */
- n = read(kn->data.pfd, &expired, sizeof(expired));
- if (n < 0 || n < sizeof(expired)) {
- dbg_puts("invalid read from timerfd");
- expired = 1; /* Fail gracefully */
- }
- dst->data = expired;
-
- if (kn->kev.flags & EV_DISPATCH) {
- KNOTE_DISABLE(kn);
- ktimer_delete(filt, kn);
- } else if (kn->kev.flags & EV_ONESHOT) {
- ktimer_delete(filt, kn);
- knote_free(filt, kn);
- }
-
- nevents++;
- dst++;
- }
-
- return (nevents);
-#endif
return (0);
}
diff --git a/test/common.h b/test/common.h
index 720cc58..6405269 100644
--- a/test/common.h
+++ b/test/common.h
@@ -49,9 +49,8 @@
#include
#include "config.h"
#else
-#include "../include/sys/event.h"
-#include "../src/windows/platform.h"
-#pragma comment(lib, "../Debug/libkqueue.lib")
+# include "../include/sys/event.h"
+# include "../src/windows/platform.h"
#endif
diff --git a/test/kqtest.vcxproj b/test/kqtest.vcxproj
index 876aac8..30043fe 100644
--- a/test/kqtest.vcxproj
+++ b/test/kqtest.vcxproj
@@ -50,6 +50,7 @@
MachineX86
true
Console
+ wsock32.lib;%(AdditionalDependencies)
@@ -82,6 +83,11 @@
+
+
+ {74c1eceb-1d2b-2740-8a0b-9ec65aa06eab}
+
+
diff --git a/test/main.c b/test/main.c
index e8078f0..ac5dc3a 100644
--- a/test/main.c
+++ b/test/main.c
@@ -14,9 +14,6 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include
-
-
#include "common.h"
struct unit_test {
diff --git a/test/read.c b/test/read.c
index 0ff3cf1..2566a17 100644
--- a/test/read.c
+++ b/test/read.c
@@ -340,7 +340,7 @@ test_kevent_regular_file(void)
/* Set file position to EOF-1 */
kev2->data--;
if ((curpos = lseek(fd, kev2->data, SEEK_SET)) != kev2->data) {
- printf("seek to %zu failed with rv=%zu\n", kev2->data, curpos);
+ printf("seek to %u failed with rv=%lu\n", kev2->data, curpos);
abort();
}
@@ -348,7 +348,7 @@ test_kevent_regular_file(void)
(void) kevent_get(kqfd);
kev2->data = curpos + 1;
if ((curpos = lseek(fd, kev2->data, SEEK_SET)) != kev2->data) {
- printf("seek to %zu failed with rv=%zu\n", kev2->data, curpos);
+ printf("seek to %u failed with rv=%lu\n", kev2->data, curpos);
abort();
}