[176] | 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 | } |
---|