1+ /*****************************************************************************
2+ Copyright (c) 2014, Lab of Parallel Software and Computational Science,ICSAS
3+ All rights reserved.
4+
5+ Redistribution and use in source and binary forms, with or without
6+ modification, are permitted provided that the following conditions are
7+ met:
8+
9+ 1. Redistributions of source code must retain the above copyright
10+ notice, this list of conditions and the following disclaimer.
11+
12+ 2. Redistributions in binary form must reproduce the above copyright
13+ notice, this list of conditions and the following disclaimer in
14+ the documentation and/or other materials provided with the
15+ distribution.
16+ 3. Neither the name of the ISCAS nor the names of its contributors may
17+ be used to endorse or promote products derived from this software
18+ without specific prior written permission.
19+
20+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
29+ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30+
31+ **********************************************************************************/
32+
33+ #ifndef OS_WINDOWS
34+ #include "common_utest.h"
35+ #include <sys/wait.h>
36+ #include <cblas.h>
37+
38+ void * xmalloc (size_t n )
39+ {
40+ void * tmp ;
41+ tmp = malloc (n );
42+ if (tmp == NULL ) {
43+ fprintf (stderr , "You are about to die\n" );
44+ exit (1 );
45+ } else {
46+ return tmp ;
47+ }
48+ }
49+
50+ void check_dgemm (double * a , double * b , double * result , double * expected , int n )
51+ {
52+ int i ;
53+ cblas_dgemm (CblasRowMajor , CblasNoTrans , CblasNoTrans , n , n , n ,
54+ 1.0 , a , n , b , n , 0.0 , result , n );
55+ for (i = 0 ; i < n * n ; ++ i ) {
56+ CU_ASSERT_DOUBLE_EQUAL (expected [i ], result [i ], CHECK_EPS );
57+ }
58+ }
59+
60+ void test_fork_safety (void )
61+ {
62+ int n = 1000 ;
63+ int i ;
64+
65+ double * a , * b , * c , * d ;
66+ size_t n_bytes ;
67+
68+ pid_t fork_pid ;
69+ pid_t fork_pid_nested ;
70+
71+ n_bytes = sizeof (* a ) * n * n ;
72+
73+ a = xmalloc (n_bytes );
74+ b = xmalloc (n_bytes );
75+ c = xmalloc (n_bytes );
76+ d = xmalloc (n_bytes );
77+
78+ // Put ones in a and b
79+ for (i = 0 ; i < n * n ; ++ i ) {
80+ a [i ] = 1 ;
81+ b [i ] = 1 ;
82+ }
83+
84+ // Compute a DGEMM product in the parent process prior to forking to
85+ // ensure that the OpenBLAS thread pool is initialized.
86+ cblas_dgemm (CblasRowMajor , CblasNoTrans , CblasNoTrans , n , n , n ,
87+ 1.0 , a , n , b , n , 0.0 , c , n );
88+
89+ fork_pid = fork ();
90+ if (fork_pid == -1 ) {
91+ CU_FAIL ("Failed to fork process." );
92+ } else if (fork_pid == 0 ) {
93+ // Compute a DGEMM product in the child process to check that the
94+ // thread pool as been properly been reinitialized after the fork.
95+ check_dgemm (a , b , d , c , n );
96+
97+ // Nested fork to check that the pthread_atfork protection can work
98+ // recursively
99+ fork_pid_nested = fork ();
100+ if (fork_pid_nested == -1 ) {
101+ CU_FAIL ("Failed to fork process." );
102+ exit (1 );
103+ } else if (fork_pid_nested == 0 ) {
104+ check_dgemm (a , b , d , c , n );
105+ exit (0 );
106+ } else {
107+ check_dgemm (a , b , d , c , n );
108+ int child_status = 0 ;
109+ pid_t wait_pid = wait (& child_status );
110+ CU_ASSERT (wait_pid == fork_pid_nested );
111+ CU_ASSERT (WEXITSTATUS (child_status ) == 0 );
112+ exit (0 );
113+ }
114+ } else {
115+ check_dgemm (a , b , d , c , n );
116+ // Wait for the child to finish and check the exit code.
117+ int child_status = 0 ;
118+ pid_t wait_pid = wait (& child_status );
119+ CU_ASSERT (wait_pid == fork_pid );
120+ CU_ASSERT (WEXITSTATUS (child_status ) == 0 );
121+ }
122+ }
123+ #endif
0 commit comments