Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[windows] Implement pthread_mutex for Windows #257

Merged
merged 1 commit into from
Jun 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 20 additions & 2 deletions 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 @@ -112,7 +114,7 @@ if(WIN32)
if(MSVC60)
set(WINVER 0x0400)
else()
set(WINVER 0x0500)
set(WINVER 0x0600)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not familiar with Windows' versioning. Can you explain this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The One-Time Initialization functions were introduced in Windows Vista. The WINVER value for Windows Vista is 0x0600.

endif()
set(_WIN32_WINNT ${WINVER})
endif(WIN32)
Expand Down Expand Up @@ -162,6 +164,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 @@ -180,6 +186,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 @@ -234,6 +244,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 Expand Up @@ -437,7 +455,7 @@ if(NOT THIS_IS_SUBPROJECT)
set(GCOV_LIBS "")
endif (CHECK_ENABLE_GCOV)

set(PTHREAD_LIBS "")
set(PTHREAD_LIBS "-pthread")
set(LIBS "")

if (HAVE_LIBM)
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
70 changes: 70 additions & 0 deletions lib/pthread_mutex.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* 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;
int ret = 0;

if (!InitOnceBeginInitialize(&mutex->init, 0, &pending, NULL))
return -1;

if (pending)
{
mutex->mutex = CreateMutexW(NULL, FALSE, NULL);
if (!mutex->mutex)
ret = -1;
brarcher marked this conversation as resolved.
Show resolved Hide resolved
}

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
13 changes: 10 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 @@ -34,12 +35,15 @@
#include "check_pack.h"

#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 PTHREAD_MUTEX_INITIALIZER
#define pthread_mutex_lock(mutex)
#define pthread_mutex_unlock(mutex)
#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 +352,15 @@ static void check_type(int type, const char *file, int line)
eprintf("Bad message type arg %d", file, line, type);
}

#ifdef HAVE_PTHREAD
#ifdef PTHREAD_MUTEX_INITIALIZER
static pthread_mutex_t ck_mutex_lock = PTHREAD_MUTEX_INITIALIZER;

static void ppack_cleanup(void *mutex)
{
pthread_mutex_unlock((pthread_mutex_t *)mutex);
}
#else
#define ppack_cleanup(mutex)
#endif

void ppack(FILE * fdes, enum ck_msg_type type, CheckMsg * msg)
Expand Down
8 changes: 8 additions & 0 deletions tests/cmake_project_usage_test/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ elseif($ENV{INCLUDE_CHECK_WITH} STREQUAL "find_package_config")
else()
message(FATAL_ERROR "Variable INCLUDE_CHECK_WITH not properly set!")
endif()

include(CheckCCompilerFlag)
check_c_compiler_flag("-pthread" HAVE_PTHREAD)
if (HAVE_PTHREAD)
add_definitions("-pthread")
add_link_options("-pthread")
endif()

add_library(test_suite test_suite.c)
target_link_libraries(test_suite PUBLIC Check::check)

Expand Down