ARGOBOTS
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_atomic_relaxed_store_uint32(&p_mutex->val, 0);
42  p_mutex->attr.attrs = ABTI_MUTEX_ATTR_NONE;
43  p_mutex->attr.max_handovers = ABTI_global_get_mutex_max_handovers();
44  p_mutex->attr.max_wakeups = ABTI_global_get_mutex_max_wakeups();
45 #ifndef ABT_CONFIG_USE_SIMPLE_MUTEX
46  p_mutex->p_htable = ABTI_thread_htable_create(gp_ABTI_global->max_xstreams);
47  p_mutex->p_handover = NULL;
48  p_mutex->p_giver = NULL;
49 #endif
50 }
51 
52 #ifdef ABT_CONFIG_USE_SIMPLE_MUTEX
53 #define ABTI_mutex_fini(p_mutex)
54 #else
55 static inline void ABTI_mutex_fini(ABTI_mutex *p_mutex)
56 {
57  ABTI_thread_htable_free(p_mutex->p_htable);
58 }
59 #endif
60 
61 static inline void ABTI_mutex_spinlock(ABTI_mutex *p_mutex)
62 {
63  /* ABTI_spinlock_ functions cannot be used since p_mutex->val can take
64  * other values (i.e., not UNLOCKED nor LOCKED.) */
65  while (!ABTD_atomic_bool_cas_weak_uint32(&p_mutex->val, 0, 1)) {
66  while (ABTD_atomic_acquire_load_uint32(&p_mutex->val) != 0)
67  ;
68  }
69  LOG_EVENT("%p: spinlock\n", p_mutex);
70 }
71 
72 static inline void ABTI_mutex_lock(ABTI_local **pp_local, ABTI_mutex *p_mutex)
73 {
74 #ifdef ABT_CONFIG_USE_SIMPLE_MUTEX
75  ABTI_local *p_local = *pp_local;
76  ABT_unit_type type = ABTI_self_get_type(p_local);
77  if (type == ABT_UNIT_TYPE_THREAD) {
78  LOG_EVENT("%p: lock - try\n", p_mutex);
79  while (!ABTD_atomic_bool_cas_weak_uint32(&p_mutex->val, 0, 1)) {
80  ABTI_thread_yield(pp_local, p_local->p_thread);
81  p_local = *pp_local;
82  }
83  LOG_EVENT("%p: lock - acquired\n", p_mutex);
84  } else {
85  ABTI_mutex_spinlock(p_mutex);
86  }
87 #else
88  int abt_errno;
89  ABT_unit_type type = ABTI_self_get_type(*pp_local);
90 
91  /* Only ULTs can yield when the mutex has been locked. For others,
92  * just call mutex_spinlock. */
93  if (type == ABT_UNIT_TYPE_THREAD) {
94  LOG_EVENT("%p: lock - try\n", p_mutex);
95  int c;
96  if ((c = ABTD_atomic_val_cas_strong_uint32(&p_mutex->val, 0, 1)) != 0) {
97  if (c != 2) {
98  c = ABTD_atomic_exchange_uint32(&p_mutex->val, 2);
99  }
100  while (c != 0) {
101  ABTI_mutex_wait(pp_local, p_mutex, 2);
102 
103  /* If the mutex has been handed over to the current ULT from
104  * other ULT on the same ES, we don't need to change the mutex
105  * state. */
106  if (p_mutex->p_handover) {
107  ABTI_thread *p_self = (*pp_local)->p_thread;
108  if (p_self == p_mutex->p_handover) {
109  p_mutex->p_handover = NULL;
110  ABTD_atomic_release_store_uint32(&p_mutex->val, 2);
111 
112  /* Push the previous ULT to its pool */
113  ABTI_thread *p_giver = p_mutex->p_giver;
114  ABTD_atomic_release_store_int(&p_giver->state,
116  ABTI_POOL_PUSH(p_giver->p_pool, p_giver->unit,
117  ABTI_self_get_native_thread_id(
118  *pp_local));
119  break;
120  }
121  }
122 
123  c = ABTD_atomic_exchange_uint32(&p_mutex->val, 2);
124  }
125  }
126  LOG_EVENT("%p: lock - acquired\n", p_mutex);
127  } else {
128  ABTI_mutex_spinlock(p_mutex);
129  }
130 
131 fn_exit:
132  return;
133 
134 fn_fail:
135  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
136  goto fn_exit;
137 #endif
138 }
139 
140 static inline int ABTI_mutex_trylock(ABTI_mutex *p_mutex)
141 {
142  if (!ABTD_atomic_bool_cas_strong_uint32(&p_mutex->val, 0, 1)) {
143  return ABT_ERR_MUTEX_LOCKED;
144  }
145  return ABT_SUCCESS;
146 }
147 
148 static inline void ABTI_mutex_unlock(ABTI_local *p_local, ABTI_mutex *p_mutex)
149 {
150 #ifdef ABT_CONFIG_USE_SIMPLE_MUTEX
151  ABTD_atomic_mem_barrier();
152  ABTD_atomic_release_store_uint32(&p_mutex->val, 0);
153  LOG_EVENT("%p: unlock w/o wake\n", p_mutex);
154 #else
155  if (ABTD_atomic_fetch_sub_uint32(&p_mutex->val, 1) != 1) {
156  ABTD_atomic_release_store_uint32(&p_mutex->val, 0);
157  LOG_EVENT("%p: unlock with wake\n", p_mutex);
158  ABTI_mutex_wake_de(p_local, p_mutex);
159  } else {
160  LOG_EVENT("%p: unlock w/o wake\n", p_mutex);
161  }
162 #endif
163 }
164 
165 static inline ABT_bool ABTI_mutex_equal(ABTI_mutex *p_mutex1,
166  ABTI_mutex *p_mutex2)
167 {
168  return (p_mutex1 == p_mutex2) ? ABT_TRUE : ABT_FALSE;
169 }
170 
171 #endif /* ABTI_MUTEX_H_INCLUDED */
#define ABT_ERR_MUTEX_LOCKED
Definition: abt.h:104
int ABT_bool
Definition: abt.h:309
struct ABT_mutex_opaque * ABT_mutex
Definition: abt.h:293
#define ABT_FALSE
Definition: abt.h:224
#define HANDLE_ERROR_FUNC_WITH_CODE(n)
Definition: abti_error.h:241
ABTI_global * gp_ABTI_global
Definition: global.c:14
#define ABT_SUCCESS
Definition: abt.h:64
#define LOG_EVENT(fmt,...)
Definition: abti_log.h:60
#define ABT_TRUE
Definition: abt.h:223
ABT_unit_type
Definition: abt.h:170
#define ABT_MUTEX_NULL
Definition: abt.h:348