1 /*
2  * kmp_stub.cpp -- stub versions of user-callable OpenMP RT functions.
3  */
4 
5 
6 //===----------------------------------------------------------------------===//
7 //
8 //                     The LLVM Compiler Infrastructure
9 //
10 // This file is dual licensed under the MIT and the University of Illinois Open
11 // Source Licenses. See LICENSE.txt for details.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 
16 #include <stdlib.h>
17 #include <limits.h>
18 #include <errno.h>
19 
20 #include "omp.h"                // Function renamings.
21 #include "kmp.h"                // KMP_DEFAULT_STKSIZE
22 #include "kmp_stub.h"
23 
24 #if KMP_OS_WINDOWS
25     #include <windows.h>
26 #else
27     #include <sys/time.h>
28 #endif
29 
30 // Moved from omp.h
31 #define omp_set_max_active_levels    ompc_set_max_active_levels
32 #define omp_set_schedule             ompc_set_schedule
33 #define omp_get_ancestor_thread_num  ompc_get_ancestor_thread_num
34 #define omp_get_team_size            ompc_get_team_size
35 
36 #define omp_set_num_threads          ompc_set_num_threads
37 #define omp_set_dynamic              ompc_set_dynamic
38 #define omp_set_nested               ompc_set_nested
39 #define kmp_set_stacksize            kmpc_set_stacksize
40 #define kmp_set_stacksize_s          kmpc_set_stacksize_s
41 #define kmp_set_blocktime            kmpc_set_blocktime
42 #define kmp_set_library              kmpc_set_library
43 #define kmp_set_defaults             kmpc_set_defaults
44 #define kmp_set_disp_num_buffers     kmpc_set_disp_num_buffers
45 #define kmp_malloc                   kmpc_malloc
46 #define kmp_aligned_malloc           kmpc_aligned_malloc
47 #define kmp_calloc                   kmpc_calloc
48 #define kmp_realloc                  kmpc_realloc
49 #define kmp_free                     kmpc_free
50 
51 static double frequency = 0.0;
52 
53 // Helper functions.
54 static size_t __kmps_init() {
55     static int    initialized = 0;
56     static size_t dummy = 0;
57     if ( ! initialized ) {
58 
59         // TODO: Analyze KMP_VERSION environment variable, print
60         // __kmp_version_copyright and __kmp_version_build_time.
61         // WARNING: Do not use "fprintf( stderr, ... )" because it will cause
62         // unresolved "__iob" symbol (see C70080). We need to extract
63         // __kmp_printf() stuff from kmp_runtime.cpp and use it.
64 
65         // Trick with dummy variable forces linker to keep __kmp_version_copyright
66         // and __kmp_version_build_time strings in executable file (in case of
67         // static linkage). When KMP_VERSION analysis is implemented, dummy
68         // variable should be deleted, function should return void.
69         dummy = __kmp_version_copyright - __kmp_version_build_time;
70 
71         #if KMP_OS_WINDOWS
72             LARGE_INTEGER freq;
73             BOOL status = QueryPerformanceFrequency( & freq );
74             if ( status ) {
75                 frequency = double( freq.QuadPart );
76             }; // if
77         #endif
78 
79         initialized = 1;
80     }; // if
81     return dummy;
82 }; // __kmps_init
83 
84 #define i __kmps_init();
85 
86 /* set API functions */
87 void omp_set_num_threads( omp_int_t num_threads ) { i; }
88 void omp_set_dynamic( omp_int_t dynamic )         { i; __kmps_set_dynamic( dynamic ); }
89 void omp_set_nested( omp_int_t nested )           { i; __kmps_set_nested( nested );   }
90 void omp_set_max_active_levels( omp_int_t max_active_levels ) { i; }
91 void omp_set_schedule( omp_sched_t kind, omp_int_t modifier ) { i; __kmps_set_schedule( (kmp_sched_t)kind, modifier ); }
92 int omp_get_ancestor_thread_num( omp_int_t level ) { i; return ( level ) ? ( -1 ) : ( 0 ); }
93 int omp_get_team_size( omp_int_t level ) { i; return ( level ) ? ( -1 ) : ( 1 ); }
94 int kmpc_set_affinity_mask_proc( int proc, void **mask ) { i; return -1; }
95 int kmpc_unset_affinity_mask_proc( int proc, void **mask ) { i; return -1; }
96 int kmpc_get_affinity_mask_proc( int proc, void **mask ) { i; return -1; }
97 
98 /* kmp API functions */
99 void kmp_set_stacksize( omp_int_t arg )   { i; __kmps_set_stacksize( arg ); }
100 void kmp_set_stacksize_s( size_t arg )    { i; __kmps_set_stacksize( arg ); }
101 void kmp_set_blocktime( omp_int_t arg )   { i; __kmps_set_blocktime( arg ); }
102 void kmp_set_library( omp_int_t arg )     { i; __kmps_set_library( arg ); }
103 void kmp_set_defaults( char const * str ) { i; }
104 void kmp_set_disp_num_buffers( omp_int_t arg ) { i; }
105 
106 /* KMP memory management functions. */
107 void * kmp_malloc( size_t size )                 { i; return malloc( size ); }
108 void * kmp_aligned_malloc( size_t sz, size_t a ) {
109     i;
110 #if KMP_OS_WINDOWS
111     errno = ENOSYS; // not supported
112     return NULL;    // no standard aligned allocator on Windows (pre - C11)
113 #else
114     void *res;
115     int err;
116     if( err = posix_memalign( &res, a, sz ) ) {
117         errno = err; // can be EINVAL or ENOMEM
118         return NULL;
119     }
120     return res;
121 #endif
122 }
123 void * kmp_calloc( size_t nelem, size_t elsize ) { i; return calloc( nelem, elsize ); }
124 void * kmp_realloc( void *ptr, size_t size )     { i; return realloc( ptr, size ); }
125 void   kmp_free( void * ptr )                    { i; free( ptr ); }
126 
127 static int __kmps_blocktime = INT_MAX;
128 
129 void __kmps_set_blocktime( int arg ) {
130     i;
131     __kmps_blocktime = arg;
132 } // __kmps_set_blocktime
133 
134 int __kmps_get_blocktime( void ) {
135     i;
136     return __kmps_blocktime;
137 } // __kmps_get_blocktime
138 
139 static int __kmps_dynamic = 0;
140 
141 void __kmps_set_dynamic( int arg ) {
142     i;
143     __kmps_dynamic = arg;
144 } // __kmps_set_dynamic
145 
146 int __kmps_get_dynamic( void ) {
147     i;
148     return __kmps_dynamic;
149 } // __kmps_get_dynamic
150 
151 static int __kmps_library = 1000;
152 
153 void __kmps_set_library( int arg ) {
154     i;
155     __kmps_library = arg;
156 } // __kmps_set_library
157 
158 int __kmps_get_library( void ) {
159     i;
160     return __kmps_library;
161 } // __kmps_get_library
162 
163 static int __kmps_nested = 0;
164 
165 void __kmps_set_nested( int arg ) {
166     i;
167     __kmps_nested = arg;
168 } // __kmps_set_nested
169 
170 int __kmps_get_nested( void ) {
171     i;
172     return __kmps_nested;
173 } // __kmps_get_nested
174 
175 static size_t __kmps_stacksize = KMP_DEFAULT_STKSIZE;
176 
177 void __kmps_set_stacksize( int arg ) {
178     i;
179     __kmps_stacksize = arg;
180 } // __kmps_set_stacksize
181 
182 int __kmps_get_stacksize( void ) {
183     i;
184     return __kmps_stacksize;
185 } // __kmps_get_stacksize
186 
187 static kmp_sched_t __kmps_sched_kind     = kmp_sched_default;
188 static int         __kmps_sched_modifier = 0;
189 
190     void __kmps_set_schedule( kmp_sched_t kind, int modifier ) {
191         i;
192         __kmps_sched_kind     = kind;
193         __kmps_sched_modifier = modifier;
194     } // __kmps_set_schedule
195 
196     void __kmps_get_schedule( kmp_sched_t *kind, int *modifier ) {
197         i;
198         *kind     = __kmps_sched_kind;
199         *modifier = __kmps_sched_modifier;
200     } // __kmps_get_schedule
201 
202 #if OMP_40_ENABLED
203 
204 static kmp_proc_bind_t __kmps_proc_bind = proc_bind_false;
205 
206 void __kmps_set_proc_bind( kmp_proc_bind_t arg ) {
207     i;
208     __kmps_proc_bind = arg;
209 } // __kmps_set_proc_bind
210 
211 kmp_proc_bind_t __kmps_get_proc_bind( void ) {
212     i;
213     return __kmps_proc_bind;
214 } // __kmps_get_proc_bind
215 
216 #endif /* OMP_40_ENABLED */
217 
218 double __kmps_get_wtime( void ) {
219     // Elapsed wall clock time (in second) from "sometime in the past".
220     double wtime = 0.0;
221     i;
222     #if KMP_OS_WINDOWS
223         if ( frequency > 0.0 ) {
224             LARGE_INTEGER now;
225             BOOL status = QueryPerformanceCounter( & now );
226             if ( status ) {
227                 wtime = double( now.QuadPart ) / frequency;
228             }; // if
229         }; // if
230     #else
231         // gettimeofday() returns seconds and microseconds since the Epoch.
232         struct timeval  tval;
233         int             rc;
234         rc = gettimeofday( & tval, NULL );
235         if ( rc == 0 ) {
236             wtime = (double)( tval.tv_sec ) + 1.0E-06 * (double)( tval.tv_usec );
237         } else {
238             // TODO: Assert or abort here.
239         }; // if
240     #endif
241     return wtime;
242 }; // __kmps_get_wtime
243 
244 double __kmps_get_wtick( void ) {
245     // Number of seconds between successive clock ticks.
246     double wtick = 0.0;
247     i;
248     #if KMP_OS_WINDOWS
249         {
250             DWORD increment;
251             DWORD adjustment;
252             BOOL  disabled;
253             BOOL  rc;
254             rc = GetSystemTimeAdjustment( & adjustment, & increment, & disabled );
255             if ( rc ) {
256                 wtick = 1.0E-07 * (double)( disabled ? increment : adjustment );
257             } else {
258                 // TODO: Assert or abort here.
259                 wtick = 1.0E-03;
260             }; // if
261         }
262     #else
263         // TODO: gettimeofday() returns in microseconds, but what the precision?
264         wtick = 1.0E-06;
265     #endif
266     return wtick;
267 }; // __kmps_get_wtick
268 
269 // end of file //
270 
271