StarPU Internal Handbook
thread.h
Go to the documentation of this file.
1/* StarPU --- Runtime system for heterogeneous multicore architectures.
2 *
3 * Copyright (C) 2010-2022 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
17#ifndef __COMMON_THREAD_H__
18#define __COMMON_THREAD_H__
19
22#include <common/utils.h>
23#include <core/simgrid.h>
24
25#pragma GCC visibility push(hidden)
26
27#if defined(STARPU_LINUX_SYS) && defined(STARPU_HAVE_XCHG)
28int _starpu_pthread_spin_do_lock(starpu_pthread_spinlock_t *lock) STARPU_ATTRIBUTE_VISIBILITY_DEFAULT;
29#endif
30
31#if defined(STARPU_SIMGRID) || (defined(STARPU_LINUX_SYS) && defined(STARPU_HAVE_XCHG)) || !defined(STARPU_HAVE_PTHREAD_SPIN_LOCK)
32
33static inline int _starpu_pthread_spin_init(starpu_pthread_spinlock_t *lock, int pshared STARPU_ATTRIBUTE_UNUSED)
34{
35 lock->taken = 0;
36 return 0;
37}
38#define starpu_pthread_spin_init _starpu_pthread_spin_init
39
40static inline int _starpu_pthread_spin_destroy(starpu_pthread_spinlock_t *lock STARPU_ATTRIBUTE_UNUSED)
41{
42 /* we don't do anything */
43 return 0;
44}
45#define starpu_pthread_spin_destroy _starpu_pthread_spin_destroy
46
47static inline int _starpu_pthread_spin_lock(starpu_pthread_spinlock_t *lock)
48{
49#ifdef STARPU_SIMGRID
50 if (STARPU_LIKELY(!lock->taken))
51 {
52 lock->taken = 1;
53 return 0;
54 }
55
56#ifdef STARPU_HAVE_S4U_ON_TIME_ADVANCE_CB
57 /* There is contention, count that a bit */
58 starpu_sleep(0.000001);
59 /* And try again */
60 if (STARPU_LIKELY(!lock->taken))
61 {
62 lock->taken = 1;
63 return 0;
64 }
65
66 /* Really no luck, really wait for it */
67 STARPU_PTHREAD_MUTEX_LOCK(&_starpu_simgrid_time_advance_mutex);
68#endif
69 while (lock->taken)
70 {
71#ifdef STARPU_HAVE_S4U_ON_TIME_ADVANCE_CB
72 STARPU_PTHREAD_COND_WAIT(&_starpu_simgrid_time_advance_cond, &_starpu_simgrid_time_advance_mutex);
73#else
74 /* Give hand to another thread, hopefully the one which has the
75 * spinlock and probably just has also a short-lived mutex. */
76 starpu_sleep(0.000001);
77#endif
78 STARPU_UYIELD();
79 }
80 lock->taken = 1;
81#ifdef STARPU_HAVE_S4U_ON_TIME_ADVANCE_CB
82 STARPU_PTHREAD_MUTEX_UNLOCK(&_starpu_simgrid_time_advance_mutex);
83#endif
84 return 0;
85#elif defined(STARPU_LINUX_SYS) && defined(STARPU_HAVE_XCHG)
86 if (STARPU_LIKELY(STARPU_VAL_COMPARE_AND_SWAP(&lock->taken, 0, 1) == 0))
87 /* Got it on first try! */
88 return 0;
89
90 return _starpu_pthread_spin_do_lock(lock);
91#else /* !SIMGRID && !LINUX */
92 uint32_t prev;
93 do
94 {
95 prev = STARPU_TEST_AND_SET(&lock->taken, 1);
96 if (STARPU_UNLIKELY(prev))
97 STARPU_UYIELD();
98 }
99 while (STARPU_UNLIKELY(prev));
100 return 0;
101#endif
102}
103#define starpu_pthread_spin_lock _starpu_pthread_spin_lock
104
105static inline void _starpu_pthread_spin_checklocked(starpu_pthread_spinlock_t *lock STARPU_ATTRIBUTE_UNUSED)
106{
107#ifdef STARPU_SIMGRID
108 STARPU_ASSERT(lock->taken);
109#elif defined(STARPU_LINUX_SYS) && defined(STARPU_HAVE_XCHG)
110 STARPU_ASSERT(lock->taken == 1 || lock->taken == 2);
111#else
112 STARPU_ASSERT(lock->taken);
113#endif
114}
115
116static inline int _starpu_pthread_spin_trylock(starpu_pthread_spinlock_t *lock)
117{
118#ifdef STARPU_SIMGRID
119 if (STARPU_UNLIKELY(lock->taken))
120 return EBUSY;
121 lock->taken = 1;
122 return 0;
123#elif defined(STARPU_LINUX_SYS) && defined(STARPU_HAVE_XCHG)
124 unsigned prev;
125 prev = STARPU_VAL_COMPARE_AND_SWAP(&lock->taken, 0, 1);
126 return (prev == 0)?0:EBUSY;
127#else /* !SIMGRID && !LINUX */
128 uint32_t prev;
129 prev = STARPU_TEST_AND_SET(&lock->taken, 1);
130 return (prev == 0)?0:EBUSY;
131#endif
132}
133#define starpu_pthread_spin_trylock _starpu_pthread_spin_trylock
134
135#if defined(STARPU_LINUX_SYS) && defined(STARPU_HAVE_XCHG)
136void _starpu_pthread_spin_do_unlock(starpu_pthread_spinlock_t *lock) STARPU_ATTRIBUTE_VISIBILITY_DEFAULT;
137#endif
138
139static inline int _starpu_pthread_spin_unlock(starpu_pthread_spinlock_t *lock)
140{
141#ifdef STARPU_SIMGRID
142 lock->taken = 0;
143#elif defined(STARPU_LINUX_SYS) && defined(STARPU_HAVE_XCHG)
144 STARPU_ASSERT(lock->taken != 0);
145 STARPU_SYNCHRONIZE();
146 unsigned next = STARPU_ATOMIC_ADD(&lock->taken, -1);
147 if (STARPU_LIKELY(next == 0))
148 /* Nobody to wake, we are done */
149 return 0;
150 _starpu_pthread_spin_do_unlock(lock);
151#else /* !SIMGRID && !LINUX */
152 STARPU_RELEASE(&lock->taken);
153#endif
154 return 0;
155}
156#define starpu_pthread_spin_unlock _starpu_pthread_spin_unlock
157
158#else /* defined(STARPU_SIMGRID) || (defined(STARPU_LINUX_SYS) && defined(STARPU_HAVE_XCHG)) || !defined(STARPU_HAVE_PTHREAD_SPIN_LOCK) */
159
160static inline void _starpu_pthread_spin_checklocked(starpu_pthread_spinlock_t *lock STARPU_ATTRIBUTE_UNUSED)
161{
162 STARPU_ASSERT(pthread_spin_trylock((pthread_spinlock_t *)lock) != 0);
163}
164
165#endif /* defined(STARPU_SIMGRID) || (defined(STARPU_LINUX_SYS) && defined(STARPU_HAVE_XCHG)) || !defined(STARPU_HAVE_PTHREAD_SPIN_LOCK) */
166
167
168#pragma GCC visibility pop
169
170#endif /* __COMMON_THREAD_H__ */
171
172