ARGOBOTS  dce6e727ffc4ca5b3ffc04cb9517c6689be51ec5
abti_mutex.h
Go to the documentation of this file.
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  * See COPYRIGHT in top-level directory.
4  */
5 
6 #ifndef ABTI_MUTEX_H_INCLUDED
7 #define ABTI_MUTEX_H_INCLUDED
8 
9 static inline ABTI_mutex *ABTI_mutex_get_ptr(ABT_mutex mutex)
10 {
11 #ifndef ABT_CONFIG_DISABLE_ERROR_CHECK
12  ABTI_mutex *p_mutex;
13  if (mutex == ABT_MUTEX_NULL) {
14  p_mutex = NULL;
15  } else {
16  p_mutex = (ABTI_mutex *)mutex;
17  }
18  return p_mutex;
19 #else
20  return (ABTI_mutex *)mutex;
21 #endif
22 }
23 
25 {
26 #ifndef ABT_CONFIG_DISABLE_ERROR_CHECK
27  ABT_mutex h_mutex;
28  if (p_mutex == NULL) {
29  h_mutex = ABT_MUTEX_NULL;
30  } else {
31  h_mutex = (ABT_mutex)p_mutex;
32  }
33  return h_mutex;
34 #else
35  return (ABT_mutex)p_mutex;
36 #endif
37 }
38 
39 static inline void ABTI_mutex_init(ABTI_mutex *p_mutex)
40 {
41  ABTD_spinlock_clear(&p_mutex->lock);
42 #ifndef ABT_CONFIG_USE_SIMPLE_MUTEX
44  ABTI_waitlist_init(&p_mutex->waitlist);
45 #endif
46  p_mutex->attrs = ABTI_MUTEX_ATTR_NONE;
47  p_mutex->nesting_cnt = 0;
48  p_mutex->owner_id = 0;
49 }
50 
51 static inline void ABTI_mutex_fini(ABTI_mutex *p_mutex)
52 {
53 #ifndef ABT_CONFIG_USE_SIMPLE_MUTEX
55 #endif
56 }
57 
58 static inline void ABTI_mutex_lock_no_recursion(ABTI_local **pp_local,
59  ABTI_mutex *p_mutex)
60 {
61 #ifndef ABT_CONFIG_USE_SIMPLE_MUTEX
62  while (ABTD_spinlock_try_acquire(&p_mutex->lock)) {
63  /* Failed to take a lock, so let's add it to the waiter list. */
65  /* Maybe the mutex lock has been already released. Check it. */
66  if (!ABTD_spinlock_try_acquire(&p_mutex->lock)) {
67  /* Lock has been taken. */
69  break;
70  }
71  /* Wait on waitlist. */
72  ABTI_waitlist_wait_and_unlock(pp_local, &p_mutex->waitlist,
73  &p_mutex->waiter_lock,
75  (void *)p_mutex);
76  }
77  /* Take a lock. */
78 #else
79  /* Simple yield-based implementation */
80  ABTI_ythread *p_ythread = NULL;
81  ABTI_xstream *p_local_xstream = ABTI_local_get_xstream_or_null(*pp_local);
82  if (!ABTI_IS_EXT_THREAD_ENABLED || p_local_xstream)
83  p_ythread = ABTI_thread_get_ythread_or_null(p_local_xstream->p_thread);
84 
85  if (p_ythread) {
86  while (ABTD_spinlock_try_acquire(&p_mutex->lock)) {
87  ABTI_ythread_yield(&p_local_xstream, p_ythread,
89  ABT_SYNC_EVENT_TYPE_MUTEX, (void *)p_mutex);
90  *pp_local = ABTI_xstream_get_local(p_local_xstream);
91  }
92  } else {
93  /* Use spinlock. */
94  ABTD_spinlock_acquire(&p_mutex->lock);
95  }
96 #endif
97 }
98 
99 static inline void ABTI_mutex_lock(ABTI_local **pp_local, ABTI_mutex *p_mutex)
100 {
101  if (p_mutex->attrs & ABTI_MUTEX_ATTR_RECURSIVE) {
102  /* Recursive mutex */
103  ABTI_thread_id self_id = ABTI_self_get_thread_id(*pp_local);
104  if (self_id != p_mutex->owner_id) {
105  ABTI_mutex_lock_no_recursion(pp_local, p_mutex);
106  ABTI_ASSERT(p_mutex->nesting_cnt == 0);
107  p_mutex->owner_id = self_id;
108  } else {
109  /* Increment a nesting count. */
110  p_mutex->nesting_cnt++;
111  }
112  } else {
113  ABTI_mutex_lock_no_recursion(pp_local, p_mutex);
114  }
115 }
116 
117 static inline ABT_bool ABTI_mutex_is_locked(ABTI_mutex *p_mutex)
118 {
119  return ABTD_spinlock_is_locked(&p_mutex->lock);
120 }
121 
122 static inline int ABTI_mutex_trylock_no_recursion(ABTI_mutex *p_mutex)
123 {
125  : ABT_SUCCESS;
126 }
127 
128 static inline int ABTI_mutex_trylock(ABTI_local *p_local, ABTI_mutex *p_mutex)
129 {
130  if (p_mutex->attrs & ABTI_MUTEX_ATTR_RECURSIVE) {
131  /* Recursive mutex */
132  ABTI_thread_id self_id = ABTI_self_get_thread_id(p_local);
133  if (self_id != p_mutex->owner_id) {
134  int abt_errno = ABTI_mutex_trylock_no_recursion(p_mutex);
135  if (abt_errno == ABT_SUCCESS) {
136  ABTI_ASSERT(p_mutex->nesting_cnt == 0);
137  p_mutex->owner_id = self_id;
138  }
139  return abt_errno;
140  } else {
141  /* Increment a nesting count. */
142  p_mutex->nesting_cnt++;
143  return ABT_SUCCESS;
144  }
145  } else {
146  return ABTI_mutex_trylock_no_recursion(p_mutex);
147  }
148 }
149 
150 static inline void ABTI_mutex_spinlock_no_recursion(ABTI_mutex *p_mutex)
151 {
152  ABTD_spinlock_acquire(&p_mutex->lock);
153 }
154 
155 static inline void ABTI_mutex_spinlock(ABTI_local *p_local, ABTI_mutex *p_mutex)
156 {
157  if (p_mutex->attrs & ABTI_MUTEX_ATTR_RECURSIVE) {
158  /* Recursive mutex */
159  ABTI_thread_id self_id = ABTI_self_get_thread_id(p_local);
160  if (self_id != p_mutex->owner_id) {
162  ABTI_ASSERT(p_mutex->nesting_cnt == 0);
163  p_mutex->owner_id = self_id;
164  } else {
165  /* Increment a nesting count. */
166  p_mutex->nesting_cnt++;
167  }
168  } else {
170  }
171 }
172 
173 static inline void ABTI_mutex_unlock_no_recursion(ABTI_local *p_local,
174  ABTI_mutex *p_mutex)
175 {
176 #ifndef ABT_CONFIG_USE_SIMPLE_MUTEX
178  ABTD_spinlock_release(&p_mutex->lock);
179  /* Operations of waitlist must be done while taking waiter_lock. */
180  ABTI_waitlist_broadcast(p_local, &p_mutex->waitlist);
182 #else
183  ABTD_spinlock_release(&p_mutex->lock);
184 #endif
185 }
186 
187 static inline void ABTI_mutex_unlock(ABTI_local *p_local, ABTI_mutex *p_mutex)
188 {
189  if (p_mutex->attrs & ABTI_MUTEX_ATTR_RECURSIVE) {
190  /* recursive mutex */
191  if (p_mutex->nesting_cnt == 0) {
192  p_mutex->owner_id = 0;
193  ABTI_mutex_unlock_no_recursion(p_local, p_mutex);
194  } else {
195  p_mutex->nesting_cnt--;
196  }
197  } else {
198  /* unknown attributes */
199  ABTI_mutex_unlock_no_recursion(p_local, p_mutex);
200  }
201 }
202 
203 #endif /* ABTI_MUTEX_H_INCLUDED */
ABTI_mutex_get_ptr
static ABTI_mutex * ABTI_mutex_get_ptr(ABT_mutex mutex)
Definition: abti_mutex.h:9
ABT_bool
int ABT_bool
Boolean type.
Definition: abt.h:1043
ABTI_mutex_unlock_no_recursion
static void ABTI_mutex_unlock_no_recursion(ABTI_local *p_local, ABTI_mutex *p_mutex)
Definition: abti_mutex.h:173
ABTI_mutex_is_locked
static ABT_bool ABTI_mutex_is_locked(ABTI_mutex *p_mutex)
Definition: abti_mutex.h:117
ABTI_mutex_lock
static void ABTI_mutex_lock(ABTI_local **pp_local, ABTI_mutex *p_mutex)
Definition: abti_mutex.h:99
ABTI_waitlist_broadcast
static void ABTI_waitlist_broadcast(ABTI_local *p_local, ABTI_waitlist *p_waitlist)
Definition: abti_waitlist.h:246
ABTI_mutex_fini
static void ABTI_mutex_fini(ABTI_mutex *p_mutex)
Definition: abti_mutex.h:51
ABTI_YTHREAD_YIELD_KIND_YIELD_LOOP
@ ABTI_YTHREAD_YIELD_KIND_YIELD_LOOP
Definition: abti_ythread.h:239
ABTI_MUTEX_ATTR_RECURSIVE
#define ABTI_MUTEX_ATTR_RECURSIVE
Definition: abti.h:125
ABT_mutex
struct ABT_mutex_opaque * ABT_mutex
Mutex handle type.
Definition: abt.h:987
ABT_SYNC_EVENT_TYPE_MUTEX
@ ABT_SYNC_EVENT_TYPE_MUTEX
Definition: abt.h:708
ABTI_mutex::lock
ABTD_spinlock lock
Definition: abti.h:205
ABTI_xstream
Definition: abti.h:294
ABTI_mutex::attrs
int attrs
Definition: abti.h:202
ABTI_mutex_unlock
static void ABTI_mutex_unlock(ABTI_local *p_local, ABTI_mutex *p_mutex)
Definition: abti_mutex.h:187
ABTI_mutex::waitlist
ABTI_waitlist waitlist
Definition: abti.h:210
ABTI_thread_get_ythread_or_null
static ABTI_ythread * ABTI_thread_get_ythread_or_null(ABTI_thread *p_thread)
Definition: abti_thread.h:59
ABTD_spinlock_acquire
static void ABTD_spinlock_acquire(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:28
ABTI_mutex::waiter_lock
ABTD_spinlock waiter_lock
Definition: abti.h:209
ABTI_ASSERT
#define ABTI_ASSERT(cond)
Definition: abti_error.h:12
ABTI_mutex::nesting_cnt
int nesting_cnt
Definition: abti.h:206
ABTD_spinlock_try_acquire
static ABT_bool ABTD_spinlock_try_acquire(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:37
ABT_SUCCESS
#define ABT_SUCCESS
Error code: the routine returns successfully.
Definition: abt.h:92
ABTI_thread_id
struct ABTI_thread_id_opaque * ABTI_thread_id
Definition: abti.h:175
ABTI_mutex_lock_no_recursion
static void ABTI_mutex_lock_no_recursion(ABTI_local **pp_local, ABTI_mutex *p_mutex)
Definition: abti_mutex.h:58
ABTI_ythread_yield
static void ABTI_ythread_yield(ABTI_xstream **pp_local_xstream, ABTI_ythread *p_self, ABTI_ythread_yield_kind kind, ABT_sync_event_type sync_event_type, void *p_sync)
Definition: abti_ythread.h:254
ABTI_local_get_xstream_or_null
static ABTI_xstream * ABTI_local_get_xstream_or_null(ABTI_local *p_local)
Definition: abti_local.h:77
ABTI_IS_EXT_THREAD_ENABLED
#define ABTI_IS_EXT_THREAD_ENABLED
Definition: abti.h:28
ABTI_mutex_trylock_no_recursion
static int ABTI_mutex_trylock_no_recursion(ABTI_mutex *p_mutex)
Definition: abti_mutex.h:122
ABTI_xstream_get_local
static ABTI_local * ABTI_xstream_get_local(ABTI_xstream *p_xstream)
Definition: abti_stream.h:48
ABTI_mutex_spinlock_no_recursion
static void ABTI_mutex_spinlock_no_recursion(ABTI_mutex *p_mutex)
Definition: abti_mutex.h:150
ABTD_spinlock_clear
static void ABTD_spinlock_clear(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:23
ABTI_self_get_thread_id
static ABTI_thread_id ABTI_self_get_thread_id(ABTI_local *p_local)
Definition: abti_self.h:22
ABTI_ythread
Definition: abti.h:456
ABTI_MUTEX_ATTR_NONE
#define ABTI_MUTEX_ATTR_NONE
Definition: abti.h:123
ABTI_mutex_spinlock
static void ABTI_mutex_spinlock(ABTI_local *p_local, ABTI_mutex *p_mutex)
Definition: abti_mutex.h:155
ABTD_spinlock_release
static void ABTD_spinlock_release(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:42
ABT_ERR_MUTEX_LOCKED
#define ABT_ERR_MUTEX_LOCKED
Error code: a return value when a mutex is locked.
Definition: abt.h:328
ABTI_mutex_trylock
static int ABTI_mutex_trylock(ABTI_local *p_local, ABTI_mutex *p_mutex)
Definition: abti_mutex.h:128
ABTI_local
struct ABTI_local ABTI_local
Definition: abti.h:132
ABT_MUTEX_NULL
#define ABT_MUTEX_NULL
Definition: abt.h:1109
ABTI_waitlist_init
static void ABTI_waitlist_init(ABTI_waitlist *p_waitlist)
Definition: abti_waitlist.h:11
ABTD_spinlock_is_locked
static ABT_bool ABTD_spinlock_is_locked(const ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:18
ABTI_mutex_init
static void ABTI_mutex_init(ABTI_mutex *p_mutex)
Definition: abti_mutex.h:39
ABTI_waitlist_wait_and_unlock
static void ABTI_waitlist_wait_and_unlock(ABTI_local **pp_local, ABTI_waitlist *p_waitlist, ABTD_spinlock *p_lock, ABT_sync_event_type sync_event_type, void *p_sync)
Definition: abti_waitlist.h:21
ABTI_mutex_get_handle
static ABT_mutex ABTI_mutex_get_handle(ABTI_mutex *p_mutex)
Definition: abti_mutex.h:24
ABTI_mutex::owner_id
ABTI_thread_id owner_id
Definition: abti.h:207
ABTI_mutex
Definition: abti.h:201