ARGOBOTS  be805649b56a69fc4df1b6bc4efbc8911b854459
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 
24 static inline ABT_mutex ABTI_mutex_get_handle(ABTI_mutex *p_mutex)
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
43  ABTD_spinlock_clear(&p_mutex->waiter_lock);
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
54  ABTD_spinlock_acquire(&p_mutex->waiter_lock);
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. */
64  ABTD_spinlock_acquire(&p_mutex->waiter_lock);
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. */
68  ABTD_spinlock_release(&p_mutex->waiter_lock);
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  ABTI_YTHREAD_YIELD_KIND_YIELD_LOOP,
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 {
124  return ABTD_spinlock_try_acquire(&p_mutex->lock) ? ABT_ERR_MUTEX_LOCKED
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) {
161  ABTI_mutex_spinlock_no_recursion(p_mutex);
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 {
169  ABTI_mutex_spinlock_no_recursion(p_mutex);
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
177  ABTD_spinlock_acquire(&p_mutex->waiter_lock);
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);
181  ABTD_spinlock_release(&p_mutex->waiter_lock);
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 */
ABT_bool
int ABT_bool
Boolean type.
Definition: abt.h:1019
ABT_mutex
struct ABT_mutex_opaque * ABT_mutex
Mutex handle type.
Definition: abt.h:963
ABT_SYNC_EVENT_TYPE_MUTEX
@ ABT_SYNC_EVENT_TYPE_MUTEX
Definition: abt.h:684
ABT_SUCCESS
#define ABT_SUCCESS
Error code: the routine returns successfully.
Definition: abt.h:92
ABT_ERR_MUTEX_LOCKED
#define ABT_ERR_MUTEX_LOCKED
Error code: a return value when a mutex is locked.
Definition: abt.h:328
ABT_MUTEX_NULL
#define ABT_MUTEX_NULL
Definition: abt.h:1085