1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #ifndef PMIX_THREAD_H
25 #define PMIX_THREAD_H 1
26
27 #include "pmix_config.h"
28
29 #include <pthread.h>
30 #include <signal.h>
31
32 #include "src/class/pmix_object.h"
33 #if PMIX_ENABLE_DEBUG
34 #include "src/util/output.h"
35 #endif
36
37 #include "mutex.h"
38
39 BEGIN_C_DECLS
40
41 typedef void *(*pmix_thread_fn_t) (pmix_object_t *);
42
43 #define PMIX_THREAD_CANCELLED ((void*)1);
44
45 struct pmix_thread_t {
46 pmix_object_t super;
47 pmix_thread_fn_t t_run;
48 void* t_arg;
49 pthread_t t_handle;
50 };
51
52 typedef struct pmix_thread_t pmix_thread_t;
53
54 #if PMIX_ENABLE_DEBUG
55 PMIX_EXPORT extern bool pmix_debug_threads;
56 #endif
57
58
59 PMIX_EXPORT PMIX_CLASS_DECLARATION(pmix_thread_t);
60
61 #define pmix_condition_wait(a,b) pthread_cond_wait(a, &(b)->m_lock_pthread)
62 typedef pthread_cond_t pmix_condition_t;
63 #define pmix_condition_broadcast(a) pthread_cond_broadcast(a)
64 #define pmix_condition_signal(a) pthread_cond_signal(a)
65 #define PMIX_CONDITION_STATIC_INIT PTHREAD_COND_INITIALIZER
66
67 typedef struct {
68 pmix_status_t status;
69 pmix_mutex_t mutex;
70 pmix_condition_t cond;
71 volatile bool active;
72 } pmix_lock_t;
73
74 #define PMIX_CONSTRUCT_LOCK(l) \
75 do { \
76 PMIX_CONSTRUCT(&(l)->mutex, pmix_mutex_t); \
77 pthread_cond_init(&(l)->cond, NULL); \
78 (l)->active = true; \
79 } while(0)
80
81 #define PMIX_DESTRUCT_LOCK(l) \
82 do { \
83 PMIX_DESTRUCT(&(l)->mutex); \
84 pthread_cond_destroy(&(l)->cond); \
85 } while(0)
86
87
88 #if PMIX_ENABLE_DEBUG
89 #define PMIX_ACQUIRE_THREAD(lck) \
90 do { \
91 pmix_mutex_lock(&(lck)->mutex); \
92 if (pmix_debug_threads) { \
93 pmix_output(0, "Waiting for thread %s:%d", \
94 __FILE__, __LINE__); \
95 } \
96 while ((lck)->active) { \
97 pmix_condition_wait(&(lck)->cond, &(lck)->mutex); \
98 } \
99 if (pmix_debug_threads) { \
100 pmix_output(0, "Thread obtained %s:%d", \
101 __FILE__, __LINE__); \
102 } \
103 PMIX_ACQUIRE_OBJECT(lck); \
104 (lck)->active = true; \
105 } while(0)
106 #else
107 #define PMIX_ACQUIRE_THREAD(lck) \
108 do { \
109 pmix_mutex_lock(&(lck)->mutex); \
110 while ((lck)->active) { \
111 pmix_condition_wait(&(lck)->cond, &(lck)->mutex); \
112 } \
113 PMIX_ACQUIRE_OBJECT(lck); \
114 (lck)->active = true; \
115 } while(0)
116 #endif
117
118
119 #if PMIX_ENABLE_DEBUG
120 #define PMIX_WAIT_THREAD(lck) \
121 do { \
122 pmix_mutex_lock(&(lck)->mutex); \
123 if (pmix_debug_threads) { \
124 pmix_output(0, "Waiting for thread %s:%d", \
125 __FILE__, __LINE__); \
126 } \
127 while ((lck)->active) { \
128 pmix_condition_wait(&(lck)->cond, &(lck)->mutex); \
129 } \
130 if (pmix_debug_threads) { \
131 pmix_output(0, "Thread obtained %s:%d", \
132 __FILE__, __LINE__); \
133 } \
134 PMIX_ACQUIRE_OBJECT(lck); \
135 pmix_mutex_unlock(&(lck)->mutex); \
136 } while(0)
137 #else
138 #define PMIX_WAIT_THREAD(lck) \
139 do { \
140 pmix_mutex_lock(&(lck)->mutex); \
141 while ((lck)->active) { \
142 pmix_condition_wait(&(lck)->cond, &(lck)->mutex); \
143 } \
144 PMIX_ACQUIRE_OBJECT(lck); \
145 pmix_mutex_unlock(&(lck)->mutex); \
146 } while(0)
147 #endif
148
149
150 #if PMIX_ENABLE_DEBUG
151 #define PMIX_RELEASE_THREAD(lck) \
152 do { \
153 if (pmix_debug_threads) { \
154 pmix_output(0, "Releasing thread %s:%d", \
155 __FILE__, __LINE__); \
156 } \
157 (lck)->active = false; \
158 PMIX_POST_OBJECT(lck); \
159 pmix_condition_broadcast(&(lck)->cond); \
160 pmix_mutex_unlock(&(lck)->mutex); \
161 } while(0)
162 #else
163 #define PMIX_RELEASE_THREAD(lck) \
164 do { \
165 (lck)->active = false; \
166 PMIX_POST_OBJECT(lck); \
167 pmix_condition_broadcast(&(lck)->cond); \
168 pmix_mutex_unlock(&(lck)->mutex); \
169 } while(0)
170 #endif
171
172
173 #define PMIX_WAKEUP_THREAD(lck) \
174 do { \
175 pmix_mutex_lock(&(lck)->mutex); \
176 (lck)->active = false; \
177 PMIX_POST_OBJECT(lck); \
178 pmix_condition_broadcast(&(lck)->cond); \
179 pmix_mutex_unlock(&(lck)->mutex); \
180 } while(0)
181
182
183
184
185
186
187
188
189 #define PMIX_POST_OBJECT(o) pmix_atomic_wmb()
190
191
192
193 #define PMIX_ACQUIRE_OBJECT(o) pmix_atomic_rmb()
194
195
196 PMIX_EXPORT int pmix_thread_start(pmix_thread_t *);
197 PMIX_EXPORT int pmix_thread_join(pmix_thread_t *, void **thread_return);
198 PMIX_EXPORT bool pmix_thread_self_compare(pmix_thread_t*);
199 PMIX_EXPORT pmix_thread_t *pmix_thread_get_self(void);
200 PMIX_EXPORT void pmix_thread_kill(pmix_thread_t *, int sig);
201 PMIX_EXPORT void pmix_thread_set_main(void);
202
203 END_C_DECLS
204
205 #endif