random_scheduler.hpp (4053B)
1 /* Relacy Race Detector 2 * Copyright (c) 2008-2013, Dmitry S. Vyukov 3 * All rights reserved. 4 * This software is provided AS-IS with no warranty, either express or implied. 5 * This software is distributed under a license and may not be copied, 6 * modified or distributed except as expressly authorized under the 7 * terms of the license contained in the file LICENSE in this distribution. 8 */ 9 10 #ifndef RL_RANDOM_SCHEDULER_HPP 11 #define RL_RANDOM_SCHEDULER_HPP 12 #ifdef _MSC_VER 13 # pragma once 14 #endif 15 16 #include "base.hpp" 17 #include "scheduler.hpp" 18 #include "random.hpp" 19 20 21 namespace rl 22 { 23 24 25 template<thread_id_t thread_count> 26 class random_scheduler : public scheduler<random_scheduler<thread_count>, scheduler_thread_info, thread_count> 27 { 28 public: 29 typedef scheduler<random_scheduler<thread_count>, scheduler_thread_info, thread_count> base_t; 30 typedef typename base_t::thread_info_t thread_info_t; 31 typedef typename base_t::shared_context_t shared_context_t; 32 33 struct task_t 34 { 35 }; 36 37 random_scheduler(test_params& params, shared_context_t& ctx, thread_id_t dynamic_thread_count) 38 : base_t(params, ctx, dynamic_thread_count) 39 { 40 } 41 42 thread_id_t iteration_begin_impl() 43 { 44 rand_.seed(this->iter_); 45 unpark_reason reason; 46 return schedule_impl(reason, false); 47 } 48 49 bool iteration_end_impl() 50 { 51 return this->iter_ == this->params_.iteration_count; 52 } 53 54 thread_id_t schedule_impl(unpark_reason& reason, unsigned /*yield*/) 55 { 56 thread_id_t const running_thread_count = this->running_threads_count; 57 58 thread_id_t timed_thread_count = this->timed_thread_count_; 59 if (timed_thread_count) 60 { 61 thread_id_t cnt = running_thread_count ? timed_thread_count * 4 : timed_thread_count; 62 thread_id_t idx = rand_.rand() % cnt; 63 if (idx < timed_thread_count) 64 { 65 thread_info_t* thr = this->timed_threads_[idx]; 66 thread_id_t th = thr->index_; 67 RL_VERIFY(1 == thr->block_count_); 68 this->unpark_thread(th); 69 RL_VERIFY(thr->state_ == thread_state_running); 70 reason = unpark_reason_timeout; 71 return th; 72 } 73 } 74 75 thread_id_t spurious_thread_count = this->spurious_thread_count_; 76 if (spurious_thread_count && running_thread_count) 77 { 78 thread_id_t cnt = spurious_thread_count * 8; 79 thread_id_t idx = rand_.rand() % cnt; 80 if (idx < spurious_thread_count) 81 { 82 thread_info_t* thr = this->spurious_threads_[idx]; 83 thread_id_t th = thr->index_; 84 RL_VERIFY(1 == thr->block_count_); 85 this->unpark_thread(th); 86 RL_VERIFY(thr->state_ == thread_state_running); 87 reason = unpark_reason_spurious; 88 return th; 89 } 90 } 91 92 RL_VERIFY(running_thread_count); 93 unsigned index = rand_.rand() % running_thread_count; 94 thread_id_t th = this->running_threads[index]; 95 reason = unpark_reason_normal; 96 return th; 97 } 98 99 unsigned rand_impl(unsigned limit, sched_type t) 100 { 101 (void)t; 102 unsigned r = rand_.rand() % limit; 103 ///!!! 104 #ifdef RL_MY_TEST 105 if (this->iter_ == 8761115) 106 { 107 char buf [1024]; 108 sprintf(buf, "rand(%u, %u) = %u\n", t, limit, r); 109 OutputDebugStringA(buf); 110 } 111 #endif 112 return r; 113 } 114 115 iteration_t iteration_count_impl() 116 { 117 return this->params_.iteration_count; 118 } 119 120 void get_state_impl(std::ostream& /*ss*/) 121 { 122 } 123 124 void set_state_impl(std::istream& /*ss*/) 125 { 126 } 127 128 void on_thread_block(thread_id_t /*th*/, bool /*yield*/) 129 { 130 } 131 132 private: 133 random_generator rand_; 134 135 RL_NOCOPY(random_scheduler); 136 }; 137 138 139 } 140 141 #endif