1 /*
2 * Mach Operating System
3 * Copyright (c) 1993 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: real_time.c,v $
29 * Revision 2.2 93/11/17 18:37:51 dbg
30 * policy_param_realtime always has start time.
31 * [93/06/21 dbg]
32 *
33 * Created.
34 * [93/05/12 dbg]
35 *
36 */
37
38 /*
39 * Common routines for real-time scheduling policies.
40 */
41
42 #include <kern/clock.h>
43 #include <kern/mach_timer.h>
44 #include <kern/run_queues.h>
45 #include <kern/thread.h>
46 #include <kern/rt_thread.h>
47
48 #include <ipc/ipc_port.h>
49
50 #include <sched_policy/real_time.h>
51
52 #include <machine/machspl.h>
53
54 /*
55 * Set the scheduling parameters for a thread. If they
56 * are not supplied, the thread`s current parameters
57 * are used if 'new_policy' is FALSE; otherwise, per-
58 * policy defaults are used. If 'new_policy' is FALSE,
59 * limit values are taken from the thread`s processor
60 * set; otherwise, the thread`s current limit values
61 * are used.
62 *
63 * For EDF, there are no limit values. Data sets the
64 * thread`s period and deadline timers.
65 */
66 kern_return_t
67 rt_thread_set_param(
68 thread_t thread,
69 policy_param_t param,
70 natural_t count,
71 boolean_t new_policy,
72 boolean_t check_limits)
73 {
74 if (count > 0) {
75 struct policy_param_realtime *pd;
76 time_spec_t period, deadline, start_time;
77 boolean_t periodic;
78 mach_timer_t wakeup_timer, deadline_timer;
79
80 /*
81 * Data supplied. Set period and deadline, and
82 * change timers to match.
83 */
84 if (count < POLICY_PARAM_REALTIME_COUNT)
85 return KERN_INVALID_VALUE;
86
87 pd = (struct policy_param_realtime *)param;
88 period = pd->period;
89 deadline = pd->deadline;
90
91 if (!time_spec_valid(period) || !time_spec_valid(deadline) ||
92 !time_spec_valid(pd->start_time))
93 {
94 return KERN_INVALID_VALUE;
95 }
96
97 /*
98 * Treat zero period or deadline as infinite
99 */
100 if (!time_spec_nonzero(period)) {
101 time_spec_set_infinite(period);
102 }
103 if (!time_spec_nonzero(deadline)) {
104 time_spec_set_infinite(deadline);
105 }
106
107 periodic = !time_spec_infinite(period);
108
109 /*
110 * Get period and deadline timers
111 */
112 wakeup_timer = thread->rt_wakeup_timer;
113 deadline_timer = thread->rt_deadline_timer;
114
115 switch (pd->start_when) {
116 case START_TIME_ABSOLUTE:
117 start_time = pd->start_time;
118 if (!time_spec_nonzero(start_time)) {
119 /*
120 * No start time specified - error
121 */
122 return KERN_INVALID_ARGUMENT;
123 }
124 break;
125
126 case START_TIME_RELATIVE:
127 if (wakeup_timer != 0) {
128 clock_read(start_time,
129 wakeup_timer->tm_clock);
130 time_spec_add(start_time, pd->start_time);
131 }
132 else {
133 return KERN_INVALID_ARGUMENT;
134 /* relative to what? */
135 }
136 break;
137
138 case START_TIME_NO_CHANGE:
139 if (wakeup_timer != 0 &&
140 timer_start_time(wakeup_timer, &start_time))
141 {
142 /*
143 * Current starting time is the
144 * start of the current period:
145 * the expiration time for the
146 * periodic timer minus the
147 * period of the timer.
148 */
149 }
150 else {
151 return KERN_INVALID_ARGUMENT;
152 /* no period */
153 }
154 break;
155
156 default:
157 return KERN_INVALID_ARGUMENT;
158 }
159
160 /*
161 * If there is no periodic timer, we cannot
162 * reset the timers. Assume that the caller
163 * has done so.
164 */
165 if (wakeup_timer != 0) {
166 /*
167 * If the new period is infinite, cancel the periodic
168 * timer. Otherwise, reset it to the new period.
169 */
170 if (periodic) {
171 time_spec_t new_wakeup_time;
172
173 new_wakeup_time = start_time;
174 time_spec_add(new_wakeup_time, period);
175
176 (void) timer_rearm(wakeup_timer,
177 new_wakeup_time,
178 period,
179 TIMER_ABSOLUTE | TIMER_PERIODIC);
180 }
181 else {
182 (void) timer_cancel(wakeup_timer, 0);
183 }
184 }
185
186 if (deadline_timer != 0) {
187 /*
188 * If the new deadline is infinite, cancel the
189 * deadline timer. Otherwise, calculate the
190 * new deadline, and set the timer.
191 *
192 * The new deadline_time is start_time +
193 * new_deadline.
194 */
195 if (!time_spec_infinite(deadline)) {
196 time_spec_t new_deadline_time;
197
198 new_deadline_time = start_time;
199 time_spec_add(new_deadline_time, deadline);
200
201 (void) timer_rearm(deadline_timer,
202 new_deadline_time,
203 period,
204 TIMER_ABSOLUTE |
205 ((periodic) ? TIMER_PERIODIC
206 : 0)
207 );
208 }
209 else {
210 (void) timer_cancel(deadline_timer, 0);
211 }
212 }
213
214 rt_sched(thread)->period = period;
215 rt_sched(thread)->deadline = deadline;
216 }
217 else {
218 if (new_policy) {
219 /*
220 * Thread is not already running this policy:
221 * use default values.
222 *
223 * Defaults are 'infinite' period and deadline.
224 */
225 rt_sched(thread)->start_time.seconds = 0;
226 rt_sched(thread)->start_time.nanoseconds = 0;
227 time_spec_set_infinite(rt_sched(thread)->period);
228 time_spec_set_infinite(rt_sched(thread)->deadline);
229 }
230 /* otherwise no change */
231 }
232
233 return KERN_SUCCESS;
234 }
235
236 /*
237 * Get the scheduling parameters and limits for a thread.
238 */
239 kern_return_t
240 rt_thread_get_param(
241 thread_t thread,
242 policy_param_t param,
243 natural_t *count)
244 {
245 mach_timer_t wakeup_timer;
246
247 struct policy_param_realtime *pd;
248
249 if (*count < POLICY_PARAM_REALTIME_COUNT)
250 return KERN_INVALID_VALUE;
251
252 pd = (struct policy_param_realtime *)param;
253
254 pd->period = rt_sched(thread)->period;
255 pd->deadline = rt_sched(thread)->deadline;
256
257 wakeup_timer = thread->rt_wakeup_timer;
258 if (wakeup_timer != 0 &&
259 timer_start_time(wakeup_timer, &pd->start_time))
260 {
261 /*
262 * The start of the current period is
263 * the expiration time for the periodic
264 * timer minus the period of the timer.
265 */
266 }
267 else {
268 /*
269 * Can`t get start time.
270 */
271 pd->start_time.seconds = 0;
272 pd->start_time.nanoseconds = 0;
273 }
274 pd->start_when = START_TIME_ABSOLUTE;
275
276 *count = POLICY_PARAM_REALTIME_COUNT;
277 return KERN_SUCCESS;
278 }
279
Cache object: 1b9bb6c5d09786547594dbdf5a4fd034
|