ia64/xen-unstable

view extras/mini-os/sched.c @ 16513:b1da8762f853

blktap: remove unused headers.

Attached patch removes unused linux specific headers
and makes bswap.h ready for BSD support.

This is first step for BSD support in blktap. More to come.
No functional change.

Signed-off-by: Christoph Egger <Christoph.Egger@amd.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Dec 04 10:48:28 2007 +0000 (2007-12-04)
parents 96409cebd74b
children b18f70656fdb
line source
1 /*
2 ****************************************************************************
3 * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
4 ****************************************************************************
5 *
6 * File: sched.c
7 * Author: Grzegorz Milos
8 * Changes: Robert Kaiser
9 *
10 * Date: Aug 2005
11 *
12 * Environment: Xen Minimal OS
13 * Description: simple scheduler for Mini-Os
14 *
15 * The scheduler is non-preemptive (cooperative), and schedules according
16 * to Round Robin algorithm.
17 *
18 ****************************************************************************
19 * Permission is hereby granted, free of charge, to any person obtaining a copy
20 * of this software and associated documentation files (the "Software"), to
21 * deal in the Software without restriction, including without limitation the
22 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
23 * sell copies of the Software, and to permit persons to whom the Software is
24 * furnished to do so, subject to the following conditions:
25 *
26 * The above copyright notice and this permission notice shall be included in
27 * all copies or substantial portions of the Software.
28 *
29 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
34 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
35 * DEALINGS IN THE SOFTWARE.
36 */
38 #include <os.h>
39 #include <hypervisor.h>
40 #include <time.h>
41 #include <mm.h>
42 #include <types.h>
43 #include <lib.h>
44 #include <xmalloc.h>
45 #include <list.h>
46 #include <sched.h>
47 #include <semaphore.h>
50 #ifdef SCHED_DEBUG
51 #define DEBUG(_f, _a...) \
52 printk("MINI_OS(file=sched.c, line=%d) " _f "\n", __LINE__, ## _a)
53 #else
54 #define DEBUG(_f, _a...) ((void)0)
55 #endif
57 struct thread *idle_thread = NULL;
58 LIST_HEAD(exited_threads);
60 void inline print_runqueue(void)
61 {
62 struct list_head *it;
63 struct thread *th;
64 list_for_each(it, &idle_thread->thread_list)
65 {
66 th = list_entry(it, struct thread, thread_list);
67 printk(" Thread \"%s\", runnable=%d\n", th->name, is_runnable(th));
68 }
69 printk("\n");
70 }
72 /* Find the time when the next timeout expires. If this is more than
73 10 seconds from now, return 10 seconds from now. */
74 static s_time_t blocking_time(void)
75 {
76 struct thread *thread;
77 struct list_head *iterator;
78 s_time_t min_wakeup_time;
79 unsigned long flags;
80 local_irq_save(flags);
81 /* default-block the domain for 10 seconds: */
82 min_wakeup_time = NOW() + SECONDS(10);
84 /* Thread list needs to be protected */
85 list_for_each(iterator, &idle_thread->thread_list)
86 {
87 thread = list_entry(iterator, struct thread, thread_list);
88 if(!is_runnable(thread) && thread->wakeup_time != 0LL)
89 {
90 if(thread->wakeup_time < min_wakeup_time)
91 {
92 min_wakeup_time = thread->wakeup_time;
93 }
94 }
95 }
96 local_irq_restore(flags);
97 return(min_wakeup_time);
98 }
100 /* Wake up all threads with expired timeouts. */
101 static void wake_expired(void)
102 {
103 struct thread *thread;
104 struct list_head *iterator;
105 s_time_t now = NOW();
106 unsigned long flags;
107 local_irq_save(flags);
108 /* Thread list needs to be protected */
109 list_for_each(iterator, &idle_thread->thread_list)
110 {
111 thread = list_entry(iterator, struct thread, thread_list);
112 if(!is_runnable(thread) && thread->wakeup_time != 0LL)
113 {
114 if(thread->wakeup_time <= now)
115 wake(thread);
116 }
117 }
118 local_irq_restore(flags);
119 }
121 void schedule(void)
122 {
123 struct thread *prev, *next, *thread;
124 struct list_head *iterator;
125 unsigned long flags;
126 prev = current;
127 local_irq_save(flags);
128 if (in_callback) {
129 printk("Must not call schedule() from a callback\n");
130 BUG();
131 }
132 if (flags) {
133 printk("Must not call schedule() with IRQs disabled\n");
134 BUG();
135 }
136 list_for_each(iterator, &exited_threads)
137 {
138 thread = list_entry(iterator, struct thread, thread_list);
139 if(thread != prev)
140 {
141 list_del(&thread->thread_list);
142 free_pages(thread->stack, 1);
143 xfree(thread);
144 }
145 }
146 next = idle_thread;
147 /* Thread list needs to be protected */
148 list_for_each(iterator, &idle_thread->thread_list)
149 {
150 thread = list_entry(iterator, struct thread, thread_list);
151 if(is_runnable(thread))
152 {
153 next = thread;
154 /* Put this thread on the end of the list */
155 list_del(&thread->thread_list);
156 list_add_tail(&thread->thread_list, &idle_thread->thread_list);
157 break;
158 }
159 }
160 local_irq_restore(flags);
161 /* Interrupting the switch is equivalent to having the next thread
162 inturrupted at the return instruction. And therefore at safe point. */
163 if(prev != next) switch_threads(prev, next);
164 }
166 struct thread* create_thread(char *name, void (*function)(void *), void *data)
167 {
168 struct thread *thread;
169 unsigned long flags;
170 /* Call architecture specific setup. */
171 thread = arch_create_thread(name, function, data);
172 /* Not runable, not exited, not sleeping */
173 thread->flags = 0;
174 thread->wakeup_time = 0LL;
175 set_runnable(thread);
176 local_irq_save(flags);
177 if(idle_thread != NULL) {
178 list_add_tail(&thread->thread_list, &idle_thread->thread_list);
179 } else if(function != idle_thread_fn)
180 {
181 printk("BUG: Not allowed to create thread before initialising scheduler.\n");
182 BUG();
183 }
184 local_irq_restore(flags);
185 return thread;
186 }
188 void exit_thread(void)
189 {
190 unsigned long flags;
191 struct thread *thread = current;
192 printk("Thread \"%s\" exited.\n", thread->name);
193 local_irq_save(flags);
194 /* Remove from the thread list */
195 list_del(&thread->thread_list);
196 clear_runnable(thread);
197 /* Put onto exited list */
198 list_add(&thread->thread_list, &exited_threads);
199 local_irq_restore(flags);
200 /* Schedule will free the resources */
201 schedule();
202 }
204 void block(struct thread *thread)
205 {
206 thread->wakeup_time = 0LL;
207 clear_runnable(thread);
208 }
210 void sleep(u32 millisecs)
211 {
212 struct thread *thread = get_current();
213 thread->wakeup_time = NOW() + MILLISECS(millisecs);
214 clear_runnable(thread);
215 schedule();
216 }
218 void wake(struct thread *thread)
219 {
220 thread->wakeup_time = 0LL;
221 set_runnable(thread);
222 }
224 void idle_thread_fn(void *unused)
225 {
226 s_time_t until;
227 unsigned long flags;
228 struct list_head *iterator;
229 struct thread *next, *thread;
230 for(;;)
231 {
232 schedule();
233 next = NULL;
234 local_irq_save(flags);
235 list_for_each(iterator, &idle_thread->thread_list)
236 {
237 thread = list_entry(iterator, struct thread, thread_list);
238 if(is_runnable(thread))
239 {
240 next = thread;
241 break;
242 }
243 }
244 if (!next) {
245 /* block until the next timeout expires, or for 10 secs, whichever comes first */
246 until = blocking_time();
247 block_domain(until);
248 }
249 local_irq_restore(flags);
250 wake_expired();
251 }
252 }
254 DECLARE_MUTEX(mutex);
256 void th_f1(void *data)
257 {
258 struct timeval tv1, tv2;
260 for(;;)
261 {
262 down(&mutex);
263 printk("Thread \"%s\" got semaphore, runnable %d\n", current->name, is_runnable(current));
264 schedule();
265 printk("Thread \"%s\" releases the semaphore\n", current->name);
266 up(&mutex);
269 gettimeofday(&tv1);
270 for(;;)
271 {
272 gettimeofday(&tv2);
273 if(tv2.tv_sec - tv1.tv_sec > 2) break;
274 }
277 schedule();
278 }
279 }
281 void th_f2(void *data)
282 {
283 for(;;)
284 {
285 printk("Thread OTHER executing, data 0x%lx\n", data);
286 schedule();
287 }
288 }
292 void init_sched(void)
293 {
294 printk("Initialising scheduler\n");
296 idle_thread = create_thread("Idle", idle_thread_fn, NULL);
297 INIT_LIST_HEAD(&idle_thread->thread_list);
298 }