Allow unit testing on Windows

These changes allow testing on Windows using clang.exe.
There are two main changes:
1. Only link to -lm when it actually exists on the system
2. Create basic versions of pthread_create() and pthread_join() for windows.
   They are not POSIX compliant by any stretch but will allow any existing
   and future tests to use pthread_create() and pthread_join() for testing
   interactions of libomp with os threads.

Differential Revision: http://reviews.llvm.org/D20391

llvm-svn: 270464
This commit is contained in:
Jonathan Peyton 2016-05-23 17:50:32 +00:00
parent 6c8f20d73d
commit 1ab887d403
6 changed files with 74 additions and 3 deletions

View File

@ -146,7 +146,11 @@ set_target_properties(omp PROPERTIES
)
# Get the library's location within the build tree for the unit tester
get_target_property(LIBOMP_LIBRARY_DIR omp LIBRARY_OUTPUT_DIRECTORY)
if(NOT WIN32)
get_target_property(LIBOMP_LIBRARY_DIR omp LIBRARY_OUTPUT_DIRECTORY)
else()
get_target_property(LIBOMP_LIBRARY_DIR omp RUNTIME_OUTPUT_DIRECTORY)
endif()
if(NOT LIBOMP_LIBRARY_DIR)
set(LIBOMP_LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
set(LIBOMP_LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE)

View File

@ -1,6 +1,7 @@
# CMakeLists.txt file for unit testing OpenMP Library
include(FindPythonInterp)
include(CheckTypeSize)
include(CheckLibraryExists)
if(NOT PYTHONINTERP_FOUND)
libomp_warning_say("Could not find Python.")
@ -8,6 +9,9 @@ if(NOT PYTHONINTERP_FOUND)
return()
endif()
# Some tests use math functions
check_library_exists(m sqrt "" LIBOMP_HAVE_LIBM)
macro(pythonize_bool var)
if (${var})
set(${var} True)
@ -20,6 +24,7 @@ pythonize_bool(LIBOMP_USE_HWLOC)
pythonize_bool(LIBOMP_OMPT_SUPPORT)
pythonize_bool(LIBOMP_OMPT_BLAME)
pythonize_bool(LIBOMP_OMPT_TRACE)
pythonize_bool(LIBOMP_HAVE_LIBM)
set(LIBOMP_TEST_CFLAGS "" CACHE STRING
"Extra compiler flags to send to the test compiler")

View File

@ -48,6 +48,11 @@ config.test_cflags = config.test_openmp_flag + \
" -L " + config.library_dir + \
" " + config.test_extra_cflags
# extra libraries
libs = ""
if config.has_libm:
libs += " -lm"
# Allow XFAIL to work
config.target_triple = [ ]
if re.search('gcc', config.test_compiler) is not None:
@ -92,7 +97,7 @@ if config.has_ompt:
config.substitutions.append(("%libomp-compile-and-run", \
"%libomp-compile && %libomp-run"))
config.substitutions.append(("%libomp-compile", \
"%clang %cflags %s -o %t -lm"))
"%clang %cflags %s -o %t" + libs))
config.substitutions.append(("%libomp-run", "%t"))
config.substitutions.append(("%clang", config.test_compiler))
config.substitutions.append(("%openmp_flag", config.test_openmp_flag))

View File

@ -11,6 +11,7 @@ config.operating_system = "@CMAKE_SYSTEM_NAME@"
config.hwloc_library_dir = "@LIBOMP_HWLOC_LIBRARY_DIR@"
config.using_hwloc = @LIBOMP_USE_HWLOC@
config.has_ompt = @LIBOMP_OMPT_SUPPORT@ and @LIBOMP_OMPT_BLAME@ and @LIBOMP_OMPT_TRACE@
config.has_libm = @LIBOMP_HAVE_LIBM@
# Let the main config do the real work.
lit_config.load_config(config, "@LIBOMP_BASE_DIR@/test/lit.cfg")

View File

@ -1,6 +1,5 @@
// RUN: %libomp-compile-and-run
#include <stdio.h>
#include <pthread.h>
#include "omp_testsuite.h"
#define NUM_THREADS 10

View File

@ -4,6 +4,7 @@
#define OMP_TESTSUITE_H
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
/* General */
@ -19,4 +20,60 @@
#define NUM_TASKS 25
#define MAX_TASKS_PER_THREAD 5
#ifdef _WIN32
// Windows versions of pthread_create() and pthread_join()
# include <windows.h>
typedef HANDLE pthread_t;
// encapsulates the information about a pthread-callable function
struct thread_func_info_t {
void* (*start_routine)(void*);
void* arg;
};
// call the void* start_routine(void*);
static DWORD __thread_func_wrapper(LPVOID lpParameter) {
struct thread_func_info_t* function_information;
function_information = (struct thread_func_info_t*)lpParameter;
function_information->start_routine(function_information->arg);
free(function_information);
return 0;
}
// attr is ignored
static int pthread_create(pthread_t *thread, void *attr,
void *(*start_routine) (void *), void *arg) {
pthread_t pthread;
struct thread_func_info_t* info;
info = (struct thread_func_info_t*)malloc(sizeof(struct thread_func_info_t));
info->start_routine = start_routine;
info->arg = arg;
pthread = CreateThread(NULL, 0, __thread_func_wrapper, info, 0, NULL);
if (pthread == NULL) {
fprintf(stderr, "CreateThread() failed: Error #%u.\n", GetLastError());
exit(1);
}
*thread = pthread;
return 0;
}
// retval is ignored for now
static int pthread_join(pthread_t thread, void **retval) {
int rc;
rc = WaitForSingleObject(thread, INFINITE);
if (rc == WAIT_FAILED) {
fprintf(stderr, "WaitForSingleObject() failed: Error #%u.\n",
GetLastError());
exit(1);
}
rc = CloseHandle(thread);
if (rc == 0) {
fprintf(stderr, "CloseHandle() failed: Error #%u.\n", GetLastError());
exit(1);
}
return 0;
}
#else
# include <pthread.h>
#endif
#endif