00001 /*! 00002 * \file cpu_reserve/include/sched.h 00003 * \brief CPU reservation prototypes 00004 * 00005 * \date 09/06/2004 00006 * \author Jork Loeser <jork.loeser@inf.tu-dresden.de> 00007 * 00008 */ 00009 /* (c) 2004 Technische Universitaet Dresden 00010 * This file is part of DROPS, which is distributed under the terms of the 00011 * GNU General Public License 2. Please see the COPYING file for details. 00012 */ 00013 #ifndef __CPU_RESERVE_INCLUDE_SCHED_H_ 00014 #define __CPU_RESERVE_INCLUDE_SCHED_H_ 00015 #include <l4/sys/types.h> 00016 #include <l4/sys/compiler.h> 00017 00018 EXTERN_C_BEGIN 00019 00020 #define l4cpu_reserve_name "cpu_res" 00021 00022 /*!\brief Make a reservation 00023 * \ingroup api 00024 * 00025 * \param thread thread to make a reservation for 00026 * \param name a name for the reservation 00027 * \param prio priority of the reservation 00028 * \param period period of the thread 00029 * \param wcet - in: WCET of the thread per period 00030 * - out: reserved amount of CPU in case of success 00031 * \param deadline deadline within the period. Specify 0 for an optional 00032 * reservation. 00033 * \param id will be filled with the id of the timeslice. 00034 * \retval 0 OK 00035 * \retval !0 Error 00036 * 00037 * This function makes a reservation for the given thread and adds the 00038 * needed timeslices at the kernel. Open success, it is ensured that 00039 * the thread will receive the requested amount of CPU within the 00040 * given deadline. However, a general assumption is that no other, 00041 * higher prioritized threads exist in the system that are not 00042 * registered at the CPU reservation server. Use the MCP mechanism of 00043 * the kernel to ensure this. 00044 * 00045 * To add multiple timeslices for a thread, call this function 00046 * multiple times. This function sets the period of the thread when 00047 * adding the first timeslice to thread. So there is no additional 00048 * set_period() call as with the raw kernel interface. 00049 */ 00050 extern int l4cpu_reserve_add(l4_threadid_t thread, 00051 const char*name, 00052 int prio, 00053 int period, 00054 int *wcet, 00055 int deadline, 00056 int *id); 00057 00058 /*!\brief Add delayed preemption reservation for a thread, internal function 00059 * \ingroup dp 00060 * 00061 * \param thread thread to add delayed preemption (DP) to 00062 * \param id id of the timeslice to add DP to 00063 * \param prio sensitive priority of DP, once it is activated. 00064 * (Ignored and assumed to be 255, see note.) 00065 * \param delay max. duration of DP. Will be rounded up according to 00066 * kernel capabilities and returned. 00067 * 00068 * \retval 0 OK 00069 * \retval !0 Error 00070 * 00071 * This function adds a delayed preemption to the specified timeslice, 00072 * which must exist already. The non real-time timeslice with id=0 00073 * always exists, the others are created by calling 00074 * l4cpu_reserve_add(). The actual duration of the delayed preemption 00075 * is returned in *delay. The name returned by the diagnostic function 00076 * l4cpu_reserve_scheds_get() is set to the name of the timeslice, 00077 * suffixed by ".dp". 00078 * 00079 * The delayed preemption reservation will be removed when the 00080 * reservations for the thread are removed. 00081 * 00082 * \note As of today (Oct 2004), the kernel has no support for DP, thus 00083 * a user-level emulation is needed. CLI/STI comes into mind, which 00084 * of course ignores the sensitive priority and prevents preemption 00085 * entirely as long as DP is activated. 00086 */ 00087 extern int l4cpu_reserve_delayed_preempt(l4_threadid_t thread, 00088 int id, 00089 int prio, 00090 int *delay); 00091 00092 /*!\brief Change the reservation of a thread 00093 * \ingroup api 00094 * 00095 * \param thread thread to change the reservation for 00096 * \param id id of the timeslice to change 00097 * \param new_prio new priority, -1 does not change 00098 * \param new_wcet - in: new wcet, -1 does not change 00099 * - out: reserved amount of CPU if successfully modified 00100 * \param deadline new deadline, -1 does not change. 00101 * \retval 0 OK 00102 * \retval !0 Error 00103 * 00104 * This function changes a reservation for the given thread and 00105 * timeslice. Checks are performed to ensure that all existing 00106 * reservations can be met. 00107 */ 00108 extern int l4cpu_reserve_change(l4_threadid_t thread, 00109 int id, 00110 int new_prio, 00111 int *new_wcet, 00112 int new_deadline); 00113 00114 /*!\brief Remove the reservations of a thread 00115 * \ingroup api 00116 * 00117 * \param thread thread to remove all reservations from 00118 * \retval 0 OK 00119 * \retval !0 Error 00120 * 00121 * This function removes all reservations for the given thread. 00122 */ 00123 extern int l4cpu_reserve_delete_thread(l4_threadid_t thread); 00124 00125 /*!\brief Remove the reservations of a task 00126 * \ingroup api 00127 * 00128 * \param task task to remove all reservations from 00129 * \retval 0 OK 00130 * \retval !0 Error 00131 * 00132 * This function removes all reservations for all threads of the given 00133 * task. 00134 */ 00135 extern int l4cpu_reserve_delete_task(l4_threadid_t task); 00136 00137 /*!\brief Start strictly periodic execution 00138 * \ingroup api 00139 * 00140 * \param dest thread that starts periodic execution 00141 * \param clock absolute time to start. 00142 * \retval 0 OK 00143 * \retval !0 Error 00144 * 00145 * Call this function to start the periodic execution of another thread after 00146 * setting up the reservations using l4cpu_reserve_add(). 00147 * 00148 * For details, see l4_rt_begin_strictly_periodic() in the l4sys package. 00149 * 00150 * \note Starting RT-mode of the own thread with a timeout is unsafe. As 00151 * the thread has no reservation, a deadline for activating this call 00152 * at the kernel can not be guaranteed. Starting the own thread requires 00153 * the NP bit to be set when calling the scheduler to activate RT mode 00154 * to ensure the thread is ready to receive its first NP-IPC at the 00155 * right time. If, however, the RT-mode activation is triggered after 00156 * the timeout, the operation fails. But, the thread is waiting for 00157 * the NP-IPC and won't receive the answer indicating the error. 00158 */ 00159 extern int l4cpu_reserve_begin_strictly_periodic(l4_threadid_t thread, 00160 l4_kernel_clock_t clock); 00161 00162 /*!\brief Start strictly periodic execution of own thread ASAP 00163 * \ingroup api 00164 * 00165 * \param me (cached) own ID. L4_INVALID_ID if you don't know. 00166 * \retval 0 OK 00167 * \retval !0 Error 00168 * 00169 * Call this function to start the periodic execution for the calling 00170 * thread after setting up the reservations using l4cpu_reserve_add(). 00171 * The initial next_period() call is automatically executed, and periodic 00172 * mode is activated as sonn as possible. 00173 * 00174 * For details, see l4_rt_begin_strictly_periodic() in the l4sys package. 00175 */ 00176 extern int l4cpu_reserve_begin_strictly_periodic_self(l4_threadid_t me); 00177 00178 /*!\brief Deprecated version with timeout, which is unsafe */ 00179 extern int l4cpu_reserve_begin_strictly_periodic_self_deprecated( 00180 l4_threadid_t me, l4_kernel_clock_t clock); 00181 00182 /*!\brief Start periodic execution with minimal interrelease times 00183 * \ingroup api 00184 * 00185 * \param dest thread that starts periodic execution 00186 * \param clock absolute time to start. 00187 * \retval 0 OK 00188 * \retval !0 Error 00189 * 00190 * Call this function to start the periodic execution after setting up 00191 * the reservations using l4cpu_reserve_add(). 00192 * 00193 * For details, see l4_rt_begin_minimal_periodic() in the l4sys package. 00194 */ 00195 extern int l4cpu_reserve_begin_minimal_periodic(l4_threadid_t thread, 00196 l4_kernel_clock_t clock); 00197 00198 /*!\brief Start periodic execution with minimal interrelease times, own thread 00199 * \ingroup api 00200 * 00201 * \param me (cached) own ID. L4_INVALID_ID if you don't know. 00202 * \param clock absolute time to start. 0: ASAP. 00203 * \retval 0 OK 00204 * \retval !0 Error 00205 * 00206 * Call this function to start the periodic execution for the calling 00207 * thread after setting up the reservations using l4cpu_reserve_add(). 00208 * The initial next_period() call is automatically executed. 00209 * 00210 * For details, see l4_rt_begin_minimal_periodic() in the l4sys package. 00211 * For notes, see l4cpu_reserve_begin_strictly_periodic_self(). 00212 */ 00213 extern int l4cpu_reserve_begin_minimal_periodic_self(l4_threadid_t thread); 00214 00215 extern int l4cpu_reserve_begin_minimal_periodic_self_deprecated( 00216 l4_threadid_t thread, l4_kernel_clock_t clock); 00217 00218 /*!\brief Stop periodic execution 00219 * \ingroup api 00220 * 00221 * \param thread thread that stops periodic execution 00222 * \retval 0 OK 00223 * \retval !0 Error 00224 * 00225 * This function aborts the periodic execution of the given thread. 00226 * 00227 * For details, see l4_rt_end_periodic() in the l4sys package. 00228 */ 00229 extern int l4cpu_reserve_end_periodic(l4_threadid_t thread); 00230 00231 /*!\brief Watch exception IPCs for the given thread 00232 * \ingroup api 00233 * 00234 * \param thread thread to be watched 00235 * \param addr will contain ptr to overflow-field after return. 00236 * if 0, no address will be provided in return. 00237 * 00238 * The function starts watching for exception IPCs (deadline miss or 00239 * timeslice expired) at cpu_reserved. If #addr is not 0 on calling, 00240 * the returned array contains an unsigned for each timeslice id, which 00241 * is incremented on each timeslice expired IPC. 00242 */ 00243 extern int l4cpu_reserve_watch(l4_threadid_t thread, 00244 unsigned **addr); 00245 00246 /*!\brief Return the number of reservations made. 00247 * \ingroup api 00248 * 00249 * Use this function for debugging/monitoring purposes. 00250 */ 00251 extern int l4cpu_reserve_scheds_count(void); 00252 00253 /*!\brief Return a given reservation. 00254 * \ingroup api 00255 * 00256 * \param idx reservation index, 0<=idx<=l4cpu_reserve_scheds_count() 00257 * \param name will set to the name, free() it after use 00258 * \param thread thread-id of reservation 00259 * \param creator thread-id of the creator of the reservation 00260 * \param id id of the reservation 00261 * \param prio priority of the reservation 00262 * \param period period of the reservation 00263 * \param wcet WCET of the reservation 00264 * \param deadline deadline of the reservation, 0 means optional 00265 * 00266 * Use this function for debugging/monitoring purposes. 00267 */ 00268 extern int l4cpu_reserve_scheds_get(int idx, 00269 char **name, 00270 l4_threadid_t *thread, 00271 l4_threadid_t *creator, 00272 int *id, 00273 int *prio, 00274 int *period, 00275 int *wcet, 00276 int *deadline); 00277 00278 00279 /*!\brief Return response time of given thread 00280 * 00281 * \param thread thread id 00282 * \param id timeslice id 00283 * 00284 * \retval >=0 worst-case response time according to given 00285 * reservations 00286 * \retval -L4_ETIME response-time larger than period (or deadline, if 00287 * set) of the thread 00288 * \retval -L4_EINVAL thread/timeslice not registered. 00289 * 00290 */ 00291 extern int l4cpu_reserve_time_demand(l4_threadid_t thread, 00292 int id); 00293 00294 00295 /*!\brief Delayed Preemption: Reserve a duration for the whole task 00296 * \ingroup dp 00297 * 00298 * \param duration time (microseconds) 00299 * \retval duration contains the actually reserved time. 00300 * \retval 0 OK 00301 * \retval !0 Error. 00302 * 00303 * This function reserves a non-preemptible duration at the kernel, for 00304 * all existing and future threads of the calling task. 00305 * 00306 * \note The task-abstraction is easy to use from client applications, 00307 * as nothing has to be done on thread creation. It is easy to 00308 * implement with the current scheme too. It is also correct in the 00309 * sense of reservation and scheduling analysis, as long as the 00310 * priority of the thread reserving the delayed preemption is _low_ 00311 * enough. Keep in mind that only one blocking may happen at a time, 00312 * and therefore the maximum blocking time of higher-prioritized 00313 * threads is determined by the maximum the DP times of all 00314 * lower-prioritized threads. 00315 * 00316 * \note With future kernel releases, that might include real kernel 00317 * support for DP, the task abstraction might be hard to implement, 00318 * and support for DP must be programmed more explicitely. Think of 00319 * interrupt threads that are created by DDE internally. 00320 */ 00321 extern int l4cpu_dp_reserve_task(int *duration); 00322 00323 /*!\brief Delayed preemption: Cancel a reservation 00324 * \ingroup dp 00325 * 00326 * \retval 0 OK 00327 * \retval !0 Error. 00328 * 00329 * \note Currently unimplemented. 00330 */ 00331 extern int l4cpu_dp_remove(void); 00332 00333 extern void*l4cpu_dp_pc; 00334 /*!\brief Return if DP is currently running. */ 00335 extern int l4cpu_dp_active(void); 00336 00337 /*!\brief Callback for start of DP section 00338 * 00339 * This function is called if an delayed preemption actually starts. 00340 */ 00341 extern void l4cpu_dp_start_callback(void) __attribute__((weak)); 00342 00343 /*!\brief Delayed preemption: Start a delayed preemption 00344 * \ingroup dp 00345 * 00346 * After making a dp reservation with l4cpu_dp_reserve_task(), a 00347 * thread can start an uninterruptible execution. Calls to this function 00348 * may be nested, and the last call to l4cpu_dp_end() actually leaves the 00349 * uninterruptible section. 00350 * 00351 * Nesting calls from different threads will be detected and interpreted 00352 * as an error. Kernel debugger is entered. 00353 * 00354 * \note Due to the currently missing support in the kernel, this 00355 * call is implemented as a cli(), requiring cooperation from the 00356 * calling thread. 00357 * 00358 * \retval 0 OK 00359 * \retval !0 Error, e.g. nesting calls from different threads. 00360 * 00361 * \pre l4_tsc_init() must have been called successfully. 00362 */ 00363 extern int l4cpu_dp_begin(void); 00364 00365 /*!\brief Callback for end of DP section 00366 * 00367 * This function is called if an delayed preemption actually ends, this is 00368 * when all nested start calls have their stop calls. 00369 * 00370 * \param diff the time the delayed preemption was active 00371 * \param eip the eip that started the delayed preemption 00372 */ 00373 extern void l4cpu_dp_stop_callback(unsigned diff, void*eip) 00374 __attribute__((weak)); 00375 00376 /*!\brief Delayed preemption: End a delayed preemption 00377 * \ingroup dp 00378 * 00379 * When calling this function, and un-nesting all previous calls to 00380 * l4cpu_dp_begin(), the thread may be preempted by the kernel again. 00381 * 00382 * \note In its current implementation, time measurement is used to verify 00383 * the actual blocking time. A warning is printed if the blocking 00384 * was too long. 00385 * 00386 * \retval 0 OK. probably someone still in the preemption 00387 * \retval >0 OK, DP ended. Time left (in usecs). 00388 * \retval -L4_ETIME blocking was too long 00389 * \retval -L4_EINVAL DP was not running 00390 * 00391 * \pre l4_tsc_init() must have been called successfully. 00392 */ 00393 extern int l4cpu_dp_end(void); 00394 00395 /*!\brief Get the reservations at the reservation server and dump them 00396 */ 00397 extern int l4cpu_reserve_dump(void); 00398 00399 int l4cpu_reserve_wait_periodic(l4_threadid_t parent); 00400 int l4cpu_reserve_wait_periodic_ready(int mode, 00401 l4_threadid_t child, 00402 l4_kernel_clock_t clock); 00403 00404 EXTERN_C_END 00405 #endif