1/** 2 * \file 3 * \brief Kernel round-robin scheduling policy 4 */ 5 6/* 7 * Copyright (c) 2007, 2008, 2009, 2010, 2013, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <kernel.h> 16#include <dispatch.h> 17#include <kcb.h> 18 19#include <timer.h> // update_sched_timer 20 21/** 22 * \brief Scheduler policy. 23 * 24 * \return Next DCB to schedule or NULL if wait for interrupts. 25 */ 26struct dcb *schedule(void) 27{ 28 // empty ring 29 if(kcb_current->ring_current == NULL) { 30 return NULL; 31 } 32 33 assert(kcb_current->ring_current->next != NULL); 34 assert(kcb_current->ring_current->prev != NULL); 35 36 kcb_current->ring_current = kcb_current->ring_current->next; 37 #ifdef CONFIG_ONESHOT_TIMER 38 update_sched_timer(kernel_now + kernel_timeslice); 39 #endif 40 return ring_current; 41} 42 43void make_runnable(struct dcb *dcb) 44{ 45 // Insert into schedule ring if not in there already 46 if(dcb->prev == NULL || dcb->next == NULL) { 47 assert(dcb->prev == NULL && dcb->next == NULL); 48 49 // Ring empty 50 if(kcb_current->ring_current == NULL) { 51 kcb_current->ring_current = dcb; 52 dcb->next = dcb; 53 } 54 55 // Insert after current ring position 56 dcb->prev = kcb_current->ring_current; 57 dcb->next = kcb_current->ring_current->next; 58 kcb_current->ring_current->next->prev = dcb; 59 kcb_current->ring_current->next = dcb; 60 } 61} 62 63/** 64 * \brief Remove 'dcb' from scheduler ring. 65 * 66 * Removes dispatcher 'dcb' from the scheduler ring. If it was not in 67 * the ring, this function is a no-op. The postcondition for this 68 * function is that dcb is not in the ring. 69 * 70 * \param dcb Pointer to DCB to remove. 71 */ 72void scheduler_remove(struct dcb *dcb) 73{ 74 // No-op if not in scheduler ring 75 if(dcb->prev == NULL || dcb->next == NULL) { 76 assert(dcb->prev == NULL && dcb->next == NULL); 77 return; 78 } 79 80 struct dcb *next = kcb_current->ring_current->next; 81 82 // Remove dcb from scheduler ring 83 dcb->prev->next = dcb->next; 84 dcb->next->prev = dcb->prev; 85 dcb->prev = dcb->next = NULL; 86 87 // Removing ring_current 88 if(dcb == kcb_current->ring_current) { 89 if(dcb == next) { 90 // Only guy in the ring 91 kcb_current->ring_current = NULL; 92 } else { 93 // Advance ring_current 94 kcb_current->ring_current = next; 95 } 96 } 97} 98 99/** 100 * \brief Yield 'dcb' for the rest of the current timeslice. 101 * 102 * Re-sorts 'dcb' into the scheduler queue with its release time increased by 103 * the timeslice period. It is an error to yield a dispatcher not in the 104 * scheduler queue. 105 * 106 * \param dcb Pointer to DCB to remove. 107 */ 108void scheduler_yield(struct dcb *dcb) 109{ 110 if(dcb->prev == NULL || dcb->next == NULL) { 111 struct dispatcher_shared_generic *dsg = 112 get_dispatcher_shared_generic(dcb->disp); 113 panic("Yield of %.*s not in scheduler queue", DISP_NAME_LEN, 114 dsg->name); 115 } 116 117 // No-op for the round-robin scheduler 118} 119 120void scheduler_reset_time(void) 121{ 122 // No-Op in RR scheduler 123} 124 125void scheduler_convert(void) 126{ 127 enum sched_state from = kcb_current->sched; 128 switch (from) { 129 case SCHED_RBED: 130 { 131 // initialize RR ring 132 struct dcb *last = NULL; 133 for (struct dcb *i = kcb_current->queue_head; i; i = i->next) 134 { 135 i->prev = last; 136 last = i; 137 } 138 // at this point: we have a dll, but need to close the ring 139 kcb_current->queue_head->prev = kcb_current->queue_tail; 140 kcb_current->queue_tail->next = kcb_current->queue_head; 141 break; 142 } 143 case SCHED_RR: 144 // do nothing 145 break; 146 default: 147 printf("don't know how to convert %d to RBED state\n", from); 148 break; 149 } 150 kcb_current->ring_current = kcb_current->queue_head; 151 for (struct dcb *i = kcb_current->ring_current; i != kcb_current->ring_current; i=i->next) { 152 printf("dcb %p\n prev=%p\n next=%p\n", i, i->prev, i->next); 153 } 154} 155 156void scheduler_restore_state(void) 157{ 158 // No-Op in RR scheduler 159} 160