StarPU Handbook
starpu_util.h
Go to the documentation of this file.
1 /* StarPU --- Runtime system for heterogeneous multicore architectures.
2  *
3  * Copyright (C) 2011-2012 Inria
4  * Copyright (C) 2008-2017 Université de Bordeaux
5  * Copyright (C) 2010-2017 CNRS
6  *
7  * StarPU is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as published by
9  * the Free Software Foundation; either version 2.1 of the License, or (at
10  * your option) any later version.
11  *
12  * StarPU is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15  *
16  * See the GNU Lesser General Public License in COPYING.LGPL for more details.
17  */
18 
19 #ifndef __STARPU_UTIL_H__
20 #define __STARPU_UTIL_H__
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26 
27 #include <starpu_config.h>
28 
29 #ifdef __GLIBC__
30 #include <execinfo.h>
31 #endif
32 
33 #ifdef __cplusplus
34 extern "C"
35 {
36 #endif
37 
38 #if defined __GNUC__ && defined __GNUC_MINOR__
39 # define STARPU_GNUC_PREREQ(maj, min) \
40  ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
41 #else
42 # define STARPU_GNUC_PREREQ(maj, min) 0
43 #endif
44 
45 #ifdef __GNUC__
46 # define STARPU_UNLIKELY(expr) (__builtin_expect(!!(expr),0))
47 # define STARPU_LIKELY(expr) (__builtin_expect(!!(expr),1))
48 # define STARPU_ATTRIBUTE_UNUSED __attribute__((unused))
49 # define STARPU_ATTRIBUTE_NORETURN __attribute__((noreturn))
50 # define STARPU_ATTRIBUTE_INTERNAL __attribute__ ((visibility ("internal")))
51 # define STARPU_ATTRIBUTE_MALLOC __attribute__((malloc))
52 # define STARPU_ATTRIBUTE_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
53 # define STARPU_ATTRIBUTE_PURE __attribute__((pure))
54 # define STARPU_ATTRIBUTE_ALIGNED(size) __attribute__((aligned(size)))
55 # define STARPU_ATTRIBUTE_FORMAT(type, string, first) __attribute__((format(type, string, first)))
56 #else
57 # define STARPU_UNLIKELY(expr) (expr)
58 # define STARPU_LIKELY(expr) (expr)
59 # define STARPU_ATTRIBUTE_UNUSED
60 # define STARPU_ATTRIBUTE_NORETURN
61 # define STARPU_ATTRIBUTE_INTERNAL
62 # define STARPU_ATTRIBUTE_MALLOC
63 # define STARPU_ATTRIBUTE_WARN_UNUSED_RESULT
64 # define STARPU_ATTRIBUTE_PURE
65 # define STARPU_ATTRIBUTE_ALIGNED(size)
66 # define STARPU_ATTRIBUTE_FORMAT(type, string, first)
67 #endif
68 
69 /* Note that if we're compiling C++, then just use the "inline"
70  keyword, since it's part of C++ */
71 #if defined(c_plusplus) || defined(__cplusplus)
72 # define STARPU_INLINE inline
73 #elif defined(_MSC_VER) || defined(__HP_cc)
74 # define STARPU_INLINE __inline
75 #else
76 # define STARPU_INLINE __inline__
77 #endif
78 
79 #if STARPU_GNUC_PREREQ(4, 3)
80 # define STARPU_ATTRIBUTE_CALLOC_SIZE(num,size) __attribute__((alloc_size(num,size)))
81 # define STARPU_ATTRIBUTE_ALLOC_SIZE(size) __attribute__((alloc_size(size)))
82 #else
83 # define STARPU_ATTRIBUTE_CALLOC_SIZE(num,size)
84 # define STARPU_ATTRIBUTE_ALLOC_SIZE(size)
85 #endif
86 
87 #if STARPU_GNUC_PREREQ(3, 1) && !defined(BUILDING_STARPU) && !defined(STARPU_USE_DEPRECATED_API) && !defined(STARPU_USE_DEPRECATED_ONE_ZERO_API)
88 #define STARPU_DEPRECATED __attribute__((__deprecated__))
89 #else
90 #define STARPU_DEPRECATED
91 #endif /* __GNUC__ */
92 
93 #if STARPU_GNUC_PREREQ(3,3)
94 #define STARPU_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
95 #else
96 #define STARPU_WARN_UNUSED_RESULT
97 #endif /* __GNUC__ */
98 
99 #define STARPU_POISON_PTR ((void *)0xdeadbeef)
100 
101 #define STARPU_MIN(a,b) ((a)<(b)?(a):(b))
102 #define STARPU_MAX(a,b) ((a)<(b)?(b):(a))
103 
104 #define STARPU_BACKTRACE_LENGTH 32
105 #ifdef __GLIBC__
106 # define STARPU_DUMP_BACKTRACE() do { \
107  void *__ptrs[STARPU_BACKTRACE_LENGTH]; \
108  int __n = backtrace(__ptrs, STARPU_BACKTRACE_LENGTH); \
109  backtrace_symbols_fd(__ptrs, __n, 2); \
110 } while (0)
111 #else
112 # define STARPU_DUMP_BACKTRACE() do { } while (0)
113 #endif
114 
115 #ifdef STARPU_NO_ASSERT
116 #define STARPU_ASSERT(x) do { if (0) { (void) (x); } } while(0)
117 #define STARPU_ASSERT_ACCESSIBLE(x) do { if (0) { (void) (x); } } while(0)
118 #define STARPU_ASSERT_MSG(x, msg, ...) do { if (0) { (void) (x); (void) msg; } } while(0)
119 #else
120 # if defined(__CUDACC__) && defined(STARPU_HAVE_WINDOWS)
121 # define STARPU_ASSERT(x) do { if (STARPU_UNLIKELY(!(x))) { STARPU_DUMP_BACKTRACE(); *(int*)NULL = 0; } } while(0)
122 # define STARPU_ASSERT_MSG(x, msg, ...) do { if (STARPU_UNLIKELY(!(x))) { STARPU_DUMP_BACKTRACE(); fprintf(stderr, "\n[starpu][%s][assert failure] " msg "\n\n", __starpu_func__, ## __VA_ARGS__); *(int*)NULL = 0; }} while(0)
123 # else
124 # define STARPU_ASSERT(x) do { if (STARPU_UNLIKELY(!(x))) { STARPU_DUMP_BACKTRACE(); assert(x); } } while (0)
125 # define STARPU_ASSERT_MSG(x, msg, ...) do { if (STARPU_UNLIKELY(!(x))) { STARPU_DUMP_BACKTRACE(); fprintf(stderr, "\n[starpu][%s][assert failure] " msg "\n\n", __starpu_func__, ## __VA_ARGS__); assert(x); } } while(0)
126 
127 # endif
128 # define STARPU_ASSERT_ACCESSIBLE(ptr) do { \
129  volatile char __c STARPU_ATTRIBUTE_UNUSED = *(char*) (ptr); \
130 } while(0)
131 #endif
132 
133 #ifdef __APPLE_CC__
134 # define _starpu_abort() *(volatile int*)NULL = 0
135 #else
136 # define _starpu_abort() abort()
137 #endif
138 
139 #define STARPU_ABORT() do { \
140  STARPU_DUMP_BACKTRACE(); \
141  fprintf(stderr, "[starpu][abort][%s()@%s:%d]\n", __starpu_func__, __FILE__, __LINE__); \
142  _starpu_abort(); \
143 } while(0)
144 
145 #define STARPU_ABORT_MSG(msg, ...) do { \
146  STARPU_DUMP_BACKTRACE(); \
147  fprintf(stderr, "[starpu][abort][%s()@%s:%d] " msg "\n", __starpu_func__, __FILE__, __LINE__, ## __VA_ARGS__); \
148  _starpu_abort(); \
149 } while(0)
150 
151 #if defined(STARPU_HAVE_STRERROR_R)
152 #if (! defined(__GLIBC__) || !__GLIBC__) || ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && (! defined(_GNU_SOURCE)))
153 /* XSI-compliant version of strerror_r returns an int */
154 #define starpu_strerror_r(errnum, buf, buflen) \
155  do \
156  { \
157  int _ret = strerror_r((errnum), (buf), (buflen)); \
158  STARPU_ASSERT(_ret == 0); \
159  } \
160  while (0)
161 #else
162 /* GNU-specific version of strerror_r returns a char * */
163 #define starpu_strerror_r(errnum, buf, buflen) \
164  do \
165  { \
166  char * const _user_buf = (buf); \
167  const size_t _user_buflen = (buflen); \
168  /* the GNU-specific behaviour when 'buf' == NULL cannot be emulated with the XSI-compliant version */ \
169  STARPU_ASSERT((buf) != NULL); \
170  char * _tmp_buf = strerror_r((errnum), _user_buf, _user_buflen); \
171  if (_tmp_buf != _user_buf) \
172  { \
173  if (_user_buflen > 0) \
174  { \
175  strncpy(_user_buf, _tmp_buf, _user_buflen); \
176  _user_buf[_user_buflen-1] = '\0'; \
177  } \
178  } \
179  } \
180  while (0)
181 #endif /* strerror_r ABI version */
182 
183 # define STARPU_CHECK_RETURN_VALUE(err, message, ...) {if (STARPU_UNLIKELY(err != 0)) { \
184  char xmessage[256]; starpu_strerror_r(-err, xmessage, 256); \
185  fprintf(stderr, "[starpu] Unexpected value: <%d:%s> returned for " message "\n", err, xmessage, ## __VA_ARGS__); \
186  STARPU_ABORT(); }}
187 # define STARPU_CHECK_RETURN_VALUE_IS(err, value, message, ...) {if (STARPU_UNLIKELY(err != value)) { \
188  char xmessage[256]; starpu_strerror_r(-err, xmessage, 256); \
189  fprintf(stderr, "[starpu] Unexpected value: <%d!=%d:%s> returned for " message "\n", err, value, xmessage, ## __VA_ARGS__); \
190  STARPU_ABORT(); }}
191 #else
192 # define STARPU_CHECK_RETURN_VALUE(err, message, ...) {if (STARPU_UNLIKELY(err != 0)) { \
193  fprintf(stderr, "[starpu] Unexpected value: <%d> returned for " message "\n", err, ## __VA_ARGS__); \
194  STARPU_ABORT(); }}
195 # define STARPU_CHECK_RETURN_VALUE_IS(err, value, message, ...) {if (STARPU_UNLIKELY(err != value)) { \
196  fprintf(stderr, "[starpu] Unexpected value: <%d != %d> returned for " message "\n", err, value, ## __VA_ARGS__); \
197  STARPU_ABORT(); }}
198 #endif /* STARPU_HAVE_STRERROR_R */
199 
200 #if defined(__i386__) || defined(__x86_64__)
201 
202 static __starpu_inline unsigned starpu_cmpxchg(unsigned *ptr, unsigned old, unsigned next)
203 {
204  __asm__ __volatile__("lock cmpxchgl %2,%1": "+a" (old), "+m" (*ptr) : "q" (next) : "memory");
205  return old;
206 }
207 static __starpu_inline unsigned starpu_xchg(unsigned *ptr, unsigned next)
208 {
209  /* Note: xchg is always locked already */
210  __asm__ __volatile__("xchgl %1,%0": "+m" (*ptr), "+q" (next) : : "memory");
211  return next;
212 }
213 #define STARPU_HAVE_XCHG
214 
215 #if defined(__i386__)
216 static __starpu_inline unsigned long starpu_cmpxchgl(unsigned long *ptr, unsigned long old, unsigned long next)
217 {
218  __asm__ __volatile__("lock cmpxchgl %2,%1": "+a" (old), "+m" (*ptr) : "q" (next) : "memory");
219  return old;
220 }
221 static __starpu_inline unsigned long starpu_xchgl(unsigned long *ptr, unsigned long next)
222 {
223  /* Note: xchg is always locked already */
224  __asm__ __volatile__("xchgl %1,%0": "+m" (*ptr), "+q" (next) : : "memory");
225  return next;
226 }
227 #define STARPU_HAVE_XCHGL
228 #endif
229 
230 #if defined(__x86_64__)
231 static __starpu_inline unsigned long starpu_cmpxchgl(unsigned long *ptr, unsigned long old, unsigned long next)
232 {
233  __asm__ __volatile__("lock cmpxchgq %2,%1": "+a" (old), "+m" (*ptr) : "q" (next) : "memory");
234  return old;
235 }
236 static __starpu_inline unsigned long starpu_xchgl(unsigned long *ptr, unsigned long next)
237 {
238  /* Note: xchg is always locked already */
239  __asm__ __volatile__("xchgq %1,%0": "+m" (*ptr), "+q" (next) : : "memory");
240  return next;
241 }
242 #define STARPU_HAVE_XCHGL
243 #endif
244 
245 #endif
246 
247 #define STARPU_ATOMIC_SOMETHING(name,expr) \
248 static __starpu_inline unsigned starpu_atomic_##name(unsigned *ptr, unsigned value) \
249 { \
250  unsigned old, next; \
251  while (1) \
252  { \
253  old = *ptr; \
254  next = expr; \
255  if (starpu_cmpxchg(ptr, old, next) == old) \
256  break; \
257  }; \
258  return expr; \
259 }
260 #define STARPU_ATOMIC_SOMETHINGL(name,expr) \
261 static __starpu_inline unsigned long starpu_atomic_##name##l(unsigned long *ptr, unsigned long value) \
262 { \
263  unsigned long old, next; \
264  while (1) \
265  { \
266  old = *ptr; \
267  next = expr; \
268  if (starpu_cmpxchgl(ptr, old, next) == old) \
269  break; \
270  }; \
271  return expr; \
272 }
273 
274 #ifdef STARPU_HAVE_SYNC_FETCH_AND_ADD
275 #define STARPU_ATOMIC_ADD(ptr, value) (__sync_fetch_and_add ((ptr), (value)) + (value))
276 #define STARPU_ATOMIC_ADDL(ptr, value) (__sync_fetch_and_add ((ptr), (value)) + (value))
277 #else
278 #if defined(STARPU_HAVE_XCHG)
279 STARPU_ATOMIC_SOMETHING(add, old + value)
280 #define STARPU_ATOMIC_ADD(ptr, value) starpu_atomic_add(ptr, value)
281 #endif
282 #if defined(STARPU_HAVE_XCHGL)
283 STARPU_ATOMIC_SOMETHINGL(add, old + value)
284 #define STARPU_ATOMIC_ADDL(ptr, value) starpu_atomic_addl(ptr, value)
285 #endif
286 #endif
287 
288 #ifdef STARPU_HAVE_SYNC_FETCH_AND_OR
289 #define STARPU_ATOMIC_OR(ptr, value) (__sync_fetch_and_or ((ptr), (value)))
290 #define STARPU_ATOMIC_ORL(ptr, value) (__sync_fetch_and_or ((ptr), (value)))
291 #else
292 #if defined(STARPU_HAVE_XCHG)
293 STARPU_ATOMIC_SOMETHING(or, old | value)
294 #define STARPU_ATOMIC_OR(ptr, value) starpu_atomic_or(ptr, value)
295 #endif
296 #if defined(STARPU_HAVE_XCHGL)
297 STARPU_ATOMIC_SOMETHINGL(or, old | value)
298 #define STARPU_ATOMIC_ORL(ptr, value) starpu_atomic_orl(ptr, value)
299 #endif
300 #endif
301 
302 #ifdef STARPU_HAVE_SYNC_BOOL_COMPARE_AND_SWAP
303 #define STARPU_BOOL_COMPARE_AND_SWAP(ptr, old, value) (__sync_bool_compare_and_swap ((ptr), (old), (value)))
304 #elif defined(STARPU_HAVE_XCHG)
305 #define STARPU_BOOL_COMPARE_AND_SWAP(ptr, old, value) (starpu_cmpxchg((ptr), (old), (value)) == (old))
306 #endif
307 
308 #ifdef STARPU_HAVE_SYNC_VAL_COMPARE_AND_SWAP
309 #define STARPU_VAL_COMPARE_AND_SWAP(ptr, old, value) (__sync_val_compare_and_swap ((ptr), (old), (value)))
310 #elif defined(STARPU_HAVE_XCHG)
311 #define STARPU_VAL_COMPARE_AND_SWAP(ptr, old, value) (starpu_cmpxchg((ptr), (old), (value)))
312 #endif
313 
314 #ifdef STARPU_HAVE_SYNC_LOCK_TEST_AND_SET
315 #define STARPU_TEST_AND_SET(ptr, value) (__sync_lock_test_and_set ((ptr), (value)))
316 #define STARPU_RELEASE(ptr) (__sync_lock_release ((ptr)))
317 #elif defined(STARPU_HAVE_XCHG)
318 #define STARPU_TEST_AND_SET(ptr, value) (starpu_xchg((ptr), (value)))
319 #define STARPU_RELEASE(ptr) (starpu_xchg((ptr), 0))
320 #endif
321 
322 #ifdef STARPU_HAVE_SYNC_SYNCHRONIZE
323 #define STARPU_SYNCHRONIZE() __sync_synchronize()
324 #elif defined(__i386__)
325 #define STARPU_SYNCHRONIZE() __asm__ __volatile__("lock; addl $0,0(%%esp)" ::: "memory")
326 #elif defined(__KNC__) || defined(__KNF__)
327 #define STARPU_SYNCHRONIZE() __asm__ __volatile__("lock; addl $0,0(%%rsp)" ::: "memory")
328 #elif defined(__x86_64__)
329 #define STARPU_SYNCHRONIZE() __asm__ __volatile__("mfence" ::: "memory")
330 #elif defined(__ppc__) || defined(__ppc64__)
331 #define STARPU_SYNCHRONIZE() __asm__ __volatile__("sync" ::: "memory")
332 #endif
333 
334 #if defined(__i386__)
335 #define STARPU_RMB() __asm__ __volatile__("lock; addl $0,0(%%esp)" ::: "memory")
336 #define STARPU_WMB() __asm__ __volatile__("lock; addl $0,0(%%esp)" ::: "memory")
337 #elif defined(__KNC__) || defined(__KNF__)
338 #define STARPU_RMB() __asm__ __volatile__("lock; addl $0,0(%%rsp)" ::: "memory")
339 #define STARPU_WMB() __asm__ __volatile__("lock; addl $0,0(%%rsp)" ::: "memory")
340 #elif defined(__x86_64__)
341 #define STARPU_RMB() __asm__ __volatile__("lfence" ::: "memory")
342 #define STARPU_WMB() __asm__ __volatile__("sfence" ::: "memory")
343 #elif defined(__ppc__) || defined(__ppc64__)
344 #define STARPU_RMB() __asm__ __volatile__("sync" ::: "memory")
345 #define STARPU_WMB() __asm__ __volatile__("sync" ::: "memory")
346 #else
347 #define STARPU_RMB() STARPU_SYNCHRONIZE()
348 #define STARPU_WMB() STARPU_SYNCHRONIZE()
349 #endif
350 
351 #ifdef __cplusplus
352 }
353 #endif
354 
355 /* Include this only here so that <starpu_data_interfaces.h> can use the
356  * macros above. */
357 #include <starpu_task.h>
358 
359 #ifdef __cplusplus
360 extern "C"
361 {
362 #endif
363 
364 extern int _starpu_silent;
365 
366 char *starpu_getenv(const char *str);
367 
368 
369 static __starpu_inline int starpu_get_env_number(const char *str)
370 {
371  char *strval;
372 
373  strval = starpu_getenv(str);
374  if (strval)
375  {
376  /* the env variable was actually set */
377  long int val;
378  char *check;
379 
380  val = strtol(strval, &check, 10);
381  if (*check) {
382  fprintf(stderr,"The %s environment variable must contain an integer\n", str);
383  STARPU_ABORT();
384  }
385 
386  /* fprintf(stderr, "ENV %s WAS %d\n", str, val); */
387  STARPU_ASSERT_MSG(val >= 0, "The value for the environment variable '%s' cannot be negative", str);
388  return (int)val;
389  }
390  else
391  {
392  /* there is no such env variable */
393  /* fprintf("There was no %s ENV\n", str); */
394  return -1;
395  }
396 }
397 
398 static __starpu_inline int starpu_get_env_number_default(const char *str, int defval)
399 {
400  int ret = starpu_get_env_number(str);
401  if (ret == -1)
402  ret = defval;
403  return ret;
404 }
405 
406 static __starpu_inline float starpu_get_env_float_default(const char *str, float defval)
407 {
408  char *strval;
409 
410  strval = starpu_getenv(str);
411  if (strval)
412  {
413  /* the env variable was actually set */
414  float val;
415  char *check;
416 
417  val = strtof(strval, &check);
418  if (*check) {
419  fprintf(stderr,"The %s environment variable must contain a float\n", str);
420  STARPU_ABORT();
421  }
422 
423  /* fprintf(stderr, "ENV %s WAS %f\n", str, val); */
424  return val;
425  }
426  else
427  {
428  /* there is no such env variable */
429  /* fprintf("There was no %s ENV\n", str); */
430  return defval;
431  }
432 }
433 
434 void starpu_execute_on_each_worker(void (*func)(void *), void *arg, uint32_t where);
435 
436 void starpu_execute_on_each_worker_ex(void (*func)(void *), void *arg, uint32_t where, const char *name);
437 
438 void starpu_execute_on_specific_workers(void (*func)(void*), void *arg, unsigned num_workers, unsigned *workers, const char *name);
439 
440 int starpu_data_cpy(starpu_data_handle_t dst_handle, starpu_data_handle_t src_handle, int asynchronous, void (*callback_func)(void*), void *callback_arg);
441 
442 double starpu_timing_now(void);
443 
444 #ifdef _WIN32
445 /* Try to fetch the system definition of timespec */
446 #include <sys/types.h>
447 #include <sys/stat.h>
448 #ifdef HAVE_UNISTD_H
449 #include <unistd.h>
450 #endif
451 #include <time.h>
452 #if !defined(_MSC_VER) || defined(BUILDING_STARPU)
453 #include <pthread.h>
454 #endif
455 #if !defined(STARPU_HAVE_STRUCT_TIMESPEC) || (defined(_MSC_VER) && _MSC_VER < 1900)
456 /* If it didn't get defined in the standard places, then define it ourself */
457 #ifndef STARPU_TIMESPEC_DEFINED
458 #define STARPU_TIMESPEC_DEFINED 1
459 struct timespec
460 {
461  time_t tv_sec; /* Seconds */
462  long tv_nsec; /* Nanoseconds */
463 };
464 #endif /* STARPU_TIMESPEC_DEFINED */
465 #endif /* STARPU_HAVE_STRUCT_TIMESPEC */
466 /* Fetch gettimeofday on mingw/cygwin */
467 #if defined(__MINGW32__) || defined(__CYGWIN__)
468 #include <sys/time.h>
469 #endif
470 #else
471 #include <sys/time.h>
472 #endif /* _WIN32 */
473 
474 #ifdef __cplusplus
475 }
476 #endif
477 
478 #endif /* __STARPU_UTIL_H__ */
double starpu_timing_now(void)
void starpu_execute_on_specific_workers(void(*func)(void *), void *arg, unsigned num_workers, unsigned *workers, const char *name)
#define STARPU_ASSERT_MSG(x, msg,...)
Definition: starpu_util.h:125
static __starpu_inline int starpu_get_env_number(const char *str)
Definition: starpu_util.h:369
int starpu_data_cpy(starpu_data_handle_t dst_handle, starpu_data_handle_t src_handle, int asynchronous, void(*callback_func)(void *), void *callback_arg)
void starpu_execute_on_each_worker_ex(void(*func)(void *), void *arg, uint32_t where, const char *name)
struct _starpu_data_state * starpu_data_handle_t
Definition: starpu_data.h:30
#define STARPU_ABORT()
Definition: starpu_util.h:139
void starpu_execute_on_each_worker(void(*func)(void *), void *arg, uint32_t where)