Skip to content

Commit

Permalink
[windows] Use critical section when pthread mutex is not available
Browse files Browse the repository at this point in the history
When compiling for Windows, pthread libraries may not be available. In
this case, we emulate pthread mutexes with critical sections.
  • Loading branch information
walac committed May 22, 2020
1 parent 55d8ee2 commit eea1348
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 3 deletions.
24 changes: 24 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,20 @@ ck_check_include_file("sys/time.h" HAVE_SYS_TIME_H)
ck_check_include_file("time.h" HAVE_TIME_H)
ck_check_include_file("unistd.h" HAVE_UNISTD_H)

# check if we have windows.h on native windows environments
ck_check_include_file("windows.h" HAVE_WINDOWS_H)
ck_check_include_file("synchapi.h" HAVE_SYNCHAPI_H)
if (HAVE_WINDOWS_H)
set(HAVE_WINDOWS_H 1)
else()
set(HAVE_WINDOWS_H 0)
endif()
if (HAVE_SYNCHAPI_H)
set(HAVE_SYNCHAPI_H 1)
else()
set(HAVE_SYNCHAPI_H 0)
endif()

###############################################################################
# Check functions
check_function_exists(fork HAVE_FORK)
Expand All @@ -173,10 +187,20 @@ check_function_exists(strsignal HAVE_DECL_STRSIGNAL)
check_function_exists(_getpid HAVE__GETPID)
check_function_exists(_strdup HAVE__STRDUP)
check_function_exists(alarm HAVE_DECL_ALARM)
if (HAVE_SYNCHAPI_H)
check_function_exists(InitOnceBeginInitialize HAVE_INIT_ONCE_BEGIN_INITIALIZE)
check_function_exists(InitOnceComplete HAVE_INIT_ONCE_COMPLETE)
endif()
if (HAVE_REGEX_H)
check_function_exists(regcomp HAVE_REGCOMP)
check_function_exists(regexec HAVE_REGEXEC)
endif()
if (HAVE_INIT_ONCE_BEGIN_INITIALIZE AND HAVE_INIT_ONCE_COMPLETE)
set(HAVE_WIN32_INIT_ONCE 1)
else()
set(HAVE_WIN32_INIT_ONCE 0)
endif()


# printf related checks
check_function_exists(snprintf HAVE_SNPRINTF_FUNCTION)
Expand Down
15 changes: 15 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,21 @@ AM_CONDITIONAL(SUBUNIT, test x"$enable_subunit" != "xfalse")
# Check for POSIX regular expressions support.
AC_CHECK_HEADERS([regex.h], HAVE_REGEX_H=1, HAVE_REGEX_H=0)

# Check if we have the windows headers for Init Once API
AC_CHECK_HEADERS([windows.h], HAVE_WINDOWS_H=1, HAVE_WINDOWS_H=0)
AC_CHECK_HEADERS([synchapi.h], HAVE_SYNCHAPI_H=1, HAVE_SYNCHAPI_H=0)
AC_SUBST(HAVE_WINDOWS_H)
AC_SUBST(HAVE_SYNCHAPI_H)

# Check if we have the One-Time Initialization API
if test "x$HAVE_SYNCHAPI_H" = "x1"; then
AC_CHECK_FUNCS([InitOnceBeginInitialize InitOnceComplete], HAVE_WIN32_INIT_ONCE=1, HAVE_WIN32_INIT_ONCE=0)
else
HAVE_WIN32_INIT_ONCE=0
fi
AC_SUBST(HAVE_WIN32_INIT_ONCE)
AC_DEFINE_UNQUOTED(HAVE_WIN32_INIT_ONCE, $HAVE_WIN32_INIT_ONCE, "Win32 Init Once API is supported")

if test "x$HAVE_REGEX_H" = "x1"; then
AC_CHECK_FUNCS([regcomp regexec], HAVE_REGEX=1, HAVE_REGEX=0)
else
Expand Down
4 changes: 4 additions & 0 deletions src/check.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -2357,4 +2357,8 @@ CK_DLL_EXP void CK_EXPORT check_set_max_msg_size(size_t max_msg_size);
CK_CPPEND
#endif

#define HAVE_WINDOWS_H @HAVE_WINDOWS_H@
#define HAVE_SYNCHAPI_H @HAVE_SYNCHAPI_H@
#define HAVE_WIN32_INIT_ONCE @HAVE_WIN32_INIT_ONCE@

#endif /* CHECK_H */
39 changes: 36 additions & 3 deletions src/check_pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,29 @@
#include "check_impl.h"
#include "check_pack.h"

#if HAVE_WINDOWS_H
#include <windows.h>
#endif

#if HAVE_SYNCHAPI_H
#include <synchapi.h>
#endif

#ifndef HAVE_PTHREAD
#define pthread_mutex_lock(arg)
#define pthread_mutex_unlock(arg)
#define pthread_cleanup_push(f, a) {
#define pthread_cleanup_pop(e) }
#endif

#ifndef HAVE_PTHREAD
#if HAVE_WIN32_INIT_ONCE
#define pthread_mutex_lock(arg) EnterCriticalSection(arg)
#define pthread_mutex_unlock(arg) LeaveCriticalSection(arg)
#else
#define pthread_mutex_lock(arg)
#define pthread_mutex_unlock(arg)
#endif
#endif

/* Maximum size for one message in the message stream. */
static size_t ck_max_msg_size = 0;
#ifndef DEFAULT_MAX_MSG_SIZE
Expand Down Expand Up @@ -348,12 +364,15 @@ static void check_type(int type, const char *file, int line)
eprintf("Bad message type arg %d", file, line, type);
}

#ifdef HAVE_PTHREAD
#if defined HAVE_PTHREAD
static pthread_mutex_t ck_mutex_lock = PTHREAD_MUTEX_INITIALIZER;
static void ppack_cleanup(void *mutex)
{
pthread_mutex_unlock((pthread_mutex_t *)mutex);
}
#elif HAVE_WIN32_INIT_ONCE
static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
static CRITICAL_SECTION ck_mutex_lock;
#endif

void ppack(FILE * fdes, enum ck_msg_type type, CheckMsg * msg)
Expand All @@ -362,6 +381,20 @@ void ppack(FILE * fdes, enum ck_msg_type type, CheckMsg * msg)
int n;
size_t r;

#if !defined HAVE_PTHREAD && HAVE_WIN32_INIT_ONCE
BOOL pending;
if (!InitOnceBeginInitialize(&init_once, 0, &pending, NULL))
{
eprintf("Cannot initialize Win32 synch object", __FILE__, __LINE__ - 5);
return;
}

if (pending)
InitializeCriticalSection(&ck_mutex_lock);

InitOnceComplete(&init_once, 0, NULL);
#endif

n = pack(type, &buf, msg);
if(n < 0)
eprintf("pack failed", __FILE__, __LINE__ - 2);
Expand Down

0 comments on commit eea1348

Please sign in to comment.