1 /*
2 This file is part of Primer Pooler (c) Silas S. Brown.  For Wen.
3 
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7 
8     http://www.apache.org/licenses/LICENSE-2.0
9 
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16 #ifndef OPENMP_H
17 #define OPENMP_H
18 #ifdef _OPENMP
19 #include <omp.h>
20 #else
21 #define omp_get_max_threads() 1
22 #define omp_get_num_threads() 1
23 #define omp_get_thread_num() 0
24 #define omp_set_num_threads(x) (void)0
25 #endif
26 
wrapped_memcpy(void * a,const void * b,size_t n)27 static inline void* wrapped_memcpy(void *a,const void *b,size_t n) {
28   /* work around Apple compiler bug in Mac OS 10.7:
29      if memcpy is called from a function that's doing
30      OpenMP stuff, get linker errors.  So wrap it (but
31      wrapping it in an INLINE function seems to work!) */
32   return memcpy(a,b,n);
33 }
34 
35 #include "random.h"
ThreadRand()36 static inline int ThreadRand() {
37   int tNum = omp_get_thread_num(); /* this might not be unique if ThreadRand is called from inside NESTED parallelism, but we don't do that */
38   if(!tNum) return rand();
39   static RandState *states = NULL;
40   if (!states) {
41     #ifdef _OPENMP
42     #pragma omp critical
43     #endif
44     if (!states) {
45       /* How many threads shall we leave room for?
46 
47          omp_get_max_threads() works BEFORE you start a
48          parallel region, but not INSIDE it (it returns 1
49          or however many threads you can NOW start).
50 
51          omp_get_num_procs() might not return a high
52          enough number if someone set more threads than
53          cores (not great for this application though).
54 
55          omp_get_num_threads() does what we want, as long
56          as the parallel region has definitely started and
57          we won't increase it later.  We've already
58          established that we're in the parallel region
59          via the above tNum test, so let's use that.
60       */
61       int nStates = omp_get_num_threads()-1;
62       states = malloc(sizeof(RandState)*nStates);
63       if(states) {
64         int r = rand(), i;
65         for(i=0; i<nStates; i++) states[i] = r++;
66       }
67     }
68     if(!states) /* aaaargh! */ return rand();
69   } return rand_r(states+(tNum-1));
70 }
71 #endif
72