thread.c 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2010-2020 Université de Bordeaux, CNRS (LaBRI UMR 5800), Inria
  4. *
  5. * StarPU is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU Lesser General Public License as published by
  7. * the Free Software Foundation; either version 2.1 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * StarPU is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. *
  14. * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  15. */
  16. #include <starpu.h>
  17. #include <core/simgrid.h>
  18. #ifdef STARPU_DEBUG
  19. #include <core/workers.h>
  20. #endif
  21. #include <common/thread.h>
  22. #include <common/fxt.h>
  23. #include <common/timing.h>
  24. #include <errno.h>
  25. #include <limits.h>
  26. #ifdef STARPU_SIMGRID
  27. #ifdef STARPU_HAVE_SIMGRID_MUTEX_H
  28. #include <simgrid/mutex.h>
  29. #include <simgrid/cond.h>
  30. #elif defined(STARPU_HAVE_XBT_SYNCHRO_H)
  31. #include <xbt/synchro.h>
  32. #else
  33. #include <xbt/synchro_core.h>
  34. #endif
  35. #include <smpi/smpi.h>
  36. #include <simgrid/simix.h>
  37. #else
  38. #if defined(STARPU_LINUX_SYS) && defined(STARPU_HAVE_XCHG)
  39. #include <linux/futex.h>
  40. #include <sys/syscall.h>
  41. /* Private futexes are not so old, cope with old kernels. */
  42. #ifdef FUTEX_WAIT_PRIVATE
  43. static int _starpu_futex_wait = FUTEX_WAIT_PRIVATE;
  44. static int _starpu_futex_wake = FUTEX_WAKE_PRIVATE;
  45. #else
  46. static int _starpu_futex_wait = FUTEX_WAIT;
  47. static int _starpu_futex_wake = FUTEX_WAKE;
  48. #endif
  49. #endif
  50. #endif /* !STARPU_SIMGRID */
  51. #ifdef STARPU_SIMGRID
  52. extern int _starpu_simgrid_thread_start(int argc, char *argv[]);
  53. int starpu_pthread_equal(starpu_pthread_t t1, starpu_pthread_t t2)
  54. {
  55. return t1 == t2;
  56. }
  57. starpu_pthread_t starpu_pthread_self(void)
  58. {
  59. #ifdef HAVE_SG_ACTOR_SELF
  60. return sg_actor_self();
  61. #else
  62. return MSG_process_self();
  63. #endif
  64. }
  65. int starpu_pthread_create_on(const char *name, starpu_pthread_t *thread, const starpu_pthread_attr_t *attr STARPU_ATTRIBUTE_UNUSED, void *(*start_routine) (void *), void *arg, starpu_sg_host_t host)
  66. {
  67. char **_args;
  68. _STARPU_MALLOC(_args, 3*sizeof(char*));
  69. asprintf(&_args[0], "%p", start_routine);
  70. asprintf(&_args[1], "%p", arg);
  71. _args[2] = NULL;
  72. if (!host)
  73. host = _starpu_simgrid_get_host_by_name("MAIN");
  74. void *tsd;
  75. _STARPU_CALLOC(tsd, MAX_TSD+1, sizeof(void*));
  76. #ifndef HAVE_SG_ACTOR_SET_STACKSIZE
  77. if (attr && attr->stacksize)
  78. _starpu_simgrid_set_stack_size(attr->stacksize);
  79. #endif
  80. #ifdef HAVE_SG_ACTOR_INIT
  81. *thread= sg_actor_init(name, host);
  82. #ifdef HAVE_SG_ACTOR_SET_STACKSIZE
  83. if (attr && attr->stacksize)
  84. sg_actor_set_stacksize(*thread, attr->stacksize);
  85. #endif
  86. #ifdef HAVE_SG_ACTOR_SET_DATA
  87. sg_actor_set_data(*thread, tsd);
  88. #else
  89. sg_actor_data_set(*thread, tsd);
  90. #endif
  91. sg_actor_start(*thread, _starpu_simgrid_thread_start, 2, _args);
  92. #else
  93. *thread = MSG_process_create_with_arguments(name, _starpu_simgrid_thread_start, tsd, host, 2, _args);
  94. #ifdef HAVE_SG_ACTOR_DATA
  95. #ifdef HAVE_SG_ACTOR_SET_DATA
  96. sg_actor_set_data(*thread, tsd);
  97. #else
  98. sg_actor_data_set(*thread, tsd);
  99. #endif
  100. #endif
  101. #endif
  102. #ifndef HAVE_SG_ACTOR_SET_STACKSIZE
  103. if (attr && attr->stacksize)
  104. _starpu_simgrid_set_stack_size(_starpu_default_stack_size);
  105. #endif
  106. #if SIMGRID_VERSION >= 31500 && SIMGRID_VERSION != 31559
  107. # ifdef HAVE_SG_ACTOR_REF
  108. sg_actor_ref(*thread);
  109. # else
  110. MSG_process_ref(*thread);
  111. # endif
  112. #endif
  113. return 0;
  114. }
  115. int starpu_pthread_create(starpu_pthread_t *thread, const starpu_pthread_attr_t *attr, void *(*start_routine) (void *), void *arg)
  116. {
  117. return starpu_pthread_create_on("", thread, attr, start_routine, arg, NULL);
  118. }
  119. int starpu_pthread_join(starpu_pthread_t thread STARPU_ATTRIBUTE_UNUSED, void **retval STARPU_ATTRIBUTE_UNUSED)
  120. {
  121. #if SIMGRID_VERSION >= 31400
  122. # ifdef STARPU_HAVE_SIMGRID_ACTOR_H
  123. sg_actor_join(thread, 1000000);
  124. # else
  125. MSG_process_join(thread, 1000000);
  126. # endif
  127. #if SIMGRID_VERSION >= 31500 && SIMGRID_VERSION != 31559
  128. # ifdef HAVE_SG_ACTOR_REF
  129. sg_actor_unref(thread);
  130. # else
  131. MSG_process_unref(thread);
  132. # endif
  133. #endif
  134. #else
  135. starpu_sleep(1);
  136. #endif
  137. return 0;
  138. }
  139. int starpu_pthread_exit(void *retval STARPU_ATTRIBUTE_UNUSED)
  140. {
  141. #ifdef HAVE_SG_ACTOR_SELF
  142. sg_actor_kill(sg_actor_self());
  143. #else
  144. MSG_process_kill(MSG_process_self());
  145. #endif
  146. STARPU_ABORT_MSG("MSG_process_kill(MSG_process_self()) returned?!");
  147. }
  148. int starpu_pthread_attr_init(starpu_pthread_attr_t *attr)
  149. {
  150. attr->stacksize = 0;
  151. return 0;
  152. }
  153. int starpu_pthread_attr_destroy(starpu_pthread_attr_t *attr STARPU_ATTRIBUTE_UNUSED)
  154. {
  155. return 0;
  156. }
  157. int starpu_pthread_attr_setstacksize(starpu_pthread_attr_t *attr, size_t stacksize)
  158. {
  159. attr->stacksize = stacksize;
  160. return 0;
  161. }
  162. int starpu_pthread_attr_setdetachstate(starpu_pthread_attr_t *attr STARPU_ATTRIBUTE_UNUSED, int detachstate STARPU_ATTRIBUTE_UNUSED)
  163. {
  164. return 0;
  165. }
  166. int starpu_pthread_mutex_init(starpu_pthread_mutex_t *mutex, const starpu_pthread_mutexattr_t *mutexattr STARPU_ATTRIBUTE_UNUSED)
  167. {
  168. #ifdef STARPU_HAVE_SIMGRID_MUTEX_H
  169. *mutex = sg_mutex_init();
  170. #else
  171. *mutex = xbt_mutex_init();
  172. #endif
  173. return 0;
  174. }
  175. int starpu_pthread_mutex_destroy(starpu_pthread_mutex_t *mutex)
  176. {
  177. if (*mutex)
  178. #ifdef STARPU_HAVE_SIMGRID_MUTEX_H
  179. sg_mutex_destroy(*mutex);
  180. #else
  181. xbt_mutex_destroy(*mutex);
  182. #endif
  183. return 0;
  184. }
  185. int starpu_pthread_mutex_lock(starpu_pthread_mutex_t *mutex)
  186. {
  187. _STARPU_TRACE_LOCKING_MUTEX();
  188. /* Note: this is actually safe, because simgrid only preempts within
  189. * simgrid functions */
  190. if (!*mutex)
  191. {
  192. /* Here we may get preempted */
  193. #ifdef STARPU_HAVE_SIMGRID_MUTEX_H
  194. sg_mutex_t new_mutex = sg_mutex_init();
  195. #else
  196. xbt_mutex_t new_mutex = xbt_mutex_init();
  197. #endif
  198. if (!*mutex)
  199. *mutex = new_mutex;
  200. else
  201. /* Somebody already initialized it while we were
  202. * calling sg_mutex_init, this one is now useless */
  203. #ifdef STARPU_HAVE_SIMGRID_MUTEX_H
  204. sg_mutex_destroy(new_mutex);
  205. #else
  206. xbt_mutex_destroy(new_mutex);
  207. #endif
  208. }
  209. #ifdef STARPU_HAVE_SIMGRID_MUTEX_H
  210. sg_mutex_lock(*mutex);
  211. #else
  212. xbt_mutex_acquire(*mutex);
  213. #endif
  214. _STARPU_TRACE_MUTEX_LOCKED();
  215. return 0;
  216. }
  217. int starpu_pthread_mutex_unlock(starpu_pthread_mutex_t *mutex)
  218. {
  219. _STARPU_TRACE_UNLOCKING_MUTEX();
  220. #ifdef STARPU_HAVE_SIMGRID_MUTEX_H
  221. sg_mutex_unlock(*mutex);
  222. #else
  223. xbt_mutex_release(*mutex);
  224. #endif
  225. _STARPU_TRACE_MUTEX_UNLOCKED();
  226. return 0;
  227. }
  228. int starpu_pthread_mutex_trylock(starpu_pthread_mutex_t *mutex)
  229. {
  230. int ret;
  231. _STARPU_TRACE_TRYLOCK_MUTEX();
  232. #ifdef STARPU_HAVE_SIMGRID_MUTEX_H
  233. ret = sg_mutex_try_lock(*mutex);
  234. #elif defined(HAVE_XBT_MUTEX_TRY_ACQUIRE) || defined(xbt_mutex_try_acquire)
  235. ret = xbt_mutex_try_acquire(*mutex);
  236. #else
  237. ret = simcall_mutex_trylock((smx_mutex_t)*mutex);
  238. #endif
  239. ret = ret ? 0 : EBUSY;
  240. _STARPU_TRACE_MUTEX_LOCKED();
  241. return ret;
  242. }
  243. int starpu_pthread_mutexattr_gettype(const starpu_pthread_mutexattr_t *attr STARPU_ATTRIBUTE_UNUSED, int *type STARPU_ATTRIBUTE_UNUSED)
  244. {
  245. return 0;
  246. }
  247. int starpu_pthread_mutexattr_settype(starpu_pthread_mutexattr_t *attr STARPU_ATTRIBUTE_UNUSED, int type STARPU_ATTRIBUTE_UNUSED)
  248. {
  249. return 0;
  250. }
  251. int starpu_pthread_mutexattr_destroy(starpu_pthread_mutexattr_t *attr STARPU_ATTRIBUTE_UNUSED)
  252. {
  253. return 0;
  254. }
  255. int starpu_pthread_mutexattr_init(starpu_pthread_mutexattr_t *attr STARPU_ATTRIBUTE_UNUSED)
  256. {
  257. return 0;
  258. }
  259. /* Indexed by key-1 */
  260. static int used_key[MAX_TSD];
  261. int starpu_pthread_key_create(starpu_pthread_key_t *key, void (*destr_function) (void *) STARPU_ATTRIBUTE_UNUSED)
  262. {
  263. unsigned i;
  264. /* Note: no synchronization here, we are actually monothreaded anyway. */
  265. for (i = 0; i < MAX_TSD; i++)
  266. {
  267. if (!used_key[i])
  268. {
  269. used_key[i] = 1;
  270. break;
  271. }
  272. }
  273. STARPU_ASSERT(i < MAX_TSD);
  274. /* key 0 is for process pointer argument */
  275. *key = i+1;
  276. return 0;
  277. }
  278. int starpu_pthread_key_delete(starpu_pthread_key_t key)
  279. {
  280. used_key[key-1] = 0;
  281. return 0;
  282. }
  283. /* We need it only when using smpi */
  284. #pragma weak smpi_process_get_user_data
  285. #if !HAVE_DECL_SMPI_PROCESS_SET_USER_DATA && !defined(smpi_process_get_user_data)
  286. extern void *smpi_process_get_user_data();
  287. #endif
  288. int starpu_pthread_setspecific(starpu_pthread_key_t key, const void *pointer)
  289. {
  290. void **array;
  291. #ifdef HAVE_SG_ACTOR_GET_DATA
  292. array = sg_actor_get_data(sg_actor_self());
  293. #elif defined(HAVE_SG_ACTOR_DATA)
  294. array = sg_actor_data(sg_actor_self());
  295. #else
  296. #if defined(HAVE_SMPI_PROCESS_SET_USER_DATA) || defined(smpi_process_get_user_data)
  297. #if defined(HAVE_MSG_PROCESS_SELF_NAME) || defined(MSG_process_self_name)
  298. const char *process_name = MSG_process_self_name();
  299. #else
  300. const char *process_name = SIMIX_process_self_get_name();
  301. #endif
  302. char *end;
  303. /* Test whether it is an MPI rank */
  304. strtol(process_name, &end, 10);
  305. if (!*end || !strcmp(process_name, "wait for mpi transfer") ||
  306. (!strcmp(process_name, "main") && _starpu_simgrid_running_smpi()))
  307. /* Special-case the SMPI process */
  308. array = smpi_process_get_user_data();
  309. else
  310. #endif
  311. array = MSG_process_get_data(MSG_process_self());
  312. #endif
  313. array[key] = (void*) pointer;
  314. return 0;
  315. }
  316. void* starpu_pthread_getspecific(starpu_pthread_key_t key)
  317. {
  318. void **array;
  319. #ifdef HAVE_SG_ACTOR_GET_DATA
  320. array = sg_actor_get_data(sg_actor_self());
  321. #elif defined(HAVE_SG_ACTOR_DATA)
  322. array = sg_actor_data(sg_actor_self());
  323. #else
  324. #if defined(HAVE_SMPI_PROCESS_SET_USER_DATA) || defined(smpi_process_get_user_data)
  325. #if defined(HAVE_MSG_PROCESS_SELF_NAME) || defined(MSG_process_self_name)
  326. const char *process_name = MSG_process_self_name();
  327. #else
  328. const char *process_name = SIMIX_process_self_get_name();
  329. #endif
  330. char *end;
  331. /* Test whether it is an MPI rank */
  332. strtol(process_name, &end, 10);
  333. if (!*end || !strcmp(process_name, "wait for mpi transfer") ||
  334. (!strcmp(process_name, "main") && _starpu_simgrid_running_smpi()))
  335. /* Special-case the SMPI processes */
  336. array = smpi_process_get_user_data();
  337. else
  338. #endif
  339. array = MSG_process_get_data(MSG_process_self());
  340. #endif
  341. if (!array)
  342. return NULL;
  343. return array[key];
  344. }
  345. int starpu_pthread_cond_init(starpu_pthread_cond_t *cond, starpu_pthread_condattr_t *cond_attr STARPU_ATTRIBUTE_UNUSED)
  346. {
  347. #ifdef STARPU_HAVE_SIMGRID_COND_H
  348. *cond = sg_cond_init();
  349. #else
  350. *cond = xbt_cond_init();
  351. #endif
  352. return 0;
  353. }
  354. static void _starpu_pthread_cond_auto_init(starpu_pthread_cond_t *cond)
  355. {
  356. /* Note: this is actually safe, because simgrid only preempts within
  357. * simgrid functions */
  358. if (!*cond)
  359. {
  360. /* Here we may get preempted */
  361. #ifdef STARPU_HAVE_SIMGRID_COND_H
  362. sg_cond_t new_cond = sg_cond_init();
  363. #else
  364. xbt_cond_t new_cond = xbt_cond_init();
  365. #endif
  366. if (!*cond)
  367. *cond = new_cond;
  368. else
  369. /* Somebody already initialized it while we were
  370. * calling xbt_cond_init, this one is now useless */
  371. #ifdef STARPU_HAVE_SIMGRID_COND_H
  372. sg_cond_destroy(new_cond);
  373. #else
  374. xbt_cond_destroy(new_cond);
  375. #endif
  376. }
  377. }
  378. int starpu_pthread_cond_signal(starpu_pthread_cond_t *cond)
  379. {
  380. _starpu_pthread_cond_auto_init(cond);
  381. #ifdef STARPU_HAVE_SIMGRID_COND_H
  382. sg_cond_notify_one(*cond);
  383. #else
  384. xbt_cond_signal(*cond);
  385. #endif
  386. return 0;
  387. }
  388. int starpu_pthread_cond_broadcast(starpu_pthread_cond_t *cond)
  389. {
  390. _starpu_pthread_cond_auto_init(cond);
  391. #ifdef STARPU_HAVE_SIMGRID_COND_H
  392. sg_cond_notify_all(*cond);
  393. #else
  394. xbt_cond_broadcast(*cond);
  395. #endif
  396. return 0;
  397. }
  398. int starpu_pthread_cond_wait(starpu_pthread_cond_t *cond, starpu_pthread_mutex_t *mutex)
  399. {
  400. _STARPU_TRACE_COND_WAIT_BEGIN();
  401. _starpu_pthread_cond_auto_init(cond);
  402. #ifdef STARPU_HAVE_SIMGRID_COND_H
  403. sg_cond_wait(*cond, *mutex);
  404. #else
  405. xbt_cond_wait(*cond, *mutex);
  406. #endif
  407. _STARPU_TRACE_COND_WAIT_END();
  408. return 0;
  409. }
  410. int starpu_pthread_cond_timedwait(starpu_pthread_cond_t *cond, starpu_pthread_mutex_t *mutex, const struct timespec *abstime)
  411. {
  412. #if SIMGRID_VERSION >= 31800
  413. struct timespec now, delta;
  414. double delay;
  415. int ret = 0;
  416. _starpu_clock_gettime(&now);
  417. delta.tv_sec = abstime->tv_sec - now.tv_sec;
  418. delta.tv_nsec = abstime->tv_nsec - now.tv_nsec;
  419. delay = (double) delta.tv_sec + (double) delta.tv_nsec / 1000000000.;
  420. _STARPU_TRACE_COND_WAIT_BEGIN();
  421. _starpu_pthread_cond_auto_init(cond);
  422. #ifdef STARPU_HAVE_SIMGRID_COND_H
  423. ret = sg_cond_wait_for(*cond, *mutex, delay) ? ETIMEDOUT : 0;
  424. #else
  425. ret = xbt_cond_timedwait(*cond, *mutex, delay) ? ETIMEDOUT : 0;
  426. #endif
  427. _STARPU_TRACE_COND_WAIT_END();
  428. return ret;
  429. #else
  430. STARPU_ASSERT_MSG(0, "simgrid version is too old for this");
  431. #endif
  432. }
  433. int starpu_pthread_cond_destroy(starpu_pthread_cond_t *cond)
  434. {
  435. if (*cond)
  436. #ifdef STARPU_HAVE_SIMGRID_COND_H
  437. sg_cond_destroy(*cond);
  438. #else
  439. xbt_cond_destroy(*cond);
  440. #endif
  441. return 0;
  442. }
  443. /* TODO: use rwlocks
  444. * https://gforge.inria.fr/tracker/index.php?func=detail&aid=17213&group_id=12&atid=165
  445. */
  446. int starpu_pthread_rwlock_init(starpu_pthread_rwlock_t *restrict rwlock, const starpu_pthread_rwlockattr_t *restrict attr STARPU_ATTRIBUTE_UNUSED)
  447. {
  448. return starpu_pthread_mutex_init(rwlock, NULL);
  449. }
  450. int starpu_pthread_rwlock_destroy(starpu_pthread_rwlock_t *rwlock)
  451. {
  452. return starpu_pthread_mutex_destroy(rwlock);
  453. }
  454. int starpu_pthread_rwlock_rdlock(starpu_pthread_rwlock_t *rwlock)
  455. {
  456. _STARPU_TRACE_RDLOCKING_RWLOCK();
  457. int p_ret = starpu_pthread_mutex_lock(rwlock);
  458. _STARPU_TRACE_RWLOCK_RDLOCKED();
  459. return p_ret;
  460. }
  461. int starpu_pthread_rwlock_tryrdlock(starpu_pthread_rwlock_t *rwlock)
  462. {
  463. int p_ret = starpu_pthread_mutex_trylock(rwlock);
  464. if (!p_ret)
  465. _STARPU_TRACE_RWLOCK_RDLOCKED();
  466. return p_ret;
  467. }
  468. int starpu_pthread_rwlock_wrlock(starpu_pthread_rwlock_t *rwlock)
  469. {
  470. _STARPU_TRACE_WRLOCKING_RWLOCK();
  471. int p_ret = starpu_pthread_mutex_lock(rwlock);
  472. _STARPU_TRACE_RWLOCK_WRLOCKED();
  473. return p_ret;
  474. }
  475. int starpu_pthread_rwlock_trywrlock(starpu_pthread_rwlock_t *rwlock)
  476. {
  477. int p_ret = starpu_pthread_mutex_trylock(rwlock);
  478. if (!p_ret)
  479. _STARPU_TRACE_RWLOCK_RDLOCKED();
  480. return p_ret;
  481. }
  482. int starpu_pthread_rwlock_unlock(starpu_pthread_rwlock_t *rwlock)
  483. {
  484. _STARPU_TRACE_UNLOCKING_RWLOCK();
  485. int p_ret = starpu_pthread_mutex_unlock(rwlock);
  486. _STARPU_TRACE_RWLOCK_UNLOCKED();
  487. return p_ret;
  488. }
  489. #ifdef STARPU_HAVE_SIMGRID_BARRIER_H
  490. int starpu_pthread_barrier_init(starpu_pthread_barrier_t *restrict barrier, const starpu_pthread_barrierattr_t *restrict attr STARPU_ATTRIBUTE_UNUSED, unsigned count)
  491. {
  492. *barrier = sg_barrier_init(count);
  493. return 0;
  494. }
  495. int starpu_pthread_barrier_destroy(starpu_pthread_barrier_t *barrier)
  496. {
  497. if (*barrier)
  498. sg_barrier_destroy(*barrier);
  499. return 0;
  500. }
  501. int starpu_pthread_barrier_wait(starpu_pthread_barrier_t *barrier)
  502. {
  503. int ret;
  504. _STARPU_TRACE_BARRIER_WAIT_BEGIN();
  505. ret = sg_barrier_wait(*barrier);
  506. _STARPU_TRACE_BARRIER_WAIT_END();
  507. return ret;
  508. }
  509. #elif defined(STARPU_SIMGRID_HAVE_XBT_BARRIER_INIT) || defined(xbt_barrier_init)
  510. int starpu_pthread_barrier_init(starpu_pthread_barrier_t *restrict barrier, const starpu_pthread_barrierattr_t *restrict attr STARPU_ATTRIBUTE_UNUSED, unsigned count)
  511. {
  512. *barrier = xbt_barrier_init(count);
  513. return 0;
  514. }
  515. int starpu_pthread_barrier_destroy(starpu_pthread_barrier_t *barrier)
  516. {
  517. if (*barrier)
  518. xbt_barrier_destroy(*barrier);
  519. return 0;
  520. }
  521. int starpu_pthread_barrier_wait(starpu_pthread_barrier_t *barrier)
  522. {
  523. int ret;
  524. _STARPU_TRACE_BARRIER_WAIT_BEGIN();
  525. ret = xbt_barrier_wait(*barrier);
  526. _STARPU_TRACE_BARRIER_WAIT_END();
  527. return ret;
  528. }
  529. #endif /* defined(STARPU_SIMGRID_HAVE_XBT_BARRIER_INIT) */
  530. int starpu_pthread_queue_init(starpu_pthread_queue_t *q)
  531. {
  532. STARPU_PTHREAD_MUTEX_INIT(&q->mutex, NULL);
  533. q->queue = NULL;
  534. q->allocqueue = 0;
  535. q->nqueue = 0;
  536. return 0;
  537. }
  538. int starpu_pthread_wait_init(starpu_pthread_wait_t *w)
  539. {
  540. STARPU_PTHREAD_MUTEX_INIT(&w->mutex, NULL);
  541. STARPU_PTHREAD_COND_INIT(&w->cond, NULL);
  542. w->block = 1;
  543. return 0;
  544. }
  545. int starpu_pthread_queue_register(starpu_pthread_wait_t *w, starpu_pthread_queue_t *q)
  546. {
  547. STARPU_PTHREAD_MUTEX_LOCK(&q->mutex);
  548. if (q->nqueue == q->allocqueue)
  549. {
  550. /* Make room for the new waiter */
  551. unsigned newalloc;
  552. newalloc = q->allocqueue * 2;
  553. if (!newalloc)
  554. newalloc = 1;
  555. _STARPU_REALLOC(q->queue, newalloc * sizeof(*(q->queue)));
  556. q->allocqueue = newalloc;
  557. }
  558. q->queue[q->nqueue++] = w;
  559. STARPU_PTHREAD_MUTEX_UNLOCK(&q->mutex);
  560. return 0;
  561. }
  562. int starpu_pthread_queue_unregister(starpu_pthread_wait_t *w, starpu_pthread_queue_t *q)
  563. {
  564. unsigned i;
  565. STARPU_PTHREAD_MUTEX_LOCK(&q->mutex);
  566. for (i = 0; i < q->nqueue; i++)
  567. {
  568. if (q->queue[i] == w)
  569. {
  570. memmove(&q->queue[i], &q->queue[i+1], (q->nqueue - i - 1) * sizeof(*(q->queue)));
  571. break;
  572. }
  573. }
  574. STARPU_ASSERT(i < q->nqueue);
  575. q->nqueue--;
  576. STARPU_PTHREAD_MUTEX_UNLOCK(&q->mutex);
  577. return 0;
  578. }
  579. int starpu_pthread_wait_reset(starpu_pthread_wait_t *w)
  580. {
  581. STARPU_PTHREAD_MUTEX_LOCK(&w->mutex);
  582. w->block = 1;
  583. STARPU_PTHREAD_MUTEX_UNLOCK(&w->mutex);
  584. return 0;
  585. }
  586. int starpu_pthread_wait_wait(starpu_pthread_wait_t *w)
  587. {
  588. STARPU_PTHREAD_MUTEX_LOCK(&w->mutex);
  589. while (w->block == 1)
  590. STARPU_PTHREAD_COND_WAIT(&w->cond, &w->mutex);
  591. STARPU_PTHREAD_MUTEX_UNLOCK(&w->mutex);
  592. return 0;
  593. }
  594. /* pthread_cond_timedwait not yet available on windows, but we don't run simgrid there anyway */
  595. #ifdef STARPU_SIMGRID
  596. int starpu_pthread_wait_timedwait(starpu_pthread_wait_t *w, const struct timespec *abstime)
  597. {
  598. STARPU_PTHREAD_MUTEX_LOCK(&w->mutex);
  599. while (w->block == 1)
  600. STARPU_PTHREAD_COND_TIMEDWAIT(&w->cond, &w->mutex, abstime);
  601. STARPU_PTHREAD_MUTEX_UNLOCK(&w->mutex);
  602. return 0;
  603. }
  604. #endif
  605. int starpu_pthread_queue_signal(starpu_pthread_queue_t *q)
  606. {
  607. starpu_pthread_wait_t *w;
  608. STARPU_PTHREAD_MUTEX_LOCK(&q->mutex);
  609. if (q->nqueue)
  610. {
  611. /* TODO: better try to wake a sleeping one if possible */
  612. w = q->queue[0];
  613. STARPU_PTHREAD_MUTEX_LOCK(&w->mutex);
  614. w->block = 0;
  615. STARPU_PTHREAD_COND_SIGNAL(&w->cond);
  616. STARPU_PTHREAD_MUTEX_UNLOCK(&w->mutex);
  617. }
  618. STARPU_PTHREAD_MUTEX_UNLOCK(&q->mutex);
  619. return 0;
  620. }
  621. int starpu_pthread_queue_broadcast(starpu_pthread_queue_t *q)
  622. {
  623. unsigned i;
  624. starpu_pthread_wait_t *w;
  625. STARPU_PTHREAD_MUTEX_LOCK(&q->mutex);
  626. for (i = 0; i < q->nqueue; i++)
  627. {
  628. w = q->queue[i];
  629. STARPU_PTHREAD_MUTEX_LOCK(&w->mutex);
  630. w->block = 0;
  631. STARPU_PTHREAD_COND_SIGNAL(&w->cond);
  632. STARPU_PTHREAD_MUTEX_UNLOCK(&w->mutex);
  633. }
  634. STARPU_PTHREAD_MUTEX_UNLOCK(&q->mutex);
  635. return 0;
  636. }
  637. int starpu_pthread_wait_destroy(starpu_pthread_wait_t *w)
  638. {
  639. STARPU_PTHREAD_MUTEX_LOCK(&w->mutex);
  640. STARPU_PTHREAD_MUTEX_UNLOCK(&w->mutex);
  641. STARPU_PTHREAD_MUTEX_DESTROY(&w->mutex);
  642. STARPU_PTHREAD_COND_DESTROY(&w->cond);
  643. return 0;
  644. }
  645. int starpu_pthread_queue_destroy(starpu_pthread_queue_t *q)
  646. {
  647. STARPU_ASSERT(!q->nqueue);
  648. STARPU_PTHREAD_MUTEX_LOCK(&q->mutex);
  649. STARPU_PTHREAD_MUTEX_UNLOCK(&q->mutex);
  650. STARPU_PTHREAD_MUTEX_DESTROY(&q->mutex);
  651. free(q->queue);
  652. return 0;
  653. }
  654. #endif /* STARPU_SIMGRID */
  655. #if (defined(STARPU_SIMGRID) && !defined(STARPU_HAVE_SIMGRID_BARRIER_H) && !defined(STARPU_SIMGRID_HAVE_XBT_BARRIER_INIT) && !defined(xbt_barrier_init)) || (!defined(STARPU_SIMGRID) && !defined(STARPU_HAVE_PTHREAD_BARRIER))
  656. int starpu_pthread_barrier_init(starpu_pthread_barrier_t *restrict barrier, const starpu_pthread_barrierattr_t *restrict attr STARPU_ATTRIBUTE_UNUSED, unsigned count)
  657. {
  658. int ret = starpu_pthread_mutex_init(&barrier->mutex, NULL);
  659. if (!ret)
  660. ret = starpu_pthread_cond_init(&barrier->cond, NULL);
  661. if (!ret)
  662. ret = starpu_pthread_cond_init(&barrier->cond_destroy, NULL);
  663. barrier->count = count;
  664. barrier->done = 0;
  665. barrier->busy = 0;
  666. return ret;
  667. }
  668. int starpu_pthread_barrier_destroy(starpu_pthread_barrier_t *barrier)
  669. {
  670. starpu_pthread_mutex_lock(&barrier->mutex);
  671. while (barrier->busy)
  672. {
  673. starpu_pthread_cond_wait(&barrier->cond_destroy, &barrier->mutex);
  674. }
  675. starpu_pthread_mutex_unlock(&barrier->mutex);
  676. int ret = starpu_pthread_mutex_destroy(&barrier->mutex);
  677. if (!ret)
  678. ret = starpu_pthread_cond_destroy(&barrier->cond);
  679. if (!ret)
  680. ret = starpu_pthread_cond_destroy(&barrier->cond_destroy);
  681. return ret;
  682. }
  683. int starpu_pthread_barrier_wait(starpu_pthread_barrier_t *barrier)
  684. {
  685. int ret = 0;
  686. _STARPU_TRACE_BARRIER_WAIT_BEGIN();
  687. starpu_pthread_mutex_lock(&barrier->mutex);
  688. barrier->done++;
  689. if (barrier->done == barrier->count)
  690. {
  691. barrier->done = 0;
  692. starpu_pthread_cond_broadcast(&barrier->cond);
  693. ret = STARPU_PTHREAD_BARRIER_SERIAL_THREAD;
  694. }
  695. else
  696. {
  697. barrier->busy++;
  698. starpu_pthread_cond_wait(&barrier->cond, &barrier->mutex);
  699. barrier->busy--;
  700. starpu_pthread_cond_broadcast(&barrier->cond_destroy);
  701. }
  702. starpu_pthread_mutex_unlock(&barrier->mutex);
  703. _STARPU_TRACE_BARRIER_WAIT_END();
  704. return ret;
  705. }
  706. #endif /* defined(STARPU_SIMGRID) || !defined(STARPU_HAVE_PTHREAD_BARRIER) */
  707. #ifdef STARPU_FXT_LOCK_TRACES
  708. #if !defined(STARPU_SIMGRID) && !defined(_MSC_VER) /* !STARPU_SIMGRID */
  709. int starpu_pthread_mutex_lock(starpu_pthread_mutex_t *mutex)
  710. {
  711. _STARPU_TRACE_LOCKING_MUTEX();
  712. int p_ret = pthread_mutex_lock(mutex);
  713. _STARPU_TRACE_MUTEX_LOCKED();
  714. return p_ret;
  715. }
  716. int starpu_pthread_mutex_unlock(starpu_pthread_mutex_t *mutex)
  717. {
  718. _STARPU_TRACE_UNLOCKING_MUTEX();
  719. int p_ret = pthread_mutex_unlock(mutex);
  720. _STARPU_TRACE_MUTEX_UNLOCKED();
  721. return p_ret;
  722. }
  723. int starpu_pthread_mutex_trylock(starpu_pthread_mutex_t *mutex)
  724. {
  725. int ret;
  726. _STARPU_TRACE_TRYLOCK_MUTEX();
  727. ret = pthread_mutex_trylock(mutex);
  728. if (!ret)
  729. _STARPU_TRACE_MUTEX_LOCKED();
  730. return ret;
  731. }
  732. int starpu_pthread_cond_wait(starpu_pthread_cond_t *cond, starpu_pthread_mutex_t *mutex)
  733. {
  734. _STARPU_TRACE_COND_WAIT_BEGIN();
  735. int p_ret = pthread_cond_wait(cond, mutex);
  736. _STARPU_TRACE_COND_WAIT_END();
  737. return p_ret;
  738. }
  739. int starpu_pthread_rwlock_rdlock(starpu_pthread_rwlock_t *rwlock)
  740. {
  741. _STARPU_TRACE_RDLOCKING_RWLOCK();
  742. int p_ret = pthread_rwlock_rdlock(rwlock);
  743. _STARPU_TRACE_RWLOCK_RDLOCKED();
  744. return p_ret;
  745. }
  746. int starpu_pthread_rwlock_tryrdlock(starpu_pthread_rwlock_t *rwlock)
  747. {
  748. _STARPU_TRACE_RDLOCKING_RWLOCK();
  749. int p_ret = pthread_rwlock_tryrdlock(rwlock);
  750. if (!p_ret)
  751. _STARPU_TRACE_RWLOCK_RDLOCKED();
  752. return p_ret;
  753. }
  754. int starpu_pthread_rwlock_wrlock(starpu_pthread_rwlock_t *rwlock)
  755. {
  756. _STARPU_TRACE_WRLOCKING_RWLOCK();
  757. int p_ret = pthread_rwlock_wrlock(rwlock);
  758. _STARPU_TRACE_RWLOCK_WRLOCKED();
  759. return p_ret;
  760. }
  761. int starpu_pthread_rwlock_trywrlock(starpu_pthread_rwlock_t *rwlock)
  762. {
  763. _STARPU_TRACE_WRLOCKING_RWLOCK();
  764. int p_ret = pthread_rwlock_trywrlock(rwlock);
  765. if (!p_ret)
  766. _STARPU_TRACE_RWLOCK_WRLOCKED();
  767. return p_ret;
  768. }
  769. int starpu_pthread_rwlock_unlock(starpu_pthread_rwlock_t *rwlock)
  770. {
  771. _STARPU_TRACE_UNLOCKING_RWLOCK();
  772. int p_ret = pthread_rwlock_unlock(rwlock);
  773. _STARPU_TRACE_RWLOCK_UNLOCKED();
  774. return p_ret;
  775. }
  776. #endif /* !defined(STARPU_SIMGRID) && !defined(_MSC_VER) */
  777. #if !defined(STARPU_SIMGRID) && !defined(_MSC_VER) && defined(STARPU_HAVE_PTHREAD_BARRIER)
  778. int starpu_pthread_barrier_wait(starpu_pthread_barrier_t *barrier)
  779. {
  780. int ret;
  781. _STARPU_TRACE_BARRIER_WAIT_BEGIN();
  782. ret = pthread_barrier_wait(barrier);
  783. _STARPU_TRACE_BARRIER_WAIT_END();
  784. return ret;
  785. }
  786. #endif /* STARPU_SIMGRID, _MSC_VER, STARPU_HAVE_PTHREAD_BARRIER */
  787. #endif /* STARPU_FXT_LOCK_TRACES */
  788. /* "sched" variants, to be used (through the STARPU_PTHREAD_MUTEX_*LOCK_SCHED
  789. * macros of course) which record when the mutex is held or not */
  790. int starpu_pthread_mutex_lock_sched(starpu_pthread_mutex_t *mutex)
  791. {
  792. return starpu_pthread_mutex_lock(mutex);
  793. }
  794. int starpu_pthread_mutex_unlock_sched(starpu_pthread_mutex_t *mutex)
  795. {
  796. return starpu_pthread_mutex_unlock(mutex);
  797. }
  798. int starpu_pthread_mutex_trylock_sched(starpu_pthread_mutex_t *mutex)
  799. {
  800. return starpu_pthread_mutex_trylock(mutex);
  801. }
  802. #ifdef STARPU_DEBUG
  803. void starpu_pthread_mutex_check_sched(starpu_pthread_mutex_t *mutex, char *file, int line)
  804. {
  805. int workerid = starpu_worker_get_id();
  806. STARPU_ASSERT_MSG(workerid == -1 || !_starpu_worker_mutex_is_sched_mutex(workerid, mutex), "%s:%d is locking/unlocking a sched mutex but not using STARPU_PTHREAD_MUTEX_LOCK_SCHED", file, line);
  807. }
  808. #endif
  809. #if defined(STARPU_SIMGRID) || (defined(STARPU_LINUX_SYS) && defined(STARPU_HAVE_XCHG)) || !defined(HAVE_PTHREAD_SPIN_LOCK)
  810. #undef starpu_pthread_spin_init
  811. int starpu_pthread_spin_init(starpu_pthread_spinlock_t *lock, int pshared)
  812. {
  813. return _starpu_pthread_spin_init(lock, pshared);
  814. }
  815. #undef starpu_pthread_spin_destroy
  816. int starpu_pthread_spin_destroy(starpu_pthread_spinlock_t *lock STARPU_ATTRIBUTE_UNUSED)
  817. {
  818. return _starpu_pthread_spin_destroy(lock);
  819. }
  820. #undef starpu_pthread_spin_lock
  821. int starpu_pthread_spin_lock(starpu_pthread_spinlock_t *lock)
  822. {
  823. return _starpu_pthread_spin_lock(lock);
  824. }
  825. #endif
  826. #if defined(STARPU_SIMGRID) || (defined(STARPU_LINUX_SYS) && defined(STARPU_HAVE_XCHG)) || !defined(STARPU_HAVE_PTHREAD_SPIN_LOCK)
  827. #if !defined(STARPU_SIMGRID) && defined(STARPU_LINUX_SYS) && defined(STARPU_HAVE_XCHG)
  828. int _starpu_pthread_spin_do_lock(starpu_pthread_spinlock_t *lock)
  829. {
  830. if (STARPU_VAL_COMPARE_AND_SWAP(&lock->taken, 0, 1) == 0)
  831. /* Got it on first try! */
  832. return 0;
  833. /* Busy, spin a bit. */
  834. unsigned i;
  835. for (i = 0; i < 128; i++)
  836. {
  837. /* Pause a bit before retrying */
  838. STARPU_UYIELD();
  839. /* And synchronize with other threads */
  840. STARPU_SYNCHRONIZE();
  841. if (!lock->taken)
  842. /* Holder released it, try again */
  843. if (STARPU_VAL_COMPARE_AND_SWAP(&lock->taken, 0, 1) == 0)
  844. /* Got it! */
  845. return 0;
  846. }
  847. /* We have spent enough time with spinning, let's block */
  848. /* This avoids typical 10ms pauses when the application thread tries to submit tasks. */
  849. while (1)
  850. {
  851. /* Tell releaser to wake us */
  852. unsigned prev = STARPU_VAL_EXCHANGE(&lock->taken, 2);
  853. if (prev == 0)
  854. /* Ah, it just got released and we actually acquired
  855. * it!
  856. * Note: the sad thing is that we have just written 2,
  857. * so will spuriously try to wake a thread on unlock,
  858. * but we can not avoid it since we do not know whether
  859. * there are other threads sleeping or not.
  860. */
  861. return 0;
  862. /* Now start sleeping (unless it was released in between)
  863. * We are sure to get woken because either
  864. * - some thread has not released the lock yet, and lock->taken
  865. * is 2, so it will wake us.
  866. * - some other thread started blocking, and will set
  867. * lock->taken back to 2
  868. */
  869. if (syscall(SYS_futex, &lock->taken, _starpu_futex_wait, 2, NULL, NULL, 0))
  870. if (errno == ENOSYS)
  871. _starpu_futex_wait = FUTEX_WAIT;
  872. }
  873. }
  874. #endif
  875. #undef starpu_pthread_spin_trylock
  876. int starpu_pthread_spin_trylock(starpu_pthread_spinlock_t *lock)
  877. {
  878. return _starpu_pthread_spin_trylock(lock);
  879. }
  880. #undef starpu_pthread_spin_unlock
  881. int starpu_pthread_spin_unlock(starpu_pthread_spinlock_t *lock)
  882. {
  883. return _starpu_pthread_spin_unlock(lock);
  884. }
  885. #if !defined(STARPU_SIMGRID) && defined(STARPU_LINUX_SYS) && defined(STARPU_HAVE_XCHG)
  886. void _starpu_pthread_spin_do_unlock(starpu_pthread_spinlock_t *lock)
  887. {
  888. /*
  889. * Somebody to wake. Clear 'taken' and wake him.
  890. * Note that he may not be sleeping yet, but if he is not, we won't
  891. * since the value of 'taken' will have changed.
  892. */
  893. lock->taken = 0;
  894. STARPU_SYNCHRONIZE();
  895. if (syscall(SYS_futex, &lock->taken, _starpu_futex_wake, 1, NULL, NULL, 0) == -1)
  896. switch (errno)
  897. {
  898. case ENOSYS:
  899. _starpu_futex_wake = FUTEX_WAKE;
  900. if (syscall(SYS_futex, &lock->taken, _starpu_futex_wake, 1, NULL, NULL, 0) == -1)
  901. STARPU_ASSERT_MSG(0, "futex(wake) returned %d!", errno);
  902. break;
  903. case 0:
  904. break;
  905. default:
  906. STARPU_ASSERT_MSG(0, "futex returned %d!", errno);
  907. break;
  908. }
  909. }
  910. #endif
  911. #endif /* defined(STARPU_SIMGRID) || (defined(STARPU_LINUX_SYS) && defined(STARPU_HAVE_XCHG)) || !defined(STARPU_HAVE_PTHREAD_SPIN_LOCK) */
  912. #ifdef STARPU_SIMGRID
  913. int starpu_sem_destroy(starpu_sem_t *sem)
  914. {
  915. #ifdef STARPU_HAVE_SIMGRID_SEMAPHORE_H
  916. sg_sem_destroy(*sem);
  917. #else
  918. MSG_sem_destroy(*sem);
  919. #endif
  920. return 0;
  921. }
  922. int starpu_sem_init(starpu_sem_t *sem, int pshared, unsigned value)
  923. {
  924. STARPU_ASSERT_MSG(pshared == 0, "pshared semaphores not supported under simgrid");
  925. #ifdef STARPU_HAVE_SIMGRID_SEMAPHORE_H
  926. *sem = sg_sem_init(value);
  927. #else
  928. *sem = MSG_sem_init(value);
  929. #endif
  930. return 0;
  931. }
  932. int starpu_sem_post(starpu_sem_t *sem)
  933. {
  934. #ifdef STARPU_HAVE_SIMGRID_SEMAPHORE_H
  935. sg_sem_release(*sem);
  936. #else
  937. MSG_sem_release(*sem);
  938. #endif
  939. return 0;
  940. }
  941. int starpu_sem_wait(starpu_sem_t *sem)
  942. {
  943. #ifdef STARPU_HAVE_SIMGRID_SEMAPHORE_H
  944. sg_sem_acquire(*sem);
  945. #else
  946. MSG_sem_acquire(*sem);
  947. #endif
  948. return 0;
  949. }
  950. int starpu_sem_trywait(starpu_sem_t *sem)
  951. {
  952. #ifdef STARPU_HAVE_SIMGRID_SEMAPHORE_H
  953. if (sg_sem_would_block(*sem))
  954. #else
  955. if (MSG_sem_would_block(*sem))
  956. #endif
  957. return EAGAIN;
  958. starpu_sem_wait(sem);
  959. return 0;
  960. }
  961. int starpu_sem_getvalue(starpu_sem_t *sem, int *sval)
  962. {
  963. #if SIMGRID_VERSION > 31300
  964. # ifdef STARPU_HAVE_SIMGRID_SEMAPHORE_H
  965. *sval = sg_sem_get_capacity(*sem);
  966. # else
  967. *sval = MSG_sem_get_capacity(*sem);
  968. # endif
  969. return 0;
  970. #else
  971. (void) sem;
  972. (void) sval;
  973. STARPU_ABORT_MSG("sigmrid up to 3.13 did not have working MSG_sem_get_capacity");
  974. #endif
  975. }
  976. #elif !defined(_MSC_VER) || defined(BUILDING_STARPU) /* !STARPU_SIMGRID */
  977. int starpu_sem_wait(starpu_sem_t *sem)
  978. {
  979. int ret;
  980. while((ret = sem_wait(sem)) == -1 && errno == EINTR)
  981. ;
  982. return ret;
  983. }
  984. int starpu_sem_trywait(starpu_sem_t *sem)
  985. {
  986. int ret;
  987. while((ret = sem_trywait(sem)) == -1 && errno == EINTR)
  988. ;
  989. return ret;
  990. }
  991. #endif