Skip to content

Commit

Permalink
[windows] Implement pthread_mutex for Windows
Browse files Browse the repository at this point in the history
When compiling for Windows, pthread libraries may not be available. For
Win32 applications in which a external implementation of pthread is not
available, we build libcompat with the pthread_mutex.c module, which
provides a simple implementation of pthread_mutex for the Win32 API.
  • Loading branch information
walac committed Jun 10, 2020
1 parent 55d8ee2 commit 34d1196
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 6 deletions.
20 changes: 19 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#
cmake_minimum_required(VERSION 3.9 FATAL_ERROR)

include(CheckCCompilerFlag)

# Detect if Check is being used in another build as a subproject
# probably with command FetchContent*().
set(THIS_IS_SUBPROJECT FALSE)
Expand Down Expand Up @@ -105,7 +107,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 @@ -155,6 +157,10 @@ ck_check_include_file("strings.h" HAVE_STRINGS_H)
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)
ck_check_include_file("pthread.h" HAVE_PTHREAD)

# check if we have windows.h on native windows environments
ck_check_include_file("windows.h" HAVE_WINDOWS_H)

###############################################################################
# Check functions
Expand All @@ -173,6 +179,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_WINDOWS_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 Expand Up @@ -227,6 +237,14 @@ if(HAVE_REGEX_H AND HAVE_REGCOMP AND HAVE_REGEXEC)
set(ENABLE_REGEX 1)
endif()

if (HAVE_PTHREAD)
check_c_compiler_flag("-pthread" HAVE_PTHREADS_FLAG)
if (HAVE_PTHREADS_FLAG)
add_definitions("-pthread")
add_link_options("-pthread")
endif()
endif()


###############################################################################
# Check defines
Expand Down
15 changes: 15 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 All @@ -321,6 +333,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the `_strdup' function. */
#cmakedefine HAVE__STRDUP 1

/* Define 1 if you have pthread support. */
#cmakedefine HAVE_PTHREAD 1

/* Version number of Check */
#cmakedefine CHECK_VERSION "${CHECK_MAJOR_VERSION}.${CHECK_MINOR_VERSION}.${CHECK_MICRO_VERSION}"

Expand Down
10 changes: 10 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,16 @@ 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_SUBST(HAVE_WINDOWS_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
4 changes: 4 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ if(NOT HAVE_DECL_ALARM)
set(SOURCES ${SOURCES} alarm.c)
endif(NOT HAVE_DECL_ALARM)

if (NOT HAVE_PTHREAD)
set(SOURCES ${SOURCES} pthread_mutex.c)
endif()

set(HEADERS libcompat.h)

add_library(compat STATIC ${SOURCES} ${HEADERS})
Expand Down
24 changes: 23 additions & 1 deletion lib/libcompat.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,31 @@ extern int fpclassify(double d);
#include <sys/wait.h>
#endif

#if defined(HAVE_INIT_ONCE_BEGIN_INITIALIZE) && defined(HAVE_INIT_ONCE_COMPLETE)
#define HAVE_WIN32_INIT_ONCE 1
#endif

/* declares pthread_create and friends */
#ifdef HAVE_PTHREAD
#if defined HAVE_PTHREAD
#include <pthread.h>
#elif defined HAVE_WIN32_INIT_ONCE
typedef void pthread_mutexattr_t;

typedef struct
{
INIT_ONCE init;
HANDLE mutex;
} pthread_mutex_t;

#define PTHREAD_MUTEX_INITIALIZER { \
INIT_ONCE_STATIC_INIT, \
NULL, \
}

int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
#endif

#ifdef HAVE_STDINT_H
Expand Down
69 changes: 69 additions & 0 deletions lib/pthread_mutex.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Check: a unit test framework for C
* Copyright (C) 2020 Wander Lairson Costa
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/

#include "libcompat.h"

#ifdef HAVE_WIN32_INIT_ONCE

static int mutex_init(pthread_mutex_t *mutex)
{
BOOL pending;
if (!InitOnceBeginInitialize(&mutex->init, 0, &pending, NULL))
return -1;

int ret = 0;
if (pending)
{
mutex->mutex = CreateMutexW(NULL, FALSE, NULL);
if (!mutex->mutex)
ret = -1;
}

InitOnceComplete(&mutex->init, 0, NULL);

return ret;
}

int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr)
{
InitOnceInitialize(&mutex->init);
return mutex_init(mutex);
}

int pthread_mutex_destroy(pthread_mutex_t *mutex)
{
return CloseHandle(mutex->mutex) ? 0 : -1;
}

int pthread_mutex_lock(pthread_mutex_t *mutex)
{
if (mutex_init(mutex) != 0)
return -1;

return WaitForSingleObject(mutex->mutex, INFINITE) != WAIT_OBJECT_0
? -1 : 0;
}

int pthread_mutex_unlock(pthread_mutex_t *mutex)
{
return ReleaseMutex(mutex->mutex) ? 0 : -1;
}

#endif
5 changes: 5 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ if(NOT HAVE_DECL_ALARM)
target_sources(checkShared PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../lib/alarm.c)
endif(NOT HAVE_DECL_ALARM)

if(NOT HAVE_PTHREAD)
target_sources(check PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../lib/pthread_mutex.c)
target_sources(checkShared PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../lib/pthread_mutex.c)
endif()

# Include libraries if available
if (HAVE_LIBM)
target_link_libraries(check PUBLIC m)
Expand Down
9 changes: 5 additions & 4 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,9 +34,11 @@
#include "check_impl.h"
#include "check_pack.h"

#ifdef HAVE_WINDOWS_H
#include <windows.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
Expand Down Expand Up @@ -348,13 +351,11 @@ static void check_type(int type, const char *file, int line)
eprintf("Bad message type arg %d", file, line, type);
}

#ifdef 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);
}
#endif

void ppack(FILE * fdes, enum ck_msg_type type, CheckMsg * msg)
{
Expand Down

0 comments on commit 34d1196

Please sign in to comment.