1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: edf.c,v $
29 * Revision 2.3 93/12/23 10:05:13 dbg
30 * Removed include of machine/machparam.h.
31 * [93/12/14 dbg]
32 *
33 * Revision 2.2 93/11/17 18:37:03 dbg
34 * Add per-policy scheduling parameters to thread and run queue.
35 * [93/05/10 dbg]
36 *
37 * Moved common operations to kern/run_queues.c.
38 * [93/04/10 dbg]
39 *
40 * Converted to per-policy run queue structure.
41 * [93/04/09 dbg]
42 *
43 * Merged into microkernel mainline.
44 *
45 * Changed period to time_spec_t.
46 * [92/09/06 savage]
47 * Added policy_init()
48 * [92/06/01 savage]
49 * Created
50 * [92/05/04 takuro]
51 *
52 */
53
54 /*
55 * Earliest-deadline-first scheduling policy. Threads
56 * are scheduled in the order of earliest deadline time
57 * first.
58 */
59 #include <mach_kdb.h>
60
61 #include <mach/boolean.h>
62 #include <mach/time_spec.h>
63 #include <mach/realtime_policy.h>
64
65 #include <kern/macro_help.h>
66 #include <kern/ast.h>
67 #include <kern/kalloc.h>
68 #include <kern/run_queues.h>
69 #include <kern/sched_policy.h>
70 #include <kern/processor.h>
71 #include <kern/thread.h>
72 #include <kern/rt_thread.h>
73 #include <kern/mach_timer.h>
74 #include <sched_policy/real_time.h>
75 #include <ipc/ipc_port.h>
76
77 /*
78 * Uses a single run queue, ordered by deadline time.
79 * No policy limits.
80 */
81 struct edf_run_queue {
82 struct run_queue rq; /* common structure */
83 queue_head_t edf_queue; /* queue */
84 };
85 typedef struct edf_run_queue * edf_run_queue_t;
86
87 #define edf_runq(rq) ((struct edf_run_queue *)(rq))
88 #define edf_count rq.rq_count
89
90 /*
91 * Choose thread.
92 */
93 thread_t
94 edf_thread_dequeue(
95 run_queue_t runq)
96 {
97 edf_run_queue_t rq = edf_runq(runq);
98 queue_entry_t elt;
99
100 assert(rq->edf_count > 0);
101 assert(!queue_empty(&rq->edf_queue));
102
103 dequeue_head_macro(&rq->edf_queue, elt);
104 rq->edf_count--;
105
106 current_processor()->first_quantum = TRUE; /* XXX */
107
108 return (thread_t) elt;
109 }
110
111 /*
112 * Put a thread onto a run queue in priority order.
113 * Return whether it can preempt the current thread.
114 */
115 boolean_t edf_thread_enqueue(
116 run_queue_t runq,
117 thread_t thread,
118 boolean_t may_preempt)
119 {
120 register edf_run_queue_t rq;
121 register thread_t next;
122 register queue_t q;
123 mach_timer_t timer1, timer2;
124
125 rq = edf_runq(runq);
126
127 q = &rq->edf_queue;
128 timer1 = thread->rt_deadline_timer;
129 if (timer1 == 0) {
130 enqueue_tail_macro(q, (queue_entry_t) thread);
131 rq->edf_count++;
132 return FALSE;
133 }
134 queue_iterate(q, next, thread_t, links) {
135 timer2 = next->rt_deadline_timer;
136 if (timer2 == 0)
137 break;
138 if (time_spec_leq(timer1->tm_expire_time,
139 timer2->tm_expire_time))
140 break;
141 }
142 enqueue_tail_macro((queue_t) next, (queue_entry_t) thread);
143 rq->edf_count++;
144
145 if (!may_preempt)
146 return FALSE;
147
148 timer2 = current_thread()->rt_deadline_timer;
149 if (timer2 == 0)
150 return TRUE;
151 return !time_spec_leq(timer2->tm_expire_time, timer1->tm_expire_time);
152 }
153
154 /*
155 * Remove a thread from the run queue.
156 */
157 void edf_thread_remqueue(
158 run_queue_t runq,
159 thread_t thread)
160 {
161 edf_run_queue_t rq = edf_runq(runq);
162
163 remqueue(&rq->edf_queue, (queue_entry_t) thread);
164 rq->edf_count--;
165 }
166
167 boolean_t edf_csw_needed(
168 run_queue_t runq,
169 thread_t thread)
170 {
171 edf_run_queue_t rq = edf_runq(runq);
172 thread_t th;
173 mach_timer_t timer1, timer2;
174
175 th = (thread_t) queue_first(&rq->edf_queue);
176 timer1 = th->rt_deadline_timer;
177 timer2 = thread->rt_deadline_timer;
178
179 if (timer1 == 0)
180 return FALSE;
181 if (timer2 == 0)
182 return TRUE;
183 return time_spec_leq(timer1->tm_expire_time, timer2->tm_expire_time);
184 }
185
186 extern struct sched_policy edf_sched_policy; /* forward */
187
188 run_queue_t
189 edf_run_queue_alloc(void)
190 {
191 edf_run_queue_t rq;
192
193 rq = (edf_run_queue_t) kalloc(sizeof(struct edf_run_queue));
194 run_queue_init(&rq->rq, &edf_sched_policy);
195
196 queue_init(&rq->edf_queue);
197
198 return &rq->rq;
199 }
200
201 void
202 edf_run_queue_free(
203 run_queue_t runq)
204 {
205 kfree((vm_offset_t) runq, sizeof(struct edf_run_queue));
206 }
207
208 #if MACH_KDB
209 #include <ddb/db_output.h>
210 void edf_thread_db_print(
211 thread_t thread)
212 {
213 db_printf("EDF ");
214 }
215 #endif
216
217 /*
218 * Statically allocated policy structure.
219 */
220 struct sched_policy edf_sched_policy = {
221 {
222 /* sched_ops */
223 edf_thread_dequeue,
224 edf_thread_enqueue,
225 edf_thread_remqueue,
226
227 edf_csw_needed,
228 ast_check,
229 0, /* no update_priority */
230
231 edf_run_queue_alloc,
232 edf_run_queue_free,
233
234 rt_runq_set_limit,
235 rt_runq_get_limit,
236 rt_thread_set_limit,
237 rt_thread_set_param,
238 rt_thread_get_param,
239 rt_task_set_param,
240 rt_task_get_param,
241
242 #if MACH_KDB
243 edf_thread_db_print
244 #endif
245
246 },
247 POLICY_EARLIEST_DEADLINE_FIRST,
248 "earliest deadline first"
249 };
250
Cache object: 768e041ac30674ab4a56cbac77154f34
|