1 | /* |
---|
2 | * swift_scheduler.c |
---|
3 | * |
---|
4 | * (c) 2009 Ionut Rosoiu <ionut.rosoiu@gmail.com> |
---|
5 | * |
---|
6 | */ |
---|
7 | |
---|
8 | #include "swift_scheduler.h" |
---|
9 | #include <stdlib.h> |
---|
10 | #include <sched.h> |
---|
11 | |
---|
12 | inline |
---|
13 | swift_thread_t* swift_get_steal_target(swift_context_t *context, swift_thread_t* thread) |
---|
14 | { |
---|
15 | /* round robin */ |
---|
16 | ++thread->round_robin_id; |
---|
17 | thread->round_robin_id %= context->thread_num; |
---|
18 | |
---|
19 | if (thread->round_robin_id == thread->id) { |
---|
20 | ++thread->round_robin_id; |
---|
21 | thread->round_robin_id %= context->thread_num; |
---|
22 | } |
---|
23 | |
---|
24 | return &context->threads[thread->round_robin_id]; |
---|
25 | } |
---|
26 | |
---|
27 | inline |
---|
28 | swift_frame_t* swift_get_frame(swift_context_t *context, swift_thread_t *thread) |
---|
29 | { |
---|
30 | swift_frame_t *frame = NULL; |
---|
31 | swift_thread_t *target = NULL; |
---|
32 | swift_status_t status; |
---|
33 | |
---|
34 | /* 1. get a frame from the bottom of the workqueue */ |
---|
35 | SWIFT_LOG(INFO, "[%d] get_frame_try_deq\n", thread->id); |
---|
36 | frame = swift_deque_pop(&thread->workque, &status); |
---|
37 | if (frame) { |
---|
38 | SWIFT_LOG_FRAME_INFO_STR("deq_bottom", thread, frame); |
---|
39 | goto exit; |
---|
40 | } |
---|
41 | |
---|
42 | /* 2. try to steal a frame */ |
---|
43 | target = swift_get_steal_target(context, thread); |
---|
44 | SWIFT_LOG(INFO, "[%d] get_frame_try_steal %d\n", thread->id, target->id); |
---|
45 | do { |
---|
46 | frame = swift_deque_steal(&target->workque, &status); |
---|
47 | } while (status == SWIFT_DEQUE_ABORT); |
---|
48 | |
---|
49 | if (frame) { |
---|
50 | SWIFT_LOG_FRAME_INFO_STR("-STOLEN-", thread, frame); |
---|
51 | goto exit; |
---|
52 | } |
---|
53 | |
---|
54 | //FIXME: experimental! |
---|
55 | sched_yield(); |
---|
56 | |
---|
57 | exit: |
---|
58 | return frame; |
---|
59 | } |
---|
60 | |
---|
61 | inline |
---|
62 | void swift_scheduler_execute(swift_thread_t *thread) |
---|
63 | { |
---|
64 | swift_frame_t *frame; |
---|
65 | |
---|
66 | // execute some work |
---|
67 | SWIFT_LOG(INFO, "[%d] sched_exec\n", thread->id); |
---|
68 | frame = swift_get_frame(thread->context, thread); |
---|
69 | |
---|
70 | if (frame) { |
---|
71 | SWIFT_LOG_FRAME_INFO_STR("scheduler_execute", thread, frame); |
---|
72 | frame->closure(thread, frame); |
---|
73 | } |
---|
74 | //else { |
---|
75 | // swift_backoff(thread, status); |
---|
76 | // SWIFT_LOG(INFO, "[%d] slept %u\n", thread->id, thread->last_sleep_time); |
---|
77 | //} |
---|
78 | } |
---|
79 | |
---|
80 | inline |
---|
81 | void swift_signal_frame_done(swift_thread_t *thread, swift_frame_t *frame) |
---|
82 | { |
---|
83 | swift_status_t status; |
---|
84 | |
---|
85 | SWIFT_LOG_FRAME_INFO_STR("frame_done_signal_sync", thread, frame); |
---|
86 | |
---|
87 | /* signal sync */ |
---|
88 | // decrement the number of frames needed to be sync'd |
---|
89 | SWIFT_ATOMIC_DECR(*frame->sync_frames_remaining); |
---|
90 | |
---|
91 | // this is the last frame for the sync |
---|
92 | #ifdef LOGGING_ON |
---|
93 | // if this is the last frame before the sync, signal sync done |
---|
94 | if (SWIFT_CAS(*frame->sync_frames_remaining, 0, 0)) { |
---|
95 | SWIFT_LOG_FRAME_INFO_STR("frame_done_signal_sync_FINAL", thread, frame); |
---|
96 | } |
---|
97 | #endif |
---|
98 | |
---|
99 | /* signal dependencies */ |
---|
100 | if (frame->dependencies_frame) { |
---|
101 | swift_frame_t *f = frame->dependencies_frame; |
---|
102 | SWIFT_LOG_FRAME_INFO_STR("frame_done_signal_deps", thread, frame); |
---|
103 | |
---|
104 | SWIFT_ATOMIC_DECR(f->dependencies_no); |
---|
105 | |
---|
106 | // this is the last frame for the dependent frame |
---|
107 | if (SWIFT_CAS(f->dependencies_no, 0, 0)) { |
---|
108 | SWIFT_LOG_FRAME_INFO_STR("frame_done_signal_deps_FINAL", thread, frame); |
---|
109 | swift_deque_push(&thread->workque, f, &status); |
---|
110 | } |
---|
111 | } |
---|
112 | } |
---|
113 | |
---|
114 | inline |
---|
115 | void swift_frame_done(swift_context_t *context, swift_thread_t *thread, swift_frame_t *frame) |
---|
116 | { |
---|
117 | |
---|
118 | /* the last frame for the parallel region */ |
---|
119 | if (SWIFT_FRAME_IS_END_PARALLEL(frame)) { |
---|
120 | SWIFT_LOG_FRAME_INFO_STR("--LAST FRAME DONE!--", thread, frame); |
---|
121 | thread->context->parallel_finished = 1; |
---|
122 | } |
---|
123 | |
---|
124 | thread->stats += 1; |
---|
125 | |
---|
126 | swift_retire_frame(thread, frame); |
---|
127 | } |
---|