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 93143eb
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 4 deletions.
10 changes: 9 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ if(WIN32)
if(MSVC60)
set(WINVER 0x0400)
else()
set(WINVER 0x0500)
set(WINVER 0x0600)
endif()
set(_WIN32_WINNT ${WINVER})
endif(WIN32)
Expand Down Expand Up @@ -156,6 +156,10 @@ 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)

###############################################################################
# Check functions
check_function_exists(fork HAVE_FORK)
Expand All @@ -173,6 +177,10 @@ 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)
Expand Down
12 changes: 12 additions & 0 deletions cmake/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,18 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H 1

/* Define to 1 if you have <windows.h> header file. */
#cmakedefine HAVE_WINDOWS_H 1

/* Define to 1 if you have <synchapi.h> header file. */
#cmakedefine HAVE_SYNCHAPI_H 1

/* Define to 1 if you have the 'InitOnceBeginInitialize' function. */
#cmakedefine HAVE_INIT_ONCE_BEGIN_INITIALIZE 1

/* Define to 1 if you have the 'InitOnceComplete' function. */
#cmakedefine HAVE_INIT_ONCE_COMPLETE 1

/* Define to 1 if the system has the type `unsigned long long'. */
#cmakedefine HAVE_UNSIGNED_LONG_LONG 1

Expand Down
12 changes: 12 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,18 @@ 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
AC_CHECK_FUNCS([InitOnceBeginInitialize], HAVE_INIT_ONCE_BEGIN_INITIALIZE=1, HAVE_INIT_ONCE_BEGIN_INITIALIZE=0)
AC_CHECK_FUNCS([InitOnceComplete], HAVE_INIT_ONCE_COMPLETE=1, HAVE_INIT_ONCE_COMPLETE=0)
AC_SUBST(HAVE_INIT_ONCE_BEGIN_INITIALIZE)
AC_SUBST(HAVE_INIT_ONCE_COMPLETE)

if test "x$HAVE_REGEX_H" = "x1"; then
AC_CHECK_FUNCS([regcomp regexec], HAVE_REGEX=1, HAVE_REGEX=0)
else
Expand Down
44 changes: 41 additions & 3 deletions src/check_pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*/

#include "../lib/libcompat.h"
#include "config.h"

#include <stdlib.h>
#include <string.h>
Expand All @@ -33,13 +34,33 @@
#include "check_impl.h"
#include "check_pack.h"

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

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

#if defined(HAVE_INIT_ONCE_BEGIN_INITIALIZE) && defined(HAVE_INIT_ONCE_COMPLETE)
#define HAVE_WIN32_INIT_ONCE 1
#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 defined(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 +369,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 defined 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 +386,20 @@ void ppack(FILE * fdes, enum ck_msg_type type, CheckMsg * msg)
int n;
size_t r;

#if !defined(HAVE_PTHREAD) && defined(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 93143eb

Please sign in to comment.