Made libkqueue compile on windows again - functionality still broken on this platform

git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@473 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7
This commit is contained in:
marius 2011-04-13 17:35:34 +00:00
parent 0abf2a781a
commit 9abd0fc49c
15 changed files with 146 additions and 98 deletions

View File

@ -50,6 +50,7 @@
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<AdditionalDependencies>msvcrtd.lib;Libcmtd.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -72,12 +73,14 @@
<ClCompile Include="src\common\kevent.c" />
<ClCompile Include="src\common\knote.c" />
<ClCompile Include="src\common\kqueue.c" />
<ClCompile Include="src\common\map.c" />
<ClCompile Include="src\windows\platform.c" />
<ClCompile Include="src\windows\timer.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\kqueue.h" />
<ClInclude Include="include\sys\event.h" />
<ClInclude Include="src\common\debug.h" />
<ClInclude Include="src\common\private.h" />
<ClInclude Include="src\common\queue.h" />
<ClInclude Include="src\common\tree.h" />

View File

@ -34,7 +34,10 @@
*/
#include <stdlib.h>
#ifndef _WIN32
# include <unistd.h>
#endif
static __thread struct {
void **ac_cache; /* An array of reusable memory objects */

View File

@ -19,7 +19,7 @@
#include <assert.h>
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) ;

View File

@ -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);

View File

@ -19,6 +19,7 @@
#include <sys/types.h>
#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;
}

View File

@ -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

View File

@ -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;

View File

@ -35,6 +35,9 @@ struct evfilt_data;
#if defined(_WIN32)
# include "../windows/platform.h"
# include "../common/queue.h"
# if !defined(NDEBUG) && !defined(__GNUC__)
# include <crtdbg.h>
# 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 *);

View File

@ -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);

View File

@ -28,11 +28,11 @@
#include <stdio.h>
#include <fcntl.h>
#pragma comment(lib, "Ws2_32.lib")
/* The #define doesn't seem to work, but the #pragma does.. */
#define _CRT_SECURE_NO_WARNINGS 1
/* 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
*/
#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;
#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

View File

@ -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
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.
/* We have no way to determine the number of times
the timer triggered, thus we assume it was only once
*/
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;
dst->data = 1;
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);
}

View File

@ -51,7 +51,6 @@
#else
# include "../include/sys/event.h"
# include "../src/windows/platform.h"
#pragma comment(lib, "../Debug/libkqueue.lib")
#endif

View File

@ -50,6 +50,7 @@
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>wsock32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -82,6 +83,11 @@
<ItemGroup>
<None Include="config.inc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\libkqueue.vcxproj">
<Project>{74c1eceb-1d2b-2740-8a0b-9ec65aa06eab}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@ -14,9 +14,6 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include "common.h"
struct unit_test {

View File

@ -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();
}