master
h 226 lines 8.54 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 lxtevent.c
8
9 Abstract:
10
11 This file contains synchronization event primitive support.
12
13 --*/
14
15 #include <pthread.h>
16
17 //
18 // Synchronization event usable for synchronizing threads and forked processes.
19 //
20
21 typedef struct _LXT_SYNCHRONIZATION_EVENT
22 {
23 pthread_cond_t WaitConditionalVariable;
24 pthread_condattr_t ConditionVariableAttribute;
25 pthread_mutex_t Lock;
26 pthread_mutexattr_t LockAttribute;
27 int Ready;
28 int Fail;
29 } LXT_SYNCHRONIZATION_EVENT, *PLXT_SYNCHRONIZATION_EVENT;
30
31 int LxtSynchronizationEventClear(PLXT_SYNCHRONIZATION_EVENT Event);
32
33 int LxtSynchronizationEventDestroy(PLXT_SYNCHRONIZATION_EVENT* Event);
34
35 int LxtSynchronizationEventFail(PLXT_SYNCHRONIZATION_EVENT Event);
36
37 int LxtSynchronizationEventInit(PLXT_SYNCHRONIZATION_EVENT* Event);
38
39 int LxtSynchronizationEventReset(PLXT_SYNCHRONIZATION_EVENT Event);
40
41 int LxtSynchronizationEventSet(PLXT_SYNCHRONIZATION_EVENT Event);
42
43 int LxtSynchronizationEventWait(PLXT_SYNCHRONIZATION_EVENT Event);
44
45 //
46 // Synchronization point based on synchronization event.
47 //
48
49 #define LXT_SYNCHRONIZATION_POINT_DECLARE_FOR(_ChildPidVariable_) \
50 PLXT_SYNCHRONIZATION_EVENT LxtSync##_ChildPidVariable_##Parent; \
51 PLXT_SYNCHRONIZATION_EVENT LxtSync##_ChildPidVariable_##Child;
52
53 #define LXT_SYNCHRONIZATION_POINT_DECLARE_FOR_STATIC(_ChildPidVariable_) \
54 static PLXT_SYNCHRONIZATION_EVENT LxtSync##_ChildPidVariable_##Parent; \
55 static PLXT_SYNCHRONIZATION_EVENT LxtSync##_ChildPidVariable_##Child;
56
57 #define LXT_SYNCHRONIZATION_POINT_INIT_SYNCVARS(_ParentVar_, _ChildVar_) \
58 (_ParentVar_) = NULL; \
59 (_ChildVar_) = NULL; \
60 LxtCheckResult(LxtSynchronizationEventInit(&_ParentVar_)); \
61 LxtCheckResult(LxtSynchronizationEventInit(&_ChildVar_));
62
63 #define LXT_SYNCHRONIZATION_POINT_INIT_FOR(_ChildPidVariable_) \
64 LXT_SYNCHRONIZATION_POINT_INIT_SYNCVARS(LxtSync##_ChildPidVariable_##Parent, LxtSync##_ChildPidVariable_##Child)
65
66 #define LXT_SYNCHRONIZATION_POINT_INIT() LXT_SYNCHRONIZATION_POINT_INIT_FOR(ChildPid)
67
68 #define LXT_SYNCHRONIZATION_POINT_DESTROY_SYNCVARS(_ParentVar_, _ChildVar_) \
69 LxtSynchronizationEventDestroy(&(_ParentVar_)); \
70 LxtSynchronizationEventDestroy(&(_ChildVar_));
71
72 #define LXT_SYNCHRONIZATION_POINT_DESTROY_FOR(_ChildPidVariable_) \
73 LXT_SYNCHRONIZATION_POINT_DESTROY_SYNCVARS(LxtSync##_ChildPidVariable_##Parent, LxtSync##_ChildPidVariable_##Child)
74
75 #define LXT_SYNCHRONIZATION_POINT_DESTROY() LXT_SYNCHRONIZATION_POINT_DESTROY_FOR(ChildPid)
76
77 #define LXT_SYNCHRONIZATION_POINT_START_SYNCVARS(_ParentVar_, _ChildVar_) \
78 LxtSynchronizationEventReset(_ChildVar_); \
79 LxtSynchronizationEventReset(_ParentVar_);
80
81 #define LXT_SYNCHRONIZATION_POINT_START_FOR(_ChildPidVariable_) \
82 LXT_SYNCHRONIZATION_POINT_START_SYNCVARS(LxtSync##_ChildPidVariable_##Child, LxtSync##_ChildPidVariable_##Parent)
83
84 #define LXT_SYNCHRONIZATION_POINT_START() LXT_SYNCHRONIZATION_POINT_START_FOR(ChildPid)
85
86 #define LXT_SYNCHRONIZATION_POINT_END_SYNCVARS(_ChildId_, _ParentVar_, _ChildVar_, _Destroy_) \
87 if (((_ChildId_) >= 0) && (Result < 0)) \
88 { \
89 LxtLogError("Failing synchronization points."); \
90 LxtSynchronizationEventFail(_ChildVar_); \
91 LxtSynchronizationEventFail(_ParentVar_); \
92 } \
93 if ((_ChildId_) > 0) \
94 { \
95 if (TEMP_FAILURE_RETRY(waitpid((_ChildId_), &Status, 0)) >= 0) \
96 { \
97 if (!WIFEXITED(Status)) \
98 { \
99 LxtLogInfo("Child exited uncleanly (Child = %d, Status = %x)", (_ChildId_), Status); \
100 Result = LXT_RESULT_FAILURE; \
101 } \
102 else \
103 { \
104 Result = (int)(char)WEXITSTATUS(Status); \
105 } \
106 } \
107 else \
108 { \
109 Result = errno; \
110 LxtLogInfo("Failed wait on child %d with errno %d", (_ChildId_), Result); \
111 } \
112 if ((Result == LXT_RESULT_SUCCESS) && ((_ChildVar_)->Fail == 1)) \
113 { \
114 LxtLogInfo("Child failed"); \
115 Result = LXT_RESULT_FAILURE; \
116 } \
117 if ((_Destroy_) != FALSE) \
118 { \
119 LXT_SYNCHRONIZATION_POINT_DESTROY_SYNCVARS(_ParentVar_, _ChildVar_) \
120 } \
121 } \
122 else if ((_ChildId_) == 0) \
123 { \
124 _exit(Result); \
125 }
126
127 #define LXT_SYNCHRONIZATION_POINT_END_FOR(_ChildPidVariable_, _Destroy_) \
128 LXT_SYNCHRONIZATION_POINT_END_SYNCVARS((_ChildPidVariable_), LxtSync##_ChildPidVariable_##Parent, LxtSync##_ChildPidVariable_##Child, _Destroy_)
129
130 #define LXT_SYNCHRONIZATION_POINT_END() LXT_SYNCHRONIZATION_POINT_END_FOR(ChildPid, FALSE)
131
132 #define LXT_SYNCHRONIZATION_POINT_PTHREAD_END_THREAD_SYNCVARS(_ParentVar_, _ChildVar_) \
133 if (Result < 0) \
134 { \
135 LxtLogError("Failing synchronization points."); \
136 LxtSynchronizationEventFail(_ChildVar_); \
137 LxtSynchronizationEventFail(_ParentVar_); \
138 }
139
140 #define LXT_SYNCHRONIZATION_POINT_PTHREAD_END_THREAD_FOR(_SyncIdVariable_) \
141 LXT_SYNCHRONIZATION_POINT_PTHREAD_END_THREAD_SYNCVARS(LxtSync##_SyncIdVariable_##Parent, LxtSync##_SyncIdVariable_##Child)
142
143 #define LXT_SYNCHRONIZATION_POINT_PTHREAD_END_THREAD() LXT_SYNCHRONIZATION_POINT_PTHREAD_END_THREAD_FOR(ChildPid)
144
145 #define LXT_SYNCHRONIZATION_POINT_PTHREAD_END_PARENT_SYNCVARS(_ThreadId_, _ParentVar_, _ChildVar_) \
146 if (Result < 0) \
147 { \
148 LxtLogError("Failing synchronization points."); \
149 LxtSynchronizationEventFail(_ChildVar_); \
150 LxtSynchronizationEventFail(_ParentVar_); \
151 } \
152 if (((_ThreadId_) > 0) && (pthread_join((_ThreadId_), &Status) == 0)) \
153 { \
154 if (Status != 0) \
155 { \
156 LxtLogInfo("Thread exited uncleanly (Thread = %d, Status = %x)", (_ThreadId_), (int)(long)Status); \
157 Result = LXT_RESULT_FAILURE; \
158 } \
159 } \
160 else if ((_ThreadId_) > 0) \
161 { \
162 Result = errno; \
163 LxtLogInfo("Failed wait on thread %d with errno %d", (_ThreadId_), Result); \
164 } \
165 if ((Result == LXT_RESULT_SUCCESS) && ((_ChildVar_)->Fail == 1)) \
166 { \
167 LxtLogInfo("Thread failed"); \
168 Result = LXT_RESULT_FAILURE; \
169 }
170
171 #define LXT_SYNCHRONIZATION_POINT_PTHREAD_END_PARENT_FOR(_ThreadId_, _SyncIdVariable_) \
172 LXT_SYNCHRONIZATION_POINT_PTHREAD_END_PARENT_SYNCVARS((_ThreadId_), LxtSync##_SyncIdVariable_##Parent, LxtSync##_SyncIdVariable_##Child)
173
174 #define LXT_SYNCHRONIZATION_POINT_PTHREAD_END_PARENT(_ThreadId_) \
175 LXT_SYNCHRONIZATION_POINT_PTHREAD_END_PARENT_FOR(_ThreadId_, ChildPid)
176
177 #define LXT_SYNCHRONIZATION_POINT_CLEAR_FOR(_ChildPidVariable_) \
178 if (Result < 0) \
179 { \
180 LxtCheckResult(LxtSynchronizationEventClear(LxtSync##_ChildPidVariable_##Child)); \
181 LxtCheckResult(LxtSynchronizationEventClear(LxtSync##_ChildPidVariable_##Parent)); \
182 }
183
184 #define LXT_SYNCHRONIZATION_POINT_CLEAR() LXT_SYNCHRONIZATION_POINT_CLEAR_FOR(ChildPid)
185
186 #define LXT_SYNCHRONIZATION_POINT_SYNCVARS(_IsChild_, _ParentVar_, _ChildVar_) \
187 if ((_IsChild_) != FALSE) \
188 { \
189 LxtCheckResult(LxtSynchronizationEventWait(_ChildVar_)); \
190 LxtCheckResult(LxtSynchronizationEventClear(_ChildVar_)); \
191 LxtCheckResult(LxtSynchronizationEventSet(_ParentVar_)); \
192 } \
193 else \
194 { \
195 LxtCheckResult(LxtSynchronizationEventSet(_ChildVar_)); \
196 LxtCheckResult(LxtSynchronizationEventWait(_ParentVar_)); \
197 LxtCheckResult(LxtSynchronizationEventClear(_ParentVar_)); \
198 }
199
200 #define LXT_SYNCHRONIZATION_POINT_CHILD_FOR(_ChildPidVariable_) \
201 LXT_SYNCHRONIZATION_POINT_SYNCVARS(TRUE, LxtSync##_ChildPidVariable_##Parent, LxtSync##_ChildPidVariable_##Child)
202
203 #define LXT_SYNCHRONIZATION_POINT_PARENT_FOR(_ChildPidVariable_) \
204 LXT_SYNCHRONIZATION_POINT_SYNCVARS(FALSE, LxtSync##_ChildPidVariable_##Parent, LxtSync##_ChildPidVariable_##Child)
205
206 #define LXT_SYNCHRONIZATION_POINT_FOR(_ChildPidVariable_) \
207 if ((_ChildPidVariable_) == 0) \
208 { \
209 LXT_SYNCHRONIZATION_POINT_CHILD_FOR(_ChildPidVariable_); \
210 } \
211 else \
212 { \
213 LXT_SYNCHRONIZATION_POINT_PARENT_FOR(_ChildPidVariable_); \
214 }
215
216 #define LXT_SYNCHRONIZATION_POINT_CHILD() LXT_SYNCHRONIZATION_POINT_CHILD_FOR(ChildPid)
217
218 #define LXT_SYNCHRONIZATION_POINT_PARENT() LXT_SYNCHRONIZATION_POINT_PARENT_FOR(ChildPid)
219
220 #define LXT_SYNCHRONIZATION_POINT() LXT_SYNCHRONIZATION_POINT_FOR(ChildPid);
221
222 //
223 // Declare global synchronization values for common ChildPid variable.
224 //
225
226 LXT_SYNCHRONIZATION_POINT_DECLARE_FOR_STATIC(ChildPid)