include/sched.h

Go to the documentation of this file.
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

CPU reservation server Reference Manual, written by Jork Loeser  © 2004