Skip to content

Commit a429f7b

Browse files
ericxu233pcolberg
authored andcommitted
Refactor runtime multi-threading/synchronization support
First stage of multi-threading support refactor by providing a mutex wrapper class around current routines and using std::scoped_lock to follow RAII.
1 parent 1847ee9 commit a429f7b

28 files changed

+1416
-1570
lines changed

include/acl_thread.h

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
#include <stdarg.h>
1313
#include <stdio.h>
1414

15+
// System headers.
16+
#include <mutex>
17+
#include <thread>
18+
1519
#if defined(__cplusplus)
1620
extern "C" {
1721
#endif
@@ -23,10 +27,15 @@ extern "C" {
2327
#define ACL_TLS __declspec(thread)
2428
#endif
2529

30+
// Foward declaration
31+
class acl_mutex_wrapper_t;
32+
2633
extern ACL_TLS int acl_global_lock_count;
2734
extern ACL_TLS int acl_inside_sig_flag;
2835
extern ACL_TLS int acl_inside_sig_old_lock_count;
2936

37+
extern acl_mutex_wrapper_t acl_mutex_wrapper;
38+
3039
// -- signal handler functions --
3140
// When we enter a signal handler, we save "acl_global_lock_count" to
3241
// "acl_inside_sig_old_lock_count" temporarily. This is because the signal
@@ -75,10 +84,6 @@ static inline void acl_sig_unblock_signals() {
7584

7685
// -- global lock functions --
7786

78-
void acl_lock();
79-
void acl_unlock();
80-
int acl_suspend_lock();
81-
void acl_resume_lock(int lock_count);
8287
void acl_wait_for_device_update(cl_context context);
8388
void acl_signal_device_update();
8489

@@ -105,4 +110,31 @@ void acl_yield_lock_and_thread();
105110
} /* extern "C" */
106111
#endif
107112

113+
// -- RAII wrapper classes --
114+
115+
// To follow RAII, provide a mutex class acl_mutex_wrapper_t which may be used
116+
// with std::scoped_lock and std::unique_lock. Note that std::scoped_lock may
117+
// only be constructed with a single instance of acl_mutex_wrapper_t since the
118+
// latter only implements BasicLockable but not Lockable, due to a lack of
119+
// try_lock() functionality in acl_threadsupport.
120+
class acl_mutex_wrapper_t {
121+
public:
122+
void lock();
123+
void unlock();
124+
int suspend_lock();
125+
void resume_lock(int lock_count);
126+
};
127+
128+
class acl_suspend_lock_guard {
129+
public:
130+
explicit acl_suspend_lock_guard(acl_mutex_wrapper_t &mutex) : mutex(mutex) {
131+
lock_count = mutex.suspend_lock();
132+
};
133+
~acl_suspend_lock_guard() { mutex.resume_lock(lock_count); }
134+
135+
private:
136+
int lock_count;
137+
acl_mutex_wrapper_t &mutex;
138+
};
139+
108140
#endif // ACL_THREAD_H

include/acl_util.h

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -116,17 +116,6 @@ void acl_dump_mem(cl_mem mem);
116116
#endif
117117
/////////////////////
118118

119-
#define UNLOCK_RETURN(ret) \
120-
do { \
121-
acl_unlock(); \
122-
return (ret); \
123-
} while (0)
124-
#define UNLOCK_RETURN_VOID \
125-
do { \
126-
acl_unlock(); \
127-
return; \
128-
} while (0)
129-
130119
// This macro is used to signal failure from a function via "errcode_ret"
131120
// and return 0.
132121
#define BAIL(STATUS) \
@@ -136,13 +125,6 @@ void acl_dump_mem(cl_mem mem);
136125
} \
137126
return 0; \
138127
} while (0)
139-
#define UNLOCK_BAIL(STATUS) \
140-
do { \
141-
if (errcode_ret) { \
142-
*errcode_ret = (STATUS); \
143-
} \
144-
UNLOCK_RETURN(0); \
145-
} while (0)
146128

147129
// This is used to callback for a context error, assuming C is an
148130
// initialized context.
@@ -151,42 +133,31 @@ void acl_dump_mem(cl_mem mem);
151133
acl_context_callback(C, STR); \
152134
BAIL(STATUS); \
153135
} while (0)
154-
#define UNLOCK_BAIL_INFO(STATUS, C, STR) \
155-
do { \
156-
acl_context_callback(C, STR); \
157-
UNLOCK_BAIL(STATUS); \
158-
} while (0)
159136

160137
#define ERR_RET(STATUS, C, STR) \
161138
do { \
162139
acl_context_callback(C, STR); \
163140
return STATUS; \
164141
} while (0)
165-
#define UNLOCK_ERR_RET(STATUS, C, STR) \
166-
do { \
167-
acl_context_callback(C, STR); \
168-
UNLOCK_RETURN(STATUS); \
169-
} while (0)
170142

171143
// Caller only partly specified the buffer?
172144
// Caller isn't asking for any info at all?
173-
#define UNLOCK_VALIDATE_ARRAY_OUT_ARGS(buf_size, buf, answer_size_out, \
174-
context) \
145+
#define VALIDATE_ARRAY_OUT_ARGS(buf_size, buf, answer_size_out, context) \
175146
do { \
176147
if (buf && buf_size <= 0) { \
177148
acl_context_callback(context, \
178149
#buf " is specified but " #buf_size " is zero"); \
179-
UNLOCK_RETURN(CL_INVALID_VALUE); \
150+
return CL_INVALID_VALUE; \
180151
} \
181152
if (buf == 0 && buf_size > 0) { \
182153
acl_context_callback(context, #buf " is not specified but " #buf_size \
183154
" is positive"); \
184-
UNLOCK_RETURN(CL_INVALID_VALUE); \
155+
return CL_INVALID_VALUE; \
185156
} \
186157
if (answer_size_out == 0 && buf == 0) { \
187158
acl_context_callback(context, \
188159
#buf " and " #answer_size_out " are both zero"); \
189-
UNLOCK_RETURN(CL_INVALID_VALUE); \
160+
return CL_INVALID_VALUE; \
190161
} \
191162
} while (0)
192163

src/acl_command.cpp

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -38,22 +38,22 @@
3838
ACL_EXPORT
3939
CL_API_ENTRY cl_int CL_API_CALL
4040
clEnqueueBarrierIntelFPGA(cl_command_queue command_queue) {
41-
acl_lock();
41+
std::scoped_lock lock{acl_mutex_wrapper};
4242

4343
if (!acl_command_queue_is_valid(command_queue)) {
44-
UNLOCK_RETURN(CL_INVALID_COMMAND_QUEUE);
44+
return CL_INVALID_COMMAND_QUEUE;
4545
}
4646

4747
// For in order queue, since every event is executed in sequence,
4848
// there is an implicit barrier after each event.
4949
// enqueue barrier does not need to do anything
5050
if (!(command_queue->properties & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE)) {
51-
UNLOCK_RETURN(CL_SUCCESS);
51+
return CL_SUCCESS;
5252
}
5353
// OpenCL 1.2 spec: If event_wait_list is NULL, then this particular command
5454
// waits until all previous enqueued commands to command_queue have completed.
5555
cl_int status = clEnqueueBarrierWithWaitList(command_queue, 0, 0, NULL);
56-
UNLOCK_RETURN(status);
56+
return status;
5757
}
5858

5959
ACL_EXPORT
@@ -66,18 +66,18 @@ ACL_EXPORT
6666
CL_API_ENTRY cl_int CL_API_CALL
6767
clEnqueueMarkerIntelFPGA(cl_command_queue command_queue, cl_event *event) {
6868
cl_int result;
69-
acl_lock();
69+
std::scoped_lock lock{acl_mutex_wrapper};
7070

7171
if (!acl_command_queue_is_valid(command_queue)) {
72-
UNLOCK_RETURN(CL_INVALID_COMMAND_QUEUE);
72+
return CL_INVALID_COMMAND_QUEUE;
7373
}
7474

7575
if (!event)
76-
UNLOCK_RETURN(CL_INVALID_VALUE);
76+
return CL_INVALID_VALUE;
7777

7878
result = acl_create_event(command_queue, 0, 0, CL_COMMAND_MARKER, event);
7979

80-
UNLOCK_RETURN(result);
80+
return result;
8181
}
8282

8383
ACL_EXPORT
@@ -91,13 +91,13 @@ CL_API_ENTRY cl_int CL_API_CALL clEnqueueWaitForEventsIntelFPGA(
9191
cl_command_queue command_queue, cl_uint num_event, const cl_event *events) {
9292
cl_int result;
9393

94-
acl_lock();
94+
std::scoped_lock lock{acl_mutex_wrapper};
9595

9696
if (!acl_command_queue_is_valid(command_queue)) {
97-
UNLOCK_RETURN(CL_INVALID_COMMAND_QUEUE);
97+
return CL_INVALID_COMMAND_QUEUE;
9898
}
9999
if (num_event == 0 || events == 0) {
100-
UNLOCK_RETURN(CL_INVALID_VALUE);
100+
return CL_INVALID_VALUE;
101101
}
102102
cl_event event = NULL;
103103
result = acl_create_event(command_queue, num_event, events,
@@ -110,7 +110,7 @@ CL_API_ENTRY cl_int CL_API_CALL clEnqueueWaitForEventsIntelFPGA(
110110
result = CL_INVALID_EVENT;
111111
}
112112

113-
UNLOCK_RETURN(result);
113+
return result;
114114
}
115115

116116
ACL_EXPORT
@@ -129,16 +129,16 @@ clWaitForEventsIntelFPGA(cl_uint num_events, const cl_event *event_list) {
129129
cl_context context;
130130
bool first_yield_to_hal = true;
131131

132-
acl_lock();
132+
std::scoped_lock lock{acl_mutex_wrapper};
133133

134134
if (num_events == 0 || event_list == 0) {
135-
UNLOCK_RETURN(CL_INVALID_VALUE);
135+
return CL_INVALID_VALUE;
136136
}
137137

138138
#ifndef REMOVE_VALID_CHECKS
139139
result = acl_check_events(num_events, event_list);
140140
if (result != CL_SUCCESS) {
141-
UNLOCK_RETURN(CL_INVALID_EVENT);
141+
return CL_INVALID_EVENT;
142142
}
143143
#endif
144144

@@ -193,12 +193,12 @@ clWaitForEventsIntelFPGA(cl_uint num_events, const cl_event *event_list) {
193193
cl_uint i = 0;
194194
for (i = 0; i < num_events; ++i) {
195195
if (event_list[i]->execution_status < 0)
196-
UNLOCK_RETURN(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST);
196+
return CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST;
197197
}
198198
}
199199
#endif
200200

201-
UNLOCK_RETURN(result);
201+
return result;
202202
}
203203

204204
ACL_EXPORT
@@ -214,10 +214,10 @@ CL_API_ENTRY cl_int CL_API_CALL clEnqueueMarkerWithWaitListIntelFPGA(
214214
cl_int result;
215215
cl_event ret_event = NULL;
216216

217-
acl_lock();
217+
std::scoped_lock lock{acl_mutex_wrapper};
218218

219219
if (!acl_command_queue_is_valid(command_queue)) {
220-
UNLOCK_RETURN(CL_INVALID_COMMAND_QUEUE);
220+
return CL_INVALID_COMMAND_QUEUE;
221221
}
222222

223223
// Spec says:
@@ -248,7 +248,7 @@ CL_API_ENTRY cl_int CL_API_CALL clEnqueueMarkerWithWaitListIntelFPGA(
248248
if (ret_event)
249249
clReleaseEvent(ret_event); // free the ret event if the caller doesn't want
250250
// to return it
251-
UNLOCK_RETURN(result);
251+
return result;
252252
}
253253

254254
ACL_EXPORT
@@ -265,12 +265,12 @@ CL_API_ENTRY cl_int CL_API_CALL clEnqueueBarrierWithWaitListIntelFPGA(
265265
const cl_event *event_wait_list, cl_event *event) {
266266
cl_int result;
267267
cl_event local_event;
268-
acl_lock();
268+
std::scoped_lock lock{acl_mutex_wrapper};
269269

270270
result = clEnqueueMarkerWithWaitList(command_queue, num_events_in_wait_list,
271271
event_wait_list, &local_event);
272272
if (result != CL_SUCCESS) {
273-
UNLOCK_RETURN(result);
273+
return result;
274274
}
275275

276276
if (command_queue->properties & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE) {
@@ -282,7 +282,7 @@ CL_API_ENTRY cl_int CL_API_CALL clEnqueueBarrierWithWaitListIntelFPGA(
282282
} else {
283283
clReleaseEvent(local_event);
284284
}
285-
UNLOCK_RETURN(result);
285+
return result;
286286
}
287287

288288
ACL_EXPORT

0 commit comments

Comments
 (0)