ARGOBOTS  1.1
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,
88  ABT_SYNC_EVENT_TYPE_MUTEX, (void *)p_mutex);
89  *pp_local = ABTI_xstream_get_local(p_local_xstream);
90  }
91  } else {
92  /* Use spinlock. */
93  ABTD_spinlock_acquire(&p_mutex->lock);
94  }
95 #endif
96 }
97 
98 static inline void ABTI_mutex_lock(ABTI_local **pp_local, ABTI_mutex *p_mutex)
99 {
100  if (p_mutex->attrs & ABTI_MUTEX_ATTR_RECURSIVE) {
101  /* Recursive mutex */
102  ABTI_thread_id self_id = ABTI_self_get_thread_id(*pp_local);
103  if (self_id != p_mutex->owner_id) {
104  ABTI_mutex_lock_no_recursion(pp_local, p_mutex);
105  ABTI_ASSERT(p_mutex->nesting_cnt == 0);
106  p_mutex->owner_id = self_id;
107  } else {
108  /* Increment a nesting count. */
109  p_mutex->nesting_cnt++;
110  }
111  } else {
112  ABTI_mutex_lock_no_recursion(pp_local, p_mutex);
113  }
114 }
115 
116 static inline int ABTI_mutex_trylock_no_recursion(ABTI_mutex *p_mutex)
117 {
119  : ABT_SUCCESS;
120 }
121 
122 static inline int ABTI_mutex_trylock(ABTI_local *p_local, ABTI_mutex *p_mutex)
123 {
124  if (p_mutex->attrs & ABTI_MUTEX_ATTR_RECURSIVE) {
125  /* Recursive mutex */
126  ABTI_thread_id self_id = ABTI_self_get_thread_id(p_local);
127  if (self_id != p_mutex->owner_id) {
128  int abt_errno = ABTI_mutex_trylock_no_recursion(p_mutex);
129  if (abt_errno == ABT_SUCCESS) {
130  ABTI_ASSERT(p_mutex->nesting_cnt == 0);
131  p_mutex->owner_id = self_id;
132  }
133  return abt_errno;
134  } else {
135  /* Increment a nesting count. */
136  p_mutex->nesting_cnt++;
137  return ABT_SUCCESS;
138  }
139  } else {
140  return ABTI_mutex_trylock_no_recursion(p_mutex);
141  }
142 }
143 
144 static inline void ABTI_mutex_spinlock_no_recursion(ABTI_mutex *p_mutex)
145 {
146  ABTD_spinlock_acquire(&p_mutex->lock);
147 }
148 
149 static inline void ABTI_mutex_spinlock(ABTI_local *p_local, ABTI_mutex *p_mutex)
150 {
151  if (p_mutex->attrs & ABTI_MUTEX_ATTR_RECURSIVE) {
152  /* Recursive mutex */
153  ABTI_thread_id self_id = ABTI_self_get_thread_id(p_local);
154  if (self_id != p_mutex->owner_id) {
156  ABTI_ASSERT(p_mutex->nesting_cnt == 0);
157  p_mutex->owner_id = self_id;
158  } else {
159  /* Increment a nesting count. */
160  p_mutex->nesting_cnt++;
161  }
162  } else {
164  }
165 }
166 
167 static inline void ABTI_mutex_unlock_no_recursion(ABTI_local *p_local,
168  ABTI_mutex *p_mutex)
169 {
170 #ifndef ABT_CONFIG_USE_SIMPLE_MUTEX
172  ABTD_spinlock_release(&p_mutex->lock);
173  /* Operations of waitlist must be done while taking waiter_lock. */
174  ABTI_waitlist_broadcast(p_local, &p_mutex->waitlist);
176 #else
177  ABTD_spinlock_release(&p_mutex->lock);
178 #endif
179 }
180 
181 static inline void ABTI_mutex_unlock(ABTI_local *p_local, ABTI_mutex *p_mutex)
182 {
183  if (p_mutex->attrs & ABTI_MUTEX_ATTR_RECURSIVE) {
184  /* recursive mutex */
185  if (p_mutex->nesting_cnt == 0) {
186  p_mutex->owner_id = 0;
187  ABTI_mutex_unlock_no_recursion(p_local, p_mutex);
188  } else {
189  p_mutex->nesting_cnt--;
190  }
191  } else {
192  /* unknown attributes */
193  ABTI_mutex_unlock_no_recursion(p_local, p_mutex);
194  }
195 }
196 
197 #endif /* ABTI_MUTEX_H_INCLUDED */
ABTI_mutex_get_ptr
static ABTI_mutex * ABTI_mutex_get_ptr(ABT_mutex mutex)
Definition: abti_mutex.h:9
ABTI_mutex_unlock_no_recursion
static void ABTI_mutex_unlock_no_recursion(ABTI_local *p_local, ABTI_mutex *p_mutex)
Definition: abti_mutex.h:167
ABTI_mutex_lock
static void ABTI_mutex_lock(ABTI_local **pp_local, ABTI_mutex *p_mutex)
Definition: abti_mutex.h:98
ABTI_waitlist_broadcast
static void ABTI_waitlist_broadcast(ABTI_local *p_local, ABTI_waitlist *p_waitlist)
Definition: abti_waitlist.h:247
ABTI_mutex_fini
static void ABTI_mutex_fini(ABTI_mutex *p_mutex)
Definition: abti_mutex.h:51
ABTI_MUTEX_ATTR_RECURSIVE
#define ABTI_MUTEX_ATTR_RECURSIVE
Definition: abti.h:103
ABT_mutex
struct ABT_mutex_opaque * ABT_mutex
Mutex handle type.
Definition: abt.h:945
ABT_SYNC_EVENT_TYPE_MUTEX
@ ABT_SYNC_EVENT_TYPE_MUTEX
Definition: abt.h:672
ABTI_mutex::lock
ABTD_spinlock lock
Definition: abti.h:178
ABTI_xstream
Definition: abti.h:264
ABTI_mutex::attrs
int attrs
Definition: abti.h:175
ABTI_mutex_unlock
static void ABTI_mutex_unlock(ABTI_local *p_local, ABTI_mutex *p_mutex)
Definition: abti_mutex.h:181
ABTI_mutex::waitlist
ABTI_waitlist waitlist
Definition: abti.h:183
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:182
ABTI_ASSERT
#define ABTI_ASSERT(cond)
Definition: abti_error.h:12
ABTI_mutex::nesting_cnt
int nesting_cnt
Definition: abti.h:179
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:149
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_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:116
ABTI_xstream_get_local
static ABTI_local * ABTI_xstream_get_local(ABTI_xstream *p_xstream)
Definition: abti_stream.h:68
ABTI_mutex_spinlock_no_recursion
static void ABTI_mutex_spinlock_no_recursion(ABTI_mutex *p_mutex)
Definition: abti_mutex.h:144
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:406
ABTI_MUTEX_ATTR_NONE
#define ABTI_MUTEX_ATTR_NONE
Definition: abti.h:101
ABTI_mutex_spinlock
static void ABTI_mutex_spinlock(ABTI_local *p_local, ABTI_mutex *p_mutex)
Definition: abti_mutex.h:149
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:318
ABTI_mutex_trylock
static int ABTI_mutex_trylock(ABTI_local *p_local, ABTI_mutex *p_mutex)
Definition: abti_mutex.h:122
ABTI_local
struct ABTI_local ABTI_local
Definition: abti.h:110
ABT_MUTEX_NULL
#define ABT_MUTEX_NULL
Definition: abt.h:1066
ABTI_ythread_yield
static void ABTI_ythread_yield(ABTI_xstream **pp_local_xstream, ABTI_ythread *p_ythread, ABT_sync_event_type sync_event_type, void *p_sync)
Definition: abti_ythread.h:372
ABTI_waitlist_init
static void ABTI_waitlist_init(ABTI_waitlist *p_waitlist)
Definition: abti_waitlist.h:11
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:180
ABTI_mutex
Definition: abti.h:174