Main Page | Modules | Class List | File List | Class Members | File Members | Related Pages

sched.c

Go to the documentation of this file.
00001 /* $Id: sched.c,v 1.9 2004/04/27 08:15:54 aw11 Exp $ */
00002 /*****************************************************************************/
00011 /* (c) 2003 Technische Universitaet Dresden
00012  * This file is part of DROPS, which is distributed under the terms of the
00013  * GNU General Public License 2. Please see the COPYING file for details.
00014  */
00015 
00016 /* L4 */
00017 #include <l4/sys/syscalls.h>
00018 #include <l4/thread/thread.h>
00019 #include <l4/semaphore/semaphore.h>
00020 
00021 #include <l4/dde_linux/dde.h>
00022 
00023 /* Linux */
00024 #include <linux/sched.h>
00025 
00026 /* local */
00027 #include "internal.h"
00028 #include "__config.h"
00029 #include "fastcall.h"
00030 
00044 static inline int try_to_wake_up(struct task_struct *p, int synchronous)
00045 {
00046   p->state = TASK_RUNNING;
00047 
00048   /* unlock process' self_lock */
00049   l4semaphore_up(&p->dde_sem);
00050 
00051   return 1;
00052 }
00053 
00056 inline int FASTCALL(wake_up_process(struct task_struct *p))
00057 {
00058   return try_to_wake_up(p, 0);
00059 }
00060 
00062 static void process_timeout(unsigned long __data)
00063 {
00064   struct task_struct *p = (struct task_struct *) __data;
00065 
00066   wake_up_process(p);
00067 }
00068 
00071 signed long FASTCALL(schedule_timeout(signed long timeout))
00072 {
00073   struct timer_list timer;
00074   unsigned long expire;
00075 
00076   switch (timeout)
00077     {
00078     case MAX_SCHEDULE_TIMEOUT:
00079       /*
00080        * These two special cases are useful to be comfortable
00081        * in the caller. Nothing more. We could take
00082        * MAX_SCHEDULE_TIMEOUT from one of the negative value
00083        * but I' d like to return a valid offset (>=0) to allow
00084        * the caller to do everything it want with the retval.
00085        */
00086       schedule();
00087       goto out;
00088     default:
00089       /*
00090        * Another bit of PARANOID. Note that the retval will be
00091        * 0 since no piece of kernel is supposed to do a check
00092        * for a negative retval of schedule_timeout() (since it
00093        * should never happens anyway). You just have the printk()
00094        * that will tell you if something is gone wrong and where.
00095        */
00096       if (timeout < 0)
00097         {
00098           LOG_Error("schedule_timeout: wrong timeout "
00099                     "value %lx", timeout);
00100           current->state = TASK_RUNNING;
00101           goto out;
00102         }
00103     }
00104 
00105   expire = timeout + jiffies;
00106 
00107   init_timer(&timer);
00108   timer.expires = expire;
00109   timer.data = (unsigned long) current;
00110   timer.function = process_timeout;
00111 
00112   add_timer(&timer);
00113   schedule();
00114   del_timer_sync(&timer);
00115 
00116   timeout = expire - jiffies;
00117 
00118 out:
00119   return timeout < 0 ? 0 : timeout;
00120 }
00121 
00124 void schedule(void)
00125 {
00126 
00127   switch (current->state)
00128     {
00129     case TASK_RUNNING:
00130       /* release CPU on any way */
00131 #if SCHED_YIELD_OPT
00132       l4thread_usleep(SCHED_YIELD_TO);
00133 #else
00134       l4_yield();
00135 #endif
00136       break;
00137 
00138     case TASK_UNINTERRUPTIBLE:
00139     case TASK_INTERRUPTIBLE:
00140       /* lock yourself on current semaphore */
00141       l4semaphore_down(&current->dde_sem);
00142       break;
00143 
00144     default:
00145       Panic("current->state unknown (%ld)\n", current->state);
00146     }
00147 }
00148 
00150 static inline void __wake_up_common(wait_queue_head_t * q, unsigned int mode,
00151                                     int nr_exclusive, const int sync)
00152 {
00153   struct list_head *tmp, *head;
00154   struct task_struct *p;
00155 
00156   CHECK_MAGIC_WQHEAD(q);
00157   head = &q->task_list;
00158   WQ_CHECK_LIST_HEAD(head);
00159   tmp = head->next;
00160   while (tmp != head)
00161     {
00162       unsigned int state;
00163       wait_queue_t *curr = list_entry(tmp, wait_queue_t, task_list);
00164 
00165       tmp = tmp->next;
00166       CHECK_MAGIC(curr->__magic);
00167       p = curr->task;
00168       state = p->state;
00169       if (state & mode)
00170         {
00171           WQ_NOTE_WAKER(curr);
00172           if (try_to_wake_up(p, sync) && curr->flags && !--nr_exclusive)
00173             break;
00174         }
00175     }
00176 }
00177 
00180 void FASTCALL(__wake_up(wait_queue_head_t * q, unsigned int mode, int nr))
00181 {
00182   if (q)
00183     {
00184       unsigned long flags;
00185       wq_read_lock_irqsave(&q->lock, flags);
00186       __wake_up_common(q, mode, nr, 0);
00187       wq_read_unlock_irqrestore(&q->lock, flags);
00188     }
00189 }
00190 
00193 void FASTCALL(__wake_up_sync(wait_queue_head_t * q, unsigned int mode, int nr))
00194 {
00195   if (q)
00196     {
00197       unsigned long flags;
00198       wq_read_lock_irqsave(&q->lock, flags);
00199       __wake_up_common(q, mode, nr, 1);
00200       wq_read_unlock_irqrestore(&q->lock, flags);
00201     }
00202 }
00203 
00204 #define SLEEP_ON_VAR                         \
00205         unsigned long flags;                 \
00206         wait_queue_t wait;                   \
00207         init_waitqueue_entry(&wait, current);
00208 
00209 #define SLEEP_ON_HEAD                          \
00210         wq_write_lock_irqsave(&q->lock,flags); \
00211         __add_wait_queue(q, &wait);            \
00212         wq_write_unlock(&q->lock);
00213 
00214 #define SLEEP_ON_TAIL                              \
00215         wq_write_lock_irq(&q->lock);               \
00216         __remove_wait_queue(q, &wait);             \
00217         wq_write_unlock_irqrestore(&q->lock,flags);
00218 
00221 void FASTCALL(interruptible_sleep_on(wait_queue_head_t * q))
00222 {
00223   SLEEP_ON_VAR current->state = TASK_INTERRUPTIBLE;
00224 
00225   SLEEP_ON_HEAD schedule();
00226   SLEEP_ON_TAIL
00227 }
00228 
00231 long FASTCALL(interruptible_sleep_on_timeout(wait_queue_head_t * q, long timeout))
00232 {
00233   SLEEP_ON_VAR current->state = TASK_INTERRUPTIBLE;
00234 
00235   SLEEP_ON_HEAD timeout = schedule_timeout(timeout);
00236   SLEEP_ON_TAIL return timeout;
00237 }
00238 
00241 void FASTCALL(sleep_on(wait_queue_head_t * q))
00242 {
00243   SLEEP_ON_VAR current->state = TASK_UNINTERRUPTIBLE;
00244 
00245   SLEEP_ON_HEAD schedule();
00246   SLEEP_ON_TAIL
00247 }
00248 
00251 long FASTCALL(sleep_on_timeout(wait_queue_head_t * q, long timeout))
00252 {
00253   SLEEP_ON_VAR current->state = TASK_UNINTERRUPTIBLE;
00254 
00255   SLEEP_ON_HEAD timeout = schedule_timeout(timeout);
00256   SLEEP_ON_TAIL return timeout;
00257 }
00258 
00262 void daemonize(void) {
00263   LOGd(DEBUG_MSG, "dde: dummy daemonize() call");
00264 }

Linux DDE, written by Christian Helmuth  © 2003 Technische Universitaet Dresden