1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
|
/* scheduler.h -*-C++-*-
*
*************************************************************************
*
* @copyright
* Copyright (C) 2009-2013, Intel Corporation
* All rights reserved.
*
* @copyright
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* @copyright
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
**************************************************************************/
/**
* @file scheduler.h
*
* @brief scheduler.h declares routines for the Intel Cilk Plus scheduler,
* making it the heart of the Intel Cilk Plus implementation.
*/
#ifndef INCLUDED_SCHEDULER_DOT_H
#define INCLUDED_SCHEDULER_DOT_H
#include <cilk/common.h>
#include <internal/abi.h>
#include "rts-common.h"
#include "full_frame.h"
#include "reducer_impl.h"
#include "global_state.h"
#ifdef CILK_RECORD_REPLAY
#include "record-replay.h"
#endif
__CILKRTS_BEGIN_EXTERN_C
/**
* @brief Flag to disable parallel reductions.
*
* Set to 0 to allow parallel reductions.
*/
#define DISABLE_PARALLEL_REDUCERS 0
/**
* @brief Debugging level for parallel reductions.
*
* Print debugging messages and assertions for parallel reducers. 0 is
* no debugging. A higher value generates more output.
*/
#define REDPAR_DEBUG 0
/**
* @brief Lock the worker mutex to allow exclusive access to the
* values in the @c __cilkrts_worker and local_state structures.
*
* @pre @c w->l->do_not_steal must not be set. Essentially this
* condition asserts that the worker is not locked recursively.
*
* @param w The worker to lock.
*/
COMMON_PORTABLE
void __cilkrts_worker_lock(__cilkrts_worker *w);
/**
* @brief Unlock the worker mutex.
*
* @pre @c w->l->do_not_steal must be set. Essentially this condition
* asserts that the worker has been previously locked.
*
* @param w The worker to unlock.
*/
COMMON_PORTABLE
void __cilkrts_worker_unlock(__cilkrts_worker *w);
/**
* @brief Push the next full frame to be made active in this worker
* and increment its join counter.
*
* __cilkrts_push_next_frame and pop_next_frame work on a one-element queue.
* This queue is used to communicate across the runtime from the code that
* wants to activate a frame to the code that can actually begin execution
* on that frame. They are asymetrical in that push increments the join
* counter but pop does not decrement it. Rather, a single push/pop
* combination makes a frame active and increments its join counter once.
*
* @note A system worker may chose to push work onto a user worker if
* the work is the continuation from a sync which only the user worker
* may complete.
*
* @param w The worker which the frame is to be pushed onto.
* @param ff The full_frame which is to be continued by the worker.
*/
COMMON_PORTABLE
void __cilkrts_push_next_frame(__cilkrts_worker *w,
full_frame *ff);
/**
* @brief Sync on this worker.
*
* If this worker is the last to reach the sync, execution may resume
* on this worker after the sync.
*
* If this worker is not the last spawned child to reach the sync,
* then execution is suspended and the worker will re-enter the
* scheduling loop, looking for work it can steal.
*
* This function will jump into the runtime to switch to the scheduling
* stack to implement most of its logic.
*
* @param w The worker which is executing the sync.
* @param sf The __cilkrts_stack_frame containing the sync.
*/
COMMON_PORTABLE
NORETURN __cilkrts_c_sync(__cilkrts_worker *w,
__cilkrts_stack_frame *sf);
/**
* @brief Worker @c w completely promotes its own deque, simulating the case
* where the whole deque is stolen.
*
* We use this mechanism to force the allocation of new storage for
* reducers for race-detection purposes.
*
* This method is called from the reducer lookup logic when
* @c g->force_reduce is set.
*
* @warning Use of "force_reduce" is known to have bugs when run with
* more than 1 worker.
*
* @param w The worker which is to have all entries in its deque
* promoted to full frames.
*/
COMMON_PORTABLE
void __cilkrts_promote_own_deque(__cilkrts_worker *w);
/**
* Called when a spawned function attempts to return and
* __cilkrts_undo_detach() fails. This can happen for two reasons:
*
* @li If another worker is considering stealing our parent, it bumps the
* exception pointer while it did so, which will cause __cilkrts_undo_detach()
* to fail. If the other worker didn't complete the steal of our parent, we
* still may be able to return to it, either because the steal attempt failed,
* or we won the race for the tail pointer.
*
* @li If the function's parent has been stolen then we cannot return. Instead
* we'll longjmp into the runtime to switch onto the scheduling stack to
* execute do_return_from_spawn() and determine what to do. Either this
* worker is the last one to the sync, in which case we need to jump to the
* sync, or this worker is not the last one to the sync, in which case we'll
* abandon this work and jump to the scheduling loop to search for more work
* we can steal.
*
* @param w The worker which attempting to return from a spawn to
* a stolen parent.
* @param returning_sf The stack frame which is returning.
*/
COMMON_PORTABLE
void __cilkrts_c_THE_exception_check(__cilkrts_worker *w,
__cilkrts_stack_frame *returning_sf);
/**
* @brief Return an exception to an stolen parent.
*
* Used by the gcc implementation of exceptions to return an exception
* to a stolen parent
*
* @param w The worker which attempting to return from a spawn with an
* exception to a stolen parent.
* @param returning_sf The stack frame which is returning.
*/
COMMON_PORTABLE
NORETURN __cilkrts_exception_from_spawn(__cilkrts_worker *w,
__cilkrts_stack_frame *returning_sf);
/**
* @brief Used by the Windows implementations of exceptions to migrate an exception
* across fibers.
*
* Call this function when an exception has been thrown and has to
* traverse across a steal. The exception has already been wrapped
* up, so all that remains is to longjmp() into the continuation,
* sync, and re-raise it.
*
* @param sf The __cilkrts_stack_frame for the frame that is attempting to
* return an exception to a stolen parent.
*/
void __cilkrts_migrate_exception (__cilkrts_stack_frame *sf);
/**
* @brief Return from a call, not a spawn, where this frame has ever
* been stolen.
*
* @param w The worker that is returning from a frame which was ever stolen.
*/
COMMON_PORTABLE
void __cilkrts_return(__cilkrts_worker *w);
/**
* @brief Special return from the initial frame.
*
* This method will be called from @c __cilkrts_leave_frame if
* @c CILK_FRAME_LAST is set.
*
* This function will do the things necessary to cleanup, and unbind the
* thread from the Intel Cilk Plus runtime. If this is the last user
* worker unbinding from the runtime, all system worker threads will be
* suspended.
*
* @pre @c w must be the currently executing worker, and must be a user
* worker.
*
* @param w The worker that's returning from the initial frame.
*/
COMMON_PORTABLE
void __cilkrts_c_return_from_initial(__cilkrts_worker *w);
/**
* @brief Used by exception handling code to pop an entry from the
* worker's deque.
*
* @param w Worker to pop the entry from
*
* @return __cilkrts_stack_frame of parent call
* @return NULL if the deque is empty
*/
COMMON_PORTABLE
__cilkrts_stack_frame *__cilkrts_pop_tail(__cilkrts_worker *w);
/**
* @brief Modifies the worker's protected_tail to prevent frames from
* being stolen.
*
* The Dekker protocol has been extended to only steal if head+1 is also
* less than protected_tail.
*
* @param w The worker to be modified.
* @param new_protected_tail The new setting for protected_tail, or NULL if the
* entire deque is to be protected
*
* @return Previous value of protected tail.
*/
COMMON_PORTABLE
__cilkrts_stack_frame *volatile *__cilkrts_disallow_stealing(
__cilkrts_worker *w,
__cilkrts_stack_frame *volatile *new_protected_tail);
/**
* @brief Restores the protected tail to a previous state, possibly
* allowing frames to be stolen.
*
* @param w The worker to be modified.
* @param saved_protected_tail A previous setting for protected_tail that is
* to be restored
*/
COMMON_PORTABLE
void __cilkrts_restore_stealing(
__cilkrts_worker *w,
__cilkrts_stack_frame *volatile *saved_protected_tail);
/**
* @brief Initialize a @c __cilkrts_worker.
*
* @note The memory for the worker must have been allocated outside
* this call.
*
* @param g The global_state_t.
* @param self The index into the global_state's array of workers for this
* worker, or -1 if this worker was allocated from the heap and cannot be
* stolen from.
* @param w The worker to be initialized.
*
* @return The initialized __cilkrts_worker.
*/
COMMON_PORTABLE
__cilkrts_worker *make_worker(global_state_t *g,
int self,
__cilkrts_worker *w);
/**
* @brief Free up any resources allocated for a worker.
*
* @note The memory for the @c __cilkrts_worker itself must be
* deallocated outside this call.
*
* @param w The worker to be destroyed.
*/
COMMON_PORTABLE
void destroy_worker (__cilkrts_worker *w);
/**
* @brief Initialize the runtime.
*
* If necessary, allocates and initializes the global state. If
* necessary, unsuspends the system workers.
*
* @param start Specifies whether the workers are to be unsuspended if
* they are suspended. Allows __cilkrts_init() to start up the runtime without
* releasing the system threads.
*/
COMMON_PORTABLE
void __cilkrts_init_internal(int start);
/**
* @brief Part of the sequence to shutdown the runtime.
*
* Specifically, this call frees the @c global_state_t for the runtime.
*
* @param g The global_state_t.
*/
COMMON_PORTABLE
void __cilkrts_deinit_internal(global_state_t *g);
/**
* Obsolete. We no longer need to import or export reducer maps.
*/
COMMON_PORTABLE
cilkred_map *__cilkrts_xchg_reducer(
__cilkrts_worker *w, cilkred_map *newmap) cilk_nothrow;
/**
* @brief Called when a user thread is bound to the runtime.
*
* If this action increments the count of bound user threads from 0 to
* 1, the system worker threads are unsuspended.
*
* If this action increments the count of bound user threads from 0 to
* 1, the system worker threads are unsuspended.
*
* @pre Global lock must be held.
* @param g The runtime global state.
*/
COMMON_PORTABLE
void __cilkrts_enter_cilk(global_state_t *g);
/**
* @brief Called when a user thread is unbound from the runtime.
*
* If this action decrements the count of bound user threads to 0, the
* system worker threads are suspended.
*
*
* @pre Global lock must be held.
*
* @param g The runtime global state.
*/
COMMON_PORTABLE
void __cilkrts_leave_cilk(global_state_t *g);
/**
* @brief cilk_fiber_proc that runs the main scheduler loop on a
* user worker.
*
* @pre fiber's owner field should be set to the correct __cilkrts_worker
* @pre fiber must be a user worker.
*
* @param fiber The scheduling fiber object.
*/
void scheduler_fiber_proc_for_user_worker(cilk_fiber *fiber);
/**
* @brief Prints out Cilk runtime statistics.
*
* @param g The runtime global state.
*
* This method is useful only for debugging purposes. No guarantees
* are made as to the validity of this data. :)
*/
COMMON_PORTABLE
void __cilkrts_dump_stats_to_stderr(global_state_t *g);
#ifdef CILK_RECORD_REPLAY
COMMON_PORTABLE
char * walk_pedigree_nodes(char *p, const __cilkrts_pedigree *pnode);
/**
* @brief Used by exception handling code to simulate the popping of
* an entry from the worker's deque.
*
* @param w Worker whose deque we want to check
*
* @return @c __cilkrts_stack_frame of parent call
* @return NULL if the deque is empty
*/
COMMON_PORTABLE
__cilkrts_stack_frame *simulate_pop_tail(__cilkrts_worker *w);
#endif
__CILKRTS_END_EXTERN_C
#endif // ! defined(INCLUDED_SCHEDULER_DOT_H)
|