Skip to content

Commit 93143eb

Browse files
committed
[windows] Use critical section when pthread mutex is not available
When compiling for Windows, pthread libraries may not be available. In this case, we emulate pthread mutexes with critical sections.
1 parent 55d8ee2 commit 93143eb

4 files changed

Lines changed: 74 additions & 4 deletions

File tree

CMakeLists.txt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ if(WIN32)
105105
if(MSVC60)
106106
set(WINVER 0x0400)
107107
else()
108-
set(WINVER 0x0500)
108+
set(WINVER 0x0600)
109109
endif()
110110
set(_WIN32_WINNT ${WINVER})
111111
endif(WIN32)
@@ -156,6 +156,10 @@ ck_check_include_file("sys/time.h" HAVE_SYS_TIME_H)
156156
ck_check_include_file("time.h" HAVE_TIME_H)
157157
ck_check_include_file("unistd.h" HAVE_UNISTD_H)
158158

159+
# check if we have windows.h on native windows environments
160+
ck_check_include_file("windows.h" HAVE_WINDOWS_H)
161+
ck_check_include_file("synchapi.h" HAVE_SYNCHAPI_H)
162+
159163
###############################################################################
160164
# Check functions
161165
check_function_exists(fork HAVE_FORK)
@@ -173,6 +177,10 @@ check_function_exists(strsignal HAVE_DECL_STRSIGNAL)
173177
check_function_exists(_getpid HAVE__GETPID)
174178
check_function_exists(_strdup HAVE__STRDUP)
175179
check_function_exists(alarm HAVE_DECL_ALARM)
180+
if (HAVE_SYNCHAPI_H)
181+
check_function_exists(InitOnceBeginInitialize HAVE_INIT_ONCE_BEGIN_INITIALIZE)
182+
check_function_exists(InitOnceComplete HAVE_INIT_ONCE_COMPLETE)
183+
endif()
176184
if (HAVE_REGEX_H)
177185
check_function_exists(regcomp HAVE_REGCOMP)
178186
check_function_exists(regexec HAVE_REGEXEC)

cmake/config.h.in

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,18 @@ typedef uint64_t uintmax_t;
303303
/* Define to 1 if you have the <unistd.h> header file. */
304304
#cmakedefine HAVE_UNISTD_H 1
305305

306+
/* Define to 1 if you have <windows.h> header file. */
307+
#cmakedefine HAVE_WINDOWS_H 1
308+
309+
/* Define to 1 if you have <synchapi.h> header file. */
310+
#cmakedefine HAVE_SYNCHAPI_H 1
311+
312+
/* Define to 1 if you have the 'InitOnceBeginInitialize' function. */
313+
#cmakedefine HAVE_INIT_ONCE_BEGIN_INITIALIZE 1
314+
315+
/* Define to 1 if you have the 'InitOnceComplete' function. */
316+
#cmakedefine HAVE_INIT_ONCE_COMPLETE 1
317+
306318
/* Define to 1 if the system has the type `unsigned long long'. */
307319
#cmakedefine HAVE_UNSIGNED_LONG_LONG 1
308320

configure.ac

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,18 @@ AM_CONDITIONAL(SUBUNIT, test x"$enable_subunit" != "xfalse")
271271
# Check for POSIX regular expressions support.
272272
AC_CHECK_HEADERS([regex.h], HAVE_REGEX_H=1, HAVE_REGEX_H=0)
273273

274+
# Check if we have the windows headers for Init Once API
275+
AC_CHECK_HEADERS([windows.h], HAVE_WINDOWS_H=1, HAVE_WINDOWS_H=0)
276+
AC_CHECK_HEADERS([synchapi.h], HAVE_SYNCHAPI_H=1, HAVE_SYNCHAPI_H=0)
277+
AC_SUBST(HAVE_WINDOWS_H)
278+
AC_SUBST(HAVE_SYNCHAPI_H)
279+
280+
# Check if we have the One-Time Initialization API
281+
AC_CHECK_FUNCS([InitOnceBeginInitialize], HAVE_INIT_ONCE_BEGIN_INITIALIZE=1, HAVE_INIT_ONCE_BEGIN_INITIALIZE=0)
282+
AC_CHECK_FUNCS([InitOnceComplete], HAVE_INIT_ONCE_COMPLETE=1, HAVE_INIT_ONCE_COMPLETE=0)
283+
AC_SUBST(HAVE_INIT_ONCE_BEGIN_INITIALIZE)
284+
AC_SUBST(HAVE_INIT_ONCE_COMPLETE)
285+
274286
if test "x$HAVE_REGEX_H" = "x1"; then
275287
AC_CHECK_FUNCS([regcomp regexec], HAVE_REGEX=1, HAVE_REGEX=0)
276288
else

src/check_pack.c

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
*/
2020

2121
#include "../lib/libcompat.h"
22+
#include "config.h"
2223

2324
#include <stdlib.h>
2425
#include <string.h>
@@ -33,13 +34,33 @@
3334
#include "check_impl.h"
3435
#include "check_pack.h"
3536

37+
#ifdef HAVE_WINDOWS_H
38+
#include <windows.h>
39+
#endif
40+
41+
#ifdef HAVE_SYNCHAPI_H
42+
#include <synchapi.h>
43+
#endif
44+
45+
#if defined(HAVE_INIT_ONCE_BEGIN_INITIALIZE) && defined(HAVE_INIT_ONCE_COMPLETE)
46+
#define HAVE_WIN32_INIT_ONCE 1
47+
#endif
48+
3649
#ifndef HAVE_PTHREAD
37-
#define pthread_mutex_lock(arg)
38-
#define pthread_mutex_unlock(arg)
3950
#define pthread_cleanup_push(f, a) {
4051
#define pthread_cleanup_pop(e) }
4152
#endif
4253

54+
#ifndef HAVE_PTHREAD
55+
#if defined(HAVE_WIN32_INIT_ONCE)
56+
#define pthread_mutex_lock(arg) EnterCriticalSection(arg)
57+
#define pthread_mutex_unlock(arg) LeaveCriticalSection(arg)
58+
#else
59+
#define pthread_mutex_lock(arg)
60+
#define pthread_mutex_unlock(arg)
61+
#endif
62+
#endif
63+
4364
/* Maximum size for one message in the message stream. */
4465
static size_t ck_max_msg_size = 0;
4566
#ifndef DEFAULT_MAX_MSG_SIZE
@@ -348,12 +369,15 @@ static void check_type(int type, const char *file, int line)
348369
eprintf("Bad message type arg %d", file, line, type);
349370
}
350371

351-
#ifdef HAVE_PTHREAD
372+
#if defined HAVE_PTHREAD
352373
static pthread_mutex_t ck_mutex_lock = PTHREAD_MUTEX_INITIALIZER;
353374
static void ppack_cleanup(void *mutex)
354375
{
355376
pthread_mutex_unlock((pthread_mutex_t *)mutex);
356377
}
378+
#elif defined HAVE_WIN32_INIT_ONCE
379+
static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
380+
static CRITICAL_SECTION ck_mutex_lock;
357381
#endif
358382

359383
void ppack(FILE * fdes, enum ck_msg_type type, CheckMsg * msg)
@@ -362,6 +386,20 @@ void ppack(FILE * fdes, enum ck_msg_type type, CheckMsg * msg)
362386
int n;
363387
size_t r;
364388

389+
#if !defined(HAVE_PTHREAD) && defined(HAVE_WIN32_INIT_ONCE)
390+
BOOL pending;
391+
if (!InitOnceBeginInitialize(&init_once, 0, &pending, NULL))
392+
{
393+
eprintf("Cannot initialize Win32 synch object", __FILE__, __LINE__ - 5);
394+
return;
395+
}
396+
397+
if (pending)
398+
InitializeCriticalSection(&ck_mutex_lock);
399+
400+
InitOnceComplete(&init_once, 0, NULL);
401+
#endif
402+
365403
n = pack(type, &buf, msg);
366404
if(n < 0)
367405
eprintf("pack failed", __FILE__, __LINE__ - 2);

0 commit comments

Comments
 (0)