125 lines
4.1 KiB
C
125 lines
4.1 KiB
C
/*****************************************************************************
|
|
Copyright (c) 2011-2014, The OpenBLAS Project
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are
|
|
met:
|
|
|
|
1. Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in
|
|
the documentation and/or other materials provided with the
|
|
distribution.
|
|
3. Neither the name of the OpenBLAS project nor the names of
|
|
its contributors may be used to endorse or promote products
|
|
derived from this software without specific prior written
|
|
permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
|
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
**********************************************************************************/
|
|
|
|
#ifndef OS_WINDOWS
|
|
#include "common_utest.h"
|
|
#include <sys/wait.h>
|
|
#include <cblas.h>
|
|
|
|
void* xmalloc(size_t n)
|
|
{
|
|
void* tmp;
|
|
tmp = malloc(n);
|
|
if (tmp == NULL) {
|
|
fprintf(stderr, "You are about to die\n");
|
|
exit(1);
|
|
} else {
|
|
return tmp;
|
|
}
|
|
}
|
|
|
|
void check_dgemm(double *a, double *b, double *result, double *expected, int n)
|
|
{
|
|
int i;
|
|
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);
|
|
}
|
|
}
|
|
|
|
void test_fork_safety(void)
|
|
{
|
|
int n = 1000;
|
|
int i;
|
|
|
|
double *a, *b, *c, *d;
|
|
size_t n_bytes;
|
|
|
|
pid_t fork_pid;
|
|
pid_t fork_pid_nested;
|
|
|
|
n_bytes = sizeof(*a) * n * n;
|
|
|
|
a = xmalloc(n_bytes);
|
|
b = xmalloc(n_bytes);
|
|
c = xmalloc(n_bytes);
|
|
d = xmalloc(n_bytes);
|
|
|
|
// Put ones in a and b
|
|
for(i = 0; i < n * n; ++i) {
|
|
a[i] = 1;
|
|
b[i] = 1;
|
|
}
|
|
|
|
// Compute a DGEMM product in the parent process prior to forking to
|
|
// ensure that the OpenBLAS thread pool is initialized.
|
|
cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, n, n, n,
|
|
1.0, a, n, b, n, 0.0, c, n);
|
|
|
|
fork_pid = fork();
|
|
if (fork_pid == -1) {
|
|
CU_FAIL("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.
|
|
check_dgemm(a, b, d, c, n);
|
|
|
|
// Nested fork to check that the pthread_atfork protection can work
|
|
// recursively
|
|
fork_pid_nested = fork();
|
|
if (fork_pid_nested == -1) {
|
|
CU_FAIL("Failed to fork process.");
|
|
exit(1);
|
|
} else if (fork_pid_nested == 0) {
|
|
check_dgemm(a, b, d, c, n);
|
|
exit(0);
|
|
} else {
|
|
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);
|
|
exit(0);
|
|
}
|
|
} else {
|
|
check_dgemm(a, b, d, c, n);
|
|
// 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);
|
|
}
|
|
}
|
|
#endif
|