From d2119e4c873e1b6132590e27659db3d96a9864d3 Mon Sep 17 00:00:00 2001 From: Dhamoder Nalla Date: Mon, 5 Aug 2024 22:22:43 -0500 Subject: [PATCH] replace undocument keyedevent APIs with documented sync APIs --- wepoll.c | 100 +++++++++++++++++++++++++++---------------------------- wepoll.h | 4 +-- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/wepoll.c b/wepoll.c index 186d3f2..06839b8 100644 --- a/wepoll.c +++ b/wepoll.c @@ -47,7 +47,7 @@ enum EPOLL_EVENTS { EPOLLWRBAND = (int) (1U << 9), EPOLLMSG = (int) (1U << 10), /* Never reported. */ EPOLLRDHUP = (int) (1U << 13), - EPOLLONESHOT = (int) (1U << 31) + EPOLLONESHOT = (int) (1U << 30) }; #define EPOLLIN (1U << 0) @@ -61,7 +61,7 @@ enum EPOLL_EVENTS { #define EPOLLWRBAND (1U << 9) #define EPOLLMSG (1U << 10) #define EPOLLRDHUP (1U << 13) -#define EPOLLONESHOT (1U << 31) +#define EPOLLONESHOT (1U << 30) #define EPOLL_CTL_ADD 1 #define EPOLL_CTL_MOD 2 @@ -197,11 +197,6 @@ typedef struct _OBJECT_ATTRIBUTES { #define FILE_OPEN 0x00000001UL #endif -#define KEYEDEVENT_WAIT 0x00000001UL -#define KEYEDEVENT_WAKE 0x00000002UL -#define KEYEDEVENT_ALL_ACCESS \ - (STANDARD_RIGHTS_REQUIRED | KEYEDEVENT_WAIT | KEYEDEVENT_WAKE) - #define NT_NTDLL_IMPORT_LIST(X) \ X(NTSTATUS, \ NTAPI, \ @@ -225,14 +220,6 @@ typedef struct _OBJECT_ATTRIBUTES { PVOID EaBuffer, \ ULONG EaLength)) \ \ - X(NTSTATUS, \ - NTAPI, \ - NtCreateKeyedEvent, \ - (PHANDLE KeyedEventHandle, \ - ACCESS_MASK DesiredAccess, \ - POBJECT_ATTRIBUTES ObjectAttributes, \ - ULONG Flags)) \ - \ X(NTSTATUS, \ NTAPI, \ NtDeviceIoControlFile, \ @@ -247,22 +234,6 @@ typedef struct _OBJECT_ATTRIBUTES { PVOID OutputBuffer, \ ULONG OutputBufferLength)) \ \ - X(NTSTATUS, \ - NTAPI, \ - NtReleaseKeyedEvent, \ - (HANDLE KeyedEventHandle, \ - PVOID KeyValue, \ - BOOLEAN Alertable, \ - PLARGE_INTEGER Timeout)) \ - \ - X(NTSTATUS, \ - NTAPI, \ - NtWaitForKeyedEvent, \ - (HANDLE KeyedEventHandle, \ - PVOID KeyValue, \ - BOOLEAN Alertable, \ - PLARGE_INTEGER Timeout)) \ - \ X(ULONG, WINAPI, RtlNtStatusToDosError, (NTSTATUS Status)) #define X(return_type, attributes, name, parameters) \ @@ -461,7 +432,7 @@ WEPOLL_INTERNAL port_state_t* port_state_from_handle_tree_node( WEPOLL_INTERNAL ts_tree_node_t* port_state_to_handle_tree_node( port_state_t* port_state); -/* The reflock is a special kind of lock that normally prevents a chunk of +/* A reflock is a special kind of lock that normally prevents a chunk of * memory from being freed, but does allow the chunk of memory to eventually be * released in a coordinated fashion. * @@ -474,13 +445,15 @@ WEPOLL_INTERNAL ts_tree_node_t* port_state_to_handle_tree_node( * "destroy" returns, the calling thread may assume that no other threads have * a reference to the lock. * - * Attemmpting to lock or destroy a lock after reflock_unref_and_destroy() has + * Attempting to lock or destroy a lock after reflock_unref_and_destroy() has * been called is invalid and results in undefined behavior. Therefore the user * should use another lock to guarantee that this can't happen. */ typedef struct reflock { volatile long state; /* 32-bit Interlocked APIs operate on `long` values. */ + CONDITION_VARIABLE cv_signal; + CONDITION_VARIABLE cv_await; } reflock_t; WEPOLL_INTERNAL int reflock_global_init(void); @@ -1520,35 +1493,60 @@ bool queue_is_enqueued(const queue_node_t* node) { #define REFLOCK__REF ((long) 0x00000001UL) #define REFLOCK__REF_MASK ((long) 0x0fffffffUL) #define REFLOCK__DESTROY ((long) 0x10000000UL) -#define REFLOCK__DESTROY_MASK ((long) 0xf0000000UL) -#define REFLOCK__POISON ((long) 0x300dead0UL) +#define REFLOCK__DESTROY_MASK ((long) 0x10000000UL) +#define REFLOCK__SIGNAL ((long) 0x20000000UL) +#define REFLOCK__SIGNAL_MASK ((long) 0x20000000UL) +#define REFLOCK__AWAIT ((long) 0x40000000UL) +#define REFLOCK__AWAIT_MASK ((long) 0x40000000UL) +#define REFLOCK__POISON ((long) 0x800dead0UL) -static HANDLE reflock__keyed_event = NULL; +static CRITICAL_SECTION signalMutex; int reflock_global_init(void) { - NTSTATUS status = NtCreateKeyedEvent( - &reflock__keyed_event, KEYEDEVENT_ALL_ACCESS, NULL, 0); - if (status != STATUS_SUCCESS) - return_set_error(-1, RtlNtStatusToDosError(status)); + InitializeCriticalSection(&signalMutex); return 0; } void reflock_init(reflock_t* reflock) { reflock->state = 0; + InitializeConditionVariable(&reflock->cv_signal); + InitializeConditionVariable(&reflock->cv_await); } -static void reflock__signal_event(void* address) { - NTSTATUS status = - NtReleaseKeyedEvent(reflock__keyed_event, address, FALSE, NULL); - if (status != STATUS_SUCCESS) +static void reflock__signal_event(reflock_t* reflock) { + BOOL status = TRUE; + + EnterCriticalSection(&signalMutex); + long state = InterlockedOr(&reflock->state, REFLOCK__SIGNAL); + while ((reflock->state & REFLOCK__AWAIT_MASK) == 0) { + status = SleepConditionVariableCS(&reflock->cv_signal, &signalMutex, INFINITE); + } + LeaveCriticalSection(&signalMutex); + + if (status != TRUE) abort(); + + /* At most one reflock__await_event call per reflock. */ + WakeConditionVariable(&reflock->cv_await); + unused_var(state); } -static void reflock__await_event(void* address) { - NTSTATUS status = - NtWaitForKeyedEvent(reflock__keyed_event, address, FALSE, NULL); - if (status != STATUS_SUCCESS) +static void reflock__await_event(reflock_t* reflock) { + BOOL status = TRUE; + + EnterCriticalSection(&signalMutex); + long state = InterlockedOr(&reflock->state, REFLOCK__AWAIT); + while ((reflock->state & REFLOCK__SIGNAL_MASK) == 0) { + status = SleepConditionVariableCS(&reflock->cv_await, &signalMutex, INFINITE); + } + LeaveCriticalSection(&signalMutex); + + if (status != TRUE) abort(); + + /* Multiple threads could be waiting. */ + WakeAllConditionVariable(&reflock->cv_signal); + unused_var(state); } void reflock_ref(reflock_t* reflock) { @@ -1565,7 +1563,8 @@ void reflock_unref(reflock_t* reflock) { /* Verify that the lock was referenced and not already destroyed. */ assert((state & REFLOCK__DESTROY_MASK & ~REFLOCK__DESTROY) == 0); - if (state == REFLOCK__DESTROY) + if ((state & REFLOCK__DESTROY_MASK) == REFLOCK__DESTROY && + (state & REFLOCK__REF_MASK) == 0) reflock__signal_event(reflock); } @@ -1581,7 +1580,8 @@ void reflock_unref_and_destroy(reflock_t* reflock) { reflock__await_event(reflock); state = InterlockedExchange(&reflock->state, REFLOCK__POISON); - assert(state == REFLOCK__DESTROY); + assert((state & REFLOCK__DESTROY_MASK) == REFLOCK__DESTROY); + assert((state & REFLOCK__REF_MASK) == 0); } #define SOCK__KNOWN_EPOLL_EVENTS \ diff --git a/wepoll.h b/wepoll.h index daf6bdb..5d30fa1 100644 --- a/wepoll.h +++ b/wepoll.h @@ -50,7 +50,7 @@ enum EPOLL_EVENTS { EPOLLWRBAND = (int) (1U << 9), EPOLLMSG = (int) (1U << 10), /* Never reported. */ EPOLLRDHUP = (int) (1U << 13), - EPOLLONESHOT = (int) (1U << 31) + EPOLLONESHOT = (int) (1U << 30) }; #define EPOLLIN (1U << 0) @@ -64,7 +64,7 @@ enum EPOLL_EVENTS { #define EPOLLWRBAND (1U << 9) #define EPOLLMSG (1U << 10) #define EPOLLRDHUP (1U << 13) -#define EPOLLONESHOT (1U << 31) +#define EPOLLONESHOT (1U << 30) #define EPOLL_CTL_ADD 1 #define EPOLL_CTL_MOD 2