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)
28 int _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 
33 static 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 
40 static 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 
47 static 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 
105 static 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 
116 static 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)
136 void _starpu_pthread_spin_do_unlock(starpu_pthread_spinlock_t *lock) STARPU_ATTRIBUTE_VISIBILITY_DEFAULT;
137 #endif
138 
139 static 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 
160 static 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