diff --git a/src/backend/scheduler.cc b/src/backend/scheduler.cc index 909ae3e..115b266 100644 --- a/src/backend/scheduler.cc +++ b/src/backend/scheduler.cc @@ -90,14 +90,6 @@ update_requests_for_old_running_thread(DynamicThread& running_thread) { DynamicRequest& rq = **r_it; - // If the running thread terminated uncoditionally put them in exhausted state - if(running_terminated) - { - SubRequests& subreqs = rq.get_dynamic_subrequests(); - for(SubRequests::iterator s_it = subreqs.begin(); s_it != subreqs.end(); s_it++) - (*s_it)->set_state(Request::state_exhausted); - continue; // go to next request - } if(rq.get_state() == Request::state_allocated) { @@ -121,6 +113,14 @@ update_requests_for_old_running_thread(DynamicThread& running_thread) } } } + // If the running thread terminated uncoditionally put them in exhausted state + if(running_terminated) + { + SubRequests& subreqs = rq.get_dynamic_subrequests(); + for(SubRequests::iterator s_it = subreqs.begin(); s_it != subreqs.end(); s_it++) + (*s_it)->set_state(Request::state_exhausted); + continue; // go to next request + } } //~ for(over requests) } @@ -276,12 +276,39 @@ Scheduler::step_forward(History& history, CPUPolicy& cpu_policy) throw(UserInter } + + // Try to continue running the current running thread + if (running_thread != NULL && running_thread->get_state() == Schedulable::state_running) + { + // the thread may block on raising a request + Requests& reqs = running_thread->get_dynamic_requests(); + for(Requests::iterator r_it = reqs.begin(); r_it != reqs.end(); r_it++) + { + DynamicRequest& rq = **r_it; + if (rq.get_state() == Request::state_future + && rq.get_instant() == running_thread->get_elapsed_time()) + { + SubRequests& subreqs = rq.get_dynamic_subrequests(); + for(SubRequests::iterator s_it = subreqs.begin(); s_it != subreqs.end(); s_it++) + { + DynamicSubRequest& subr = **s_it; + // FIXME: allocation is always granted, by now. We'll need queues to + // implement it correctly + if(subr.get_state() == Request::state_future) + subr.set_state(Request::state_allocated); + } + } + } + } + + // ?. Ask the policy to sort the queue. We do this multiple time if we must select // a new thread and it can't run for some reason (goes blocked, or terminates). - bool selected_cant_run; + bool found = true; do { - selected_cant_run = false; + printf("\n looking for a running one"); + found = true; prepare_ready_queue(*new_snapshot, all_threads); if(_ready_queue->size() == 0) @@ -291,21 +318,47 @@ Scheduler::step_forward(History& history, CPUPolicy& cpu_policy) throw(UserInter DynamicThread& candidate = (DynamicThread&) _ready_queue->get_item_at(0); + + // the thread may block on raising a request + Requests& reqs = candidate.get_dynamic_requests(); + for(Requests::iterator r_it = reqs.begin(); r_it != reqs.end(); r_it++) + { + DynamicRequest& rq = **r_it; + if (rq.get_state() == Request::state_future + && rq.get_instant() == candidate.get_elapsed_time()) + { + SubRequests& subreqs = rq.get_dynamic_subrequests(); + for(SubRequests::iterator s_it = subreqs.begin(); s_it != subreqs.end(); s_it++) + { + DynamicSubRequest& subr = **s_it; + // FIXME: allocation is always granted, by now. We'll need queues to + // implement it correctly + if(subr.get_state() == Request::state_future) + subr.set_state(Request::state_allocated); + } + } + } + + // We could have threads with 0 duration. Silly, but possible. + // the silly thing was to permit the user to do this :P if(candidate.get_total_cpu_time() - candidate.get_elapsed_time() == 0) { candidate.set_last_acquisition(current_instant); candidate.set_last_release(current_instant); candidate.set_state(Schedulable::state_terminated); - // FIXME : check requests for thread at instant 0? - selected_cant_run = true; + // FIXED : check requests for thread at instant 0? + // the real question is: should we check for requests raised at + // the thread last instant? the answer is: who cares? + // doing it or not is a matter of cut-n-paste + found = false; continue; } // FIXME : check if the first thread of the queue blocks } - while(selected_cant_run); + while(!found); // ?. Finally select the new thread (if appropriate); now we're sure it can run if(_ready_queue->size() > 0 && (running_thread == NULL || running_thread->get_state() != Schedulable::state_running)) @@ -317,6 +370,8 @@ Scheduler::step_forward(History& history, CPUPolicy& cpu_policy) throw(UserInter // removes running element from the ready queue // since no method was provided to erase an item in the queue, we should rebuild it. // this is pointless. I just added the method. + // rebuilding the ready queue may corrupt the order set by the policy: + // this is not acceptable, nor it is asking the policy to resort it. _ready_queue->erase_first(); }