mirror of
https://github.com/darlinghq/darling-libkqueue.git
synced 2024-11-23 11:49:50 +00:00
win32 timer filter mostly done, improved windows_kevent_wait()
git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@404 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7
This commit is contained in:
parent
29a754d3f8
commit
e814dc5c6d
29
libkqueue.sln
Normal file
29
libkqueue.sln
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||||
|
# Visual C++ Express 2010
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libkqueue", "libkqueue.vcxproj", "{A29A2A03-DD72-6A48-80FB-43EE0B1A16E7}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kqtest", "test\kqtest.vcxproj", "{7578F752-17DD-C6A5-C895-A00098131EEA}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{A29A2A03-DD72-6A48-80FB-43EE0B1A16E7} = {A29A2A03-DD72-6A48-80FB-43EE0B1A16E7}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{A29A2A03-DD72-6A48-80FB-43EE0B1A16E7}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{A29A2A03-DD72-6A48-80FB-43EE0B1A16E7}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{A29A2A03-DD72-6A48-80FB-43EE0B1A16E7}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{A29A2A03-DD72-6A48-80FB-43EE0B1A16E7}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{7578F752-17DD-C6A5-C895-A00098131EEA}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{7578F752-17DD-C6A5-C895-A00098131EEA}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{7578F752-17DD-C6A5-C895-A00098131EEA}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{7578F752-17DD-C6A5-C895-A00098131EEA}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
@ -73,6 +73,7 @@
|
|||||||
<ClCompile Include="src\common\knote.c" />
|
<ClCompile Include="src\common\knote.c" />
|
||||||
<ClCompile Include="src\common\kqueue.c" />
|
<ClCompile Include="src\common\kqueue.c" />
|
||||||
<ClCompile Include="src\windows\platform.c" />
|
<ClCompile Include="src\windows\platform.c" />
|
||||||
|
<ClCompile Include="src\windows\timer.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="include\kqueue.h" />
|
<ClInclude Include="include\kqueue.h" />
|
||||||
|
@ -98,6 +98,7 @@ struct knote {
|
|||||||
} vnode;
|
} vnode;
|
||||||
timer_t timerid;
|
timer_t timerid;
|
||||||
pthread_t tid; /* Used by posix/timer.c */
|
pthread_t tid; /* Used by posix/timer.c */
|
||||||
|
void *handle; /* Used by win32 filters */
|
||||||
} data;
|
} data;
|
||||||
TAILQ_ENTRY(knote) event_ent; /* Used by filter->kf_event */
|
TAILQ_ENTRY(knote) event_ent; /* Used by filter->kf_event */
|
||||||
RB_ENTRY(knote) kntree_ent; /* Used by filter->kntree */
|
RB_ENTRY(knote) kntree_ent; /* Used by filter->kntree */
|
||||||
|
@ -22,7 +22,6 @@ const struct filter evfilt_vnode = EVFILT_NOTIMPL;
|
|||||||
const struct filter evfilt_signal = EVFILT_NOTIMPL;
|
const struct filter evfilt_signal = EVFILT_NOTIMPL;
|
||||||
const struct filter evfilt_write = EVFILT_NOTIMPL;
|
const struct filter evfilt_write = EVFILT_NOTIMPL;
|
||||||
const struct filter evfilt_read = EVFILT_NOTIMPL;
|
const struct filter evfilt_read = EVFILT_NOTIMPL;
|
||||||
const struct filter evfilt_timer = EVFILT_NOTIMPL;
|
|
||||||
const struct filter evfilt_user = EVFILT_NOTIMPL;
|
const struct filter evfilt_user = EVFILT_NOTIMPL;
|
||||||
|
|
||||||
const struct kqueue_vtable kqops = {
|
const struct kqueue_vtable kqops = {
|
||||||
@ -96,8 +95,9 @@ windows_kevent_wait(struct kqueue *kq, const struct timespec *timeout)
|
|||||||
timeout_ms += timeout->tv_nsec / 1000000;
|
timeout_ms += timeout->tv_nsec / 1000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEADWOOD
|
||||||
/* Wait for an event */
|
/* Wait for an event */
|
||||||
dbg_printf("waiting for events (timeout=%u ms)", timeout_ms);
|
dbg_printf("waiting for %u events (timeout=%u ms)", kq->kq_filt_count, timeout_ms);
|
||||||
rv = WaitForMultipleObjects(kq->kq_filt_count, kq->kq_filt_handle, FALSE, timeout_ms);
|
rv = WaitForMultipleObjects(kq->kq_filt_count, kq->kq_filt_handle, FALSE, timeout_ms);
|
||||||
switch (rv) {
|
switch (rv) {
|
||||||
case WAIT_TIMEOUT:
|
case WAIT_TIMEOUT:
|
||||||
@ -106,14 +106,23 @@ windows_kevent_wait(struct kqueue *kq, const struct timespec *timeout)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case WAIT_FAILED:
|
case WAIT_FAILED:
|
||||||
dbg_perror("WaitForMultipleEvents()");
|
dbg_lasterror("WaitForMultipleEvents()");
|
||||||
/* TODO: Use GetLastError() for details */
|
|
||||||
retval = -1;
|
retval = -1;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
kq->kq_filt_signalled = rv;
|
kq->kq_filt_signalled = rv;
|
||||||
retval = 1;
|
retval = 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rv = SleepEx(timeout_ms, TRUE);
|
||||||
|
if (rv == 0) {
|
||||||
|
dbg_puts("timeout reached");
|
||||||
|
retval = 0;
|
||||||
|
} else {
|
||||||
|
dbg_lasterror("SleepEx()");
|
||||||
|
retval = -1;
|
||||||
|
}
|
||||||
|
|
||||||
return (retval);
|
return (retval);
|
||||||
}
|
}
|
||||||
@ -143,6 +152,8 @@ windows_kevent_copyout(struct kqueue *kq, int nready,
|
|||||||
int
|
int
|
||||||
windows_filter_init(struct kqueue *kq, struct filter *kf)
|
windows_filter_init(struct kqueue *kq, struct filter *kf)
|
||||||
{
|
{
|
||||||
|
return (0); //XXX-FIXME TESTING
|
||||||
|
|
||||||
kf->kf_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
|
kf->kf_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
if (kf->kf_event_handle == NULL) {
|
if (kf->kf_event_handle == NULL) {
|
||||||
dbg_perror("CreateEvent()");
|
dbg_perror("CreateEvent()");
|
||||||
|
@ -36,6 +36,19 @@
|
|||||||
|
|
||||||
#include "../../include/sys/event.h"
|
#include "../../include/sys/event.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Debugging macros
|
||||||
|
*/
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#define dbg_lasterror(str) do { \
|
||||||
|
if (KQUEUE_DEBUG) \
|
||||||
|
fprintf(stderr, "KQ: [%d] %s(): %s: (LastError=%d)\n", \
|
||||||
|
THREAD_ID, __func__, str, GetLastError()); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Atomic integer operations
|
* Atomic integer operations
|
||||||
*/
|
*/
|
||||||
|
@ -16,97 +16,49 @@
|
|||||||
|
|
||||||
#include "../common/private.h"
|
#include "../common/private.h"
|
||||||
|
|
||||||
#ifndef NDEBUG
|
/* Convert milliseconds into negative increments of 100-nanoseconds */
|
||||||
static char *
|
|
||||||
itimerspec_dump(struct itimerspec *ts)
|
|
||||||
{
|
|
||||||
static char __thread buf[1024];
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf),
|
|
||||||
"itimer: [ interval=%lu s %lu ns, next expire=%lu s %lu ns ]",
|
|
||||||
ts->it_interval.tv_sec,
|
|
||||||
ts->it_interval.tv_nsec,
|
|
||||||
ts->it_value.tv_sec,
|
|
||||||
ts->it_value.tv_nsec
|
|
||||||
);
|
|
||||||
|
|
||||||
return (buf);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Convert milliseconds into seconds+nanoseconds */
|
|
||||||
static void
|
static void
|
||||||
convert_msec_to_itimerspec(struct itimerspec *dst, int src, int oneshot)
|
convert_msec_to_filetime(LARGE_INTEGER *dst, int src)
|
||||||
{
|
{
|
||||||
time_t sec, nsec;
|
dst->QuadPart = -((int64_t) src * 1000 * 10);
|
||||||
|
|
||||||
sec = src / 1000;
|
|
||||||
nsec = (src % 1000) * 1000000;
|
|
||||||
|
|
||||||
/* Set the interval */
|
|
||||||
if (oneshot) {
|
|
||||||
dst->it_interval.tv_sec = 0;
|
|
||||||
dst->it_interval.tv_nsec = 0;
|
|
||||||
} else {
|
|
||||||
dst->it_interval.tv_sec = sec;
|
|
||||||
dst->it_interval.tv_nsec = nsec;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the initial expiration */
|
|
||||||
dst->it_value.tv_sec = sec;
|
|
||||||
dst->it_value.tv_nsec = nsec;
|
|
||||||
dbg_printf("%s", itimerspec_dump(dst));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ktimer_delete(struct filter *filt, struct knote *kn)
|
ktimer_delete(struct filter *filt, struct knote *kn)
|
||||||
{
|
{
|
||||||
int rv = 0;
|
if (kn->data.handle == NULL)
|
||||||
|
|
||||||
if (kn->data.pfd == -1)
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
dbg_printf("removing timerfd %d from %d", kn->data.pfd, filt->kf_pfd);
|
if (!CancelWaitableTimer(kn->data.handle)) {
|
||||||
if (epoll_ctl(filt->kf_pfd, EPOLL_CTL_DEL, kn->data.pfd, NULL) < 0) {
|
dbg_lasterror("CancelWaitableTimer()");
|
||||||
dbg_printf("epoll_ctl(2): %s", strerror(errno));
|
return (-1);
|
||||||
rv = -1;
|
}
|
||||||
}
|
if (!CloseHandle(kn->data.handle)) {
|
||||||
if (close(kn->data.pfd) < 0) {
|
dbg_lasterror("CloseHandle()");
|
||||||
dbg_printf("close(2): %s", strerror(errno));
|
return (-1);
|
||||||
rv = -1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
kn->data.pfd = -1;
|
kn->data.handle = NULL;
|
||||||
return (rv);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
evfilt_timer_init(struct filter *filt)
|
evfilt_timer_init(struct filter *filt)
|
||||||
{
|
{
|
||||||
filt->kf_pfd = epoll_create(1);
|
|
||||||
if (filt->kf_pfd < 0)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
dbg_printf("timer epollfd = %d", filt->kf_pfd);
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
evfilt_timer_destroy(struct filter *filt)
|
evfilt_timer_destroy(struct filter *filt)
|
||||||
{
|
{
|
||||||
close (filt->kf_pfd);//LAME
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: This entire function is copy+pasted from socket.c
|
|
||||||
with minor changes for timerfds.
|
|
||||||
Perhaps it could be refactored into a generic epoll_copyout()
|
|
||||||
that calls custom per-filter actions.
|
|
||||||
*/
|
|
||||||
int
|
int
|
||||||
evfilt_timer_copyout(struct filter *filt,
|
evfilt_timer_copyout(struct filter *filt,
|
||||||
struct kevent *dst,
|
struct kevent *dst,
|
||||||
int nevents)
|
int nevents)
|
||||||
{
|
{
|
||||||
|
#if FIXME
|
||||||
struct epoll_event epevt[MAX_KEVENT];
|
struct epoll_event epevt[MAX_KEVENT];
|
||||||
struct epoll_event *ev;
|
struct epoll_event *ev;
|
||||||
struct knote *kn;
|
struct knote *kn;
|
||||||
@ -157,41 +109,35 @@ evfilt_timer_copyout(struct filter *filt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (nevents);
|
return (nevents);
|
||||||
|
#endif
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
evfilt_timer_knote_create(struct filter *filt, struct knote *kn)
|
evfilt_timer_knote_create(struct filter *filt, struct knote *kn)
|
||||||
{
|
{
|
||||||
struct epoll_event ev;
|
HANDLE th;
|
||||||
struct itimerspec ts;
|
LARGE_INTEGER liDueTime;
|
||||||
int tfd;
|
|
||||||
|
|
||||||
kn->kev.flags |= EV_CLEAR;
|
kn->kev.flags |= EV_CLEAR;
|
||||||
|
|
||||||
tfd = timerfd_create(CLOCK_MONOTONIC, 0);
|
th = CreateWaitableTimer(NULL, FALSE, NULL);
|
||||||
if (tfd < 0) {
|
if (th == NULL) {
|
||||||
dbg_printf("timerfd_create(2): %s", strerror(errno));
|
dbg_lasterror("CreateWaitableTimer()");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
dbg_printf("created timerfd %d", tfd);
|
dbg_printf("created timer handle %p", th);
|
||||||
|
|
||||||
convert_msec_to_itimerspec(&ts, kn->kev.data, kn->kev.flags & EV_ONESHOT);
|
convert_msec_to_filetime(&liDueTime, kn->kev.data);
|
||||||
if (timerfd_settime(tfd, 0, &ts, NULL) < 0) {
|
|
||||||
dbg_printf("timerfd_settime(2): %s", strerror(errno));
|
// XXX-FIXME add completion routine to this call
|
||||||
close(tfd);
|
if (!SetWaitableTimer(th, &liDueTime, (kn->kev.flags & EV_ONESHOT), NULL, NULL, FALSE)) {
|
||||||
|
dbg_lasterror("SetWaitableTimer()");
|
||||||
|
CloseHandle(th);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&ev, 0, sizeof(ev));
|
kn->data.handle = th;
|
||||||
ev.events = EPOLLIN;
|
|
||||||
ev.data.ptr = kn;
|
|
||||||
if (epoll_ctl(filt->kf_pfd, EPOLL_CTL_ADD, tfd, &ev) < 0) {
|
|
||||||
dbg_printf("epoll_ctl(2): %d", errno);
|
|
||||||
close(tfd);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
kn->data.pfd = tfd;
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
test/kqtest.sln
Normal file
20
test/kqtest.sln
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||||
|
# Visual C++ Express 2010
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kqtest", "kqtest.vcxproj", "{7578F752-17DD-C6A5-C895-A00098131EEA}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{7578F752-17DD-C6A5-C895-A00098131EEA}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{7578F752-17DD-C6A5-C895-A00098131EEA}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{7578F752-17DD-C6A5-C895-A00098131EEA}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{7578F752-17DD-C6A5-C895-A00098131EEA}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
@ -144,15 +144,16 @@ int
|
|||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct unit_test tests[] = {
|
struct unit_test tests[] = {
|
||||||
{ "socket", 1, test_evfilt_read },
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
{ "socket", 1, test_evfilt_read },
|
||||||
|
|
||||||
{ "signal", 1, test_evfilt_signal },
|
{ "signal", 1, test_evfilt_signal },
|
||||||
#endif
|
#endif
|
||||||
#if FIXME
|
#if FIXME
|
||||||
{ "proc", 1, test_evfilt_proc },
|
{ "proc", 1, test_evfilt_proc },
|
||||||
#endif
|
#endif
|
||||||
{ "vnode", 1, test_evfilt_vnode },
|
{ "timer", 1, test_evfilt_timer },
|
||||||
{ "timer", 1, test_evfilt_timer },
|
{ "vnode", 1, test_evfilt_vnode },
|
||||||
#if HAVE_EVFILT_USER
|
#if HAVE_EVFILT_USER
|
||||||
{ "user", 1, test_evfilt_user },
|
{ "user", 1, test_evfilt_user },
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user