win32: Thoroughly test for usability of WakeByAddress

This commit is contained in:
Douglas Katzman 2020-09-01 11:44:17 -04:00
parent 544548c21c
commit 68a703e843
3 changed files with 57 additions and 13 deletions

View file

@ -7,6 +7,10 @@
# provided with absolutely no warranty. See the COPYING and CREDITS
# files for more information.
# it is illogical that this makefile pulls in Makefile.features,
# which is presumed not to exist, and which when it does exist causes
# confusion as to what flags should be added in for a generic C compile.
# Why do we do this???
-include genesis/Makefile.features
-include Config

View file

@ -6,29 +6,26 @@ cd ./tools-for-build > /dev/null
# Assumes the presence of $1-test.c, which when built and
# run should return with 104 if the feature is present.
# We presumes that the build machine matches the target machine
# in terms of a whether each feature presence test should pass.
featurep() {
bin="$1-test"
featurename=${2:-$1}
rm -f $bin
$GNUMAKE $bin -I ../src/runtime > /dev/null 2>&1 && echo "input" | ./$bin> /dev/null 2>&1
if [ "$?" -eq 104 ]
then
printf " :$1"
printf " :$featurename"
fi
rm -f $bin
}
# Adding a nonexistent link library to Config.*-win32 will fail,
# so this needs its own recipe to detect the library.
# so we pass -lSynchronization to the featurep test specifically
# and not in the general make rule.
# It will get added in by Config.*-win32 only if LISP_FEATURE_SB_FUTEX.
if [ "$sbcl_os" = win32 ] ; then
bin=os-provides-wakebyaddr-test
rm -f $bin
# pass -f /dev/null to use only builtin Make recipes
LOADLIBES=-lSynchronization $GNUMAKE -f /dev/null $bin > /dev/null 2>&1
if [ "$?" -eq 0 ]
then
printf " :sb-futex"
fi
rm -f $bin
LOADLIBES=-lSynchronization featurep os-provides-wakebyaddr sb-futex
fi
# KLUDGE: ppc/darwin dlopen is special cased in make-config.sh, as

View file

@ -1,7 +1,50 @@
#include <windows.h>
int mutex_word = 0;
int expect = 9;
DWORD waiter(void* arg) {
mutex_word = expect = 2;
return WaitOnAddress(&mutex_word, &expect, 4, 100); // .1 sec max
}
DWORD waker(void* arg) {
mutex_word = 0;
WakeByAddressSingle(&mutex_word);
return 0;
}
int main()
{
WakeByAddressAll((void*)&main);
return 104;
// Verify that WaitOnAddress returns right away if the mutex word has the wrong value.
int result = WaitOnAddress(&mutex_word, &expect, 4, 500); // max = .5 sec
if (!result) return 0; // what? shouldn't be an error to mismatch
// Try really waiting
mutex_word = 9;
result = WaitOnAddress(&mutex_word, &expect, 4, 20); // wait 20 millisec
// expect a timeout
if (!(result == 0 && GetLastError()==ERROR_TIMEOUT)) return 0;
// Simulate a lisp mutex being woken
HANDLE hWaiter, hWaker;
hWaiter = CreateThread(NULL, 0,
waiter, 0, /* function and argument */
0, /* flags */
0); /* id */
hWaker = CreateThread(NULL, 0,
waker, 0, /* function and argument */
CREATE_SUSPENDED, /* flags */
0); /* id */
for (;;) {
// wait for the waiter to place itself into a wait state on the mutex
if (mutex_word == 2) break;
Sleep(10); // 10 millisec
}
// Give them some time to rendezvous
ResumeThread(hWaker);
WaitForSingleObject(hWaiter, 200); // .2 sec max
if (mutex_word == 0) return 104;
return 1;
}