Skip to content

Commit

Permalink
Allow unit testing on Windows
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jpeyton52 committed May 23, 2016
1 parent 6c8f20d commit 1ab887d
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 3 deletions.
6 changes: 5 additions & 1 deletion openmp/runtime/src/CMakeLists.txt
Expand Up @@ -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)
Expand Down
5 changes: 5 additions & 0 deletions openmp/runtime/test/CMakeLists.txt
@@ -1,13 +1,17 @@
# 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.")
libomp_warning_say("The check-libomp target will not be available!")
return()
endif()

# Some tests use math functions
check_library_exists(m sqrt "" LIBOMP_HAVE_LIBM)

macro(pythonize_bool var)
if (${var})
set(${var} True)
Expand All @@ -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")
Expand Down
7 changes: 6 additions & 1 deletion openmp/runtime/test/lit.cfg
Expand Up @@ -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:
Expand Down Expand Up @@ -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))
Expand Down
1 change: 1 addition & 0 deletions openmp/runtime/test/lit.site.cfg.in
Expand Up @@ -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")
Expand Down
@@ -1,6 +1,5 @@
// RUN: %libomp-compile-and-run
#include <stdio.h>
#include <pthread.h>
#include "omp_testsuite.h"

#define NUM_THREADS 10
Expand Down
57 changes: 57 additions & 0 deletions openmp/runtime/test/omp_testsuite.h
Expand Up @@ -4,6 +4,7 @@
#define OMP_TESTSUITE_H

#include <stdio.h>
#include <stdlib.h>
#include <omp.h>

/* General */
Expand All @@ -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

0 comments on commit 1ab887d

Please sign in to comment.