Fix issues with forking on Cygwintags/v0.3.0
| @@ -304,6 +304,7 @@ endif | |||
| ifeq ($(OSNAME), CYGWIN_NT) | |||
| NEED_PIC = 0 | |||
| NO_EXPRECISION = 1 | |||
| OS_CYGWIN_NT = 1 | |||
| endif | |||
| ifneq ($(OSNAME), WINNT) | |||
| @@ -40,6 +40,14 @@ | |||
| #include <stdlib.h> | |||
| #include "common.h" | |||
| #if defined(OS_CYGWIN_NT) && !defined(unlikely) | |||
| #ifdef __GNUC__ | |||
| #define unlikely(x) __builtin_expect(!!(x), 0) | |||
| #else | |||
| #define unlikely(x) (x) | |||
| #endif | |||
| #endif | |||
| /* This is a thread implementation for Win32 lazy implementation */ | |||
| /* Thread server common infomation */ | |||
| @@ -53,7 +61,7 @@ typedef struct{ | |||
| } blas_pool_t; | |||
| /* We need this grobal for cheking if initialization is finished. */ | |||
| /* We need this global for cheking if initialization is finished. */ | |||
| int blas_server_avail = 0; | |||
| /* Local Variables */ | |||
| @@ -340,6 +348,11 @@ int blas_thread_init(void){ | |||
| int exec_blas_async(BLASLONG pos, blas_queue_t *queue){ | |||
| #if defined(SMP_SERVER) && defined(OS_CYGWIN_NT) | |||
| // Handle lazy re-init of the thread-pool after a POSIX fork | |||
| if (unlikely(blas_server_avail == 0)) blas_thread_init(); | |||
| #endif | |||
| blas_queue_t *current; | |||
| current = queue; | |||
| @@ -405,6 +418,11 @@ int exec_blas_async_wait(BLASLONG num, blas_queue_t *queue){ | |||
| /* Execute Threads */ | |||
| int exec_blas(BLASLONG num, blas_queue_t *queue){ | |||
| #if defined(SMP_SERVER) && defined(OS_CYGWIN_NT) | |||
| // Handle lazy re-init of the thread-pool after a POSIX fork | |||
| if (unlikely(blas_server_avail == 0)) blas_thread_init(); | |||
| #endif | |||
| #ifndef ALL_THREADED | |||
| int (*routine)(blas_arg_t *, void *, void *, double *, double *, BLASLONG); | |||
| #endif | |||
| @@ -74,7 +74,7 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
| #include "common.h" | |||
| #include <errno.h> | |||
| #ifdef OS_WINDOWS | |||
| #if defined(OS_WINDOWS) && !defined(OS_CYGWIN_NT) | |||
| #define ALLOC_WINDOWS | |||
| #ifndef MEM_LARGE_PAGES | |||
| #define MEM_LARGE_PAGES 0x20000000 | |||
| @@ -88,7 +88,7 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
| #include <stdio.h> | |||
| #include <fcntl.h> | |||
| #ifndef OS_WINDOWS | |||
| #if !defined(OS_WINDOWS) || defined(OS_CYGWIN_NT) | |||
| #include <sys/mman.h> | |||
| #ifndef NO_SYSV_IPC | |||
| #include <sys/shm.h> | |||
| @@ -323,7 +323,7 @@ void openblas_fork_handler() | |||
| // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60035 | |||
| // In the mean time build with USE_OPENMP=0 or link against another | |||
| // implementation of OpenMP. | |||
| #if !(defined(OS_WINDOWS) || defined(OS_ANDROID)) && defined(SMP_SERVER) | |||
| #if !((defined(OS_WINDOWS) && !defined(OS_CYGWIN_NT)) || defined(OS_ANDROID)) && defined(SMP_SERVER) | |||
| int err; | |||
| err = pthread_atfork ((void (*)(void)) BLASFUNC(blas_thread_shutdown), NULL, NULL); | |||
| if(err != 0) | |||
| @@ -12,7 +12,15 @@ OBJS=utest_main.o test_amax.o | |||
| #test_rot.o test_swap.o test_axpy.o test_dotu.o test_rotmg.o test_dsdot.o test_fork.o | |||
| ifneq ($(NO_LAPACK), 1) | |||
| OBJS += test_potrs.o | |||
| #OBJS += test_potrs.o | |||
| endif | |||
| ifndef OS_WINDOWS | |||
| OBJS += test_fork.o | |||
| else | |||
| ifdef OS_CYGWIN_NT | |||
| OBJS += test_fork.o | |||
| endif | |||
| endif | |||
| all : run_test | |||
| @@ -31,8 +31,7 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
| **********************************************************************************/ | |||
| #ifndef OS_WINDOWS | |||
| #include "common_utest.h" | |||
| #include "openblas_utest.h" | |||
| #include <sys/wait.h> | |||
| #include <cblas.h> | |||
| @@ -54,11 +53,11 @@ void check_dgemm(double *a, double *b, double *result, double *expected, int n) | |||
| cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, n, n, n, | |||
| 1.0, a, n, b, n, 0.0, result, n); | |||
| for(i = 0; i < n * n; ++i) { | |||
| CU_ASSERT_DOUBLE_EQUAL(expected[i], result[i], CHECK_EPS); | |||
| ASSERT_DBL_NEAR_TOL(expected[i], result[i], DOUBLE_EPS); | |||
| } | |||
| } | |||
| void test_fork_safety(void) | |||
| CTEST(fork, safety) | |||
| { | |||
| int n = 1000; | |||
| int i; | |||
| @@ -89,7 +88,7 @@ void test_fork_safety(void) | |||
| fork_pid = fork(); | |||
| if (fork_pid == -1) { | |||
| CU_FAIL("Failed to fork process."); | |||
| CTEST_ERR("Failed to fork process."); | |||
| } else if (fork_pid == 0) { | |||
| // Compute a DGEMM product in the child process to check that the | |||
| // thread pool as been properly been reinitialized after the fork. | |||
| @@ -99,7 +98,7 @@ void test_fork_safety(void) | |||
| // recursively | |||
| fork_pid_nested = fork(); | |||
| if (fork_pid_nested == -1) { | |||
| CU_FAIL("Failed to fork process."); | |||
| CTEST_ERR("Failed to fork process."); | |||
| exit(1); | |||
| } else if (fork_pid_nested == 0) { | |||
| check_dgemm(a, b, d, c, n); | |||
| @@ -108,8 +107,8 @@ void test_fork_safety(void) | |||
| check_dgemm(a, b, d, c, n); | |||
| int child_status = 0; | |||
| pid_t wait_pid = wait(&child_status); | |||
| CU_ASSERT(wait_pid == fork_pid_nested); | |||
| CU_ASSERT(WEXITSTATUS (child_status) == 0); | |||
| ASSERT_EQUAL(wait_pid, fork_pid_nested); | |||
| ASSERT_EQUAL(0, WEXITSTATUS (child_status)); | |||
| exit(0); | |||
| } | |||
| } else { | |||
| @@ -117,8 +116,7 @@ void test_fork_safety(void) | |||
| // Wait for the child to finish and check the exit code. | |||
| int child_status = 0; | |||
| pid_t wait_pid = wait(&child_status); | |||
| CU_ASSERT(wait_pid == fork_pid); | |||
| CU_ASSERT(WEXITSTATUS (child_status) == 0); | |||
| ASSERT_EQUAL(wait_pid, fork_pid); | |||
| ASSERT_EQUAL(0, WEXITSTATUS (child_status)); | |||
| } | |||
| } | |||
| #endif | |||