Annotation of Gnu-Mach/linux/dev/kernel/sched.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * Linux scheduling support.
                      3:  *
                      4:  * Copyright (C) 1996 The University of Utah and the Computer Systems
                      5:  * Laboratory at the University of Utah (CSL)
                      6:  *
                      7:  * This program is free software; you can redistribute it and/or modify
                      8:  * it under the terms of the GNU General Public License as published by
                      9:  * the Free Software Foundation; either version 2, or (at your option)
                     10:  * any later version.
                     11:  *
                     12:  * This program is distributed in the hope that it will be useful,
                     13:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     15:  * GNU General Public License for more details.
                     16:  *
                     17:  * You should have received a copy of the GNU General Public License
                     18:  * along with this program; if not, write to the Free Software
                     19:  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
                     20:  *
                     21:  *      Author: Shantanu Goel, University of Utah CSL
                     22:  */
                     23: 
                     24: /*
                     25:  *  linux/kernel/sched.c
                     26:  *
                     27:  *  Copyright (C) 1991, 1992  Linus Torvalds
                     28:  */
                     29: 
                     30: #include <sys/types.h>
                     31: #include <machine/spl.h>
                     32: 
                     33: #include <mach/boolean.h>
                     34: 
                     35: #include <kern/thread.h>
                     36: #include <kern/sched_prim.h>
1.1.1.2 ! root       37: #include <kern/printf.h>
        !            38: 
        !            39: #include <machine/machspl.h>
1.1       root       40: 
                     41: #define MACH_INCLUDE
                     42: #include <linux/sched.h>
                     43: #include <linux/timer.h>
                     44: #include <linux/fs.h>
                     45: #include <linux/blkdev.h>
                     46: #include <linux/interrupt.h>
1.1.1.2 ! root       47: #include <linux/dev/glue/glue.h>
1.1       root       48: 
                     49: #include <asm/system.h>
                     50: #include <asm/atomic.h>
                     51: 
                     52: int securelevel = 0;
                     53: 
                     54: static void timer_bh (void);
                     55: 
                     56: DECLARE_TASK_QUEUE (tq_timer);
                     57: DECLARE_TASK_QUEUE (tq_immediate);
                     58: DECLARE_TASK_QUEUE (tq_scheduler);
                     59: 
                     60: static struct wait_queue **auto_config_queue;
                     61: 
                     62: static inline void
                     63: handle_soft_intr (void)
                     64: {
                     65:   if (bh_active & bh_mask)
                     66:     {
                     67:       intr_count = 1;
                     68:       linux_soft_intr ();
                     69:       intr_count = 0;
                     70:     }
                     71: }
                     72: 
                     73: static void
                     74: tqueue_bh (void)
                     75: {
                     76:   run_task_queue(&tq_timer);
                     77: }
                     78: 
                     79: static void
                     80: immediate_bh (void)
                     81: {
                     82:   run_task_queue (&tq_immediate);
                     83: }
                     84: 
                     85: void
                     86: add_wait_queue (struct wait_queue **q, struct wait_queue *wait)
                     87: {
                     88:   unsigned long flags;
                     89: 
                     90:   if (! linux_auto_config)
                     91:     {
                     92:       save_flags (flags);
                     93:       cli ();
                     94:       assert_wait ((event_t) q, FALSE);
                     95:       restore_flags (flags);
                     96:       return;
                     97:     }
                     98: 
                     99:   if (auto_config_queue)
                    100:     printf ("add_wait_queue: queue not empty\n");
                    101:   auto_config_queue = q;
                    102: }
                    103: 
                    104: void
                    105: remove_wait_queue (struct wait_queue **q, struct wait_queue *wait)
                    106: {
                    107:   unsigned long flags;
                    108: 
                    109:   if (! linux_auto_config)
                    110:     {
                    111:       save_flags (flags);
                    112:       thread_wakeup ((event_t) q);
                    113:       restore_flags (flags);
                    114:       return;
                    115:     }
                    116: 
                    117:   auto_config_queue = NULL;
                    118: }
                    119: 
                    120: static inline int
                    121: waking_non_zero (struct semaphore *sem)
                    122: {
                    123:   int ret;
                    124:   unsigned long flags;
                    125: 
                    126:   get_buzz_lock (&sem->lock);
                    127:   save_flags (flags);
                    128:   cli ();
                    129: 
                    130:   if ((ret = (sem->waking > 0)))
                    131:     sem->waking--;
                    132: 
                    133:   restore_flags (flags);
                    134:   give_buzz_lock (&sem->lock);
                    135:   return ret;
                    136: }
                    137: 
                    138: void
                    139: __up (struct semaphore *sem)
                    140: {
                    141:   atomic_inc (&sem->waking);
                    142:   wake_up (&sem->wait);
                    143: }
                    144: 
                    145: int
                    146: __do_down (struct semaphore *sem, int task_state)
                    147: {
                    148:   unsigned long flags;
                    149:   int ret = 0;
                    150:   int s;
                    151:   
                    152:   if (!linux_auto_config)
                    153:     {
                    154:       save_flags (flags);
                    155:       s = splhigh ();
                    156:       for (;;)
                    157:        {
                    158:          if (waking_non_zero (sem))
                    159:            break;
                    160: 
                    161:          if (task_state == TASK_INTERRUPTIBLE && issig ())
                    162:            {
1.1.1.2 ! root      163:              ret = -EINTR;
1.1       root      164:              atomic_inc (&sem->count);
                    165:              break;
                    166:            }
                    167: 
                    168:          assert_wait ((event_t) &sem->wait,
                    169:                       task_state == TASK_INTERRUPTIBLE ? TRUE : FALSE);
                    170:          splx (s);
                    171:          schedule ();
                    172:          s = splhigh ();
                    173:        }
                    174:       splx (s);
                    175:       restore_flags (flags);
                    176:       return ret;
                    177:     }
                    178: 
                    179:   while (!waking_non_zero (sem))
                    180:     {
                    181:       if (task_state == TASK_INTERRUPTIBLE && issig ())
                    182:        {
1.1.1.2 ! root      183:          ret = -EINTR;
1.1       root      184:          atomic_inc (&sem->count);
                    185:          break;
                    186:        }
                    187:       schedule ();
                    188:     }
                    189: 
                    190:   return ret;
                    191: }
                    192: 
                    193: void
                    194: __down (struct semaphore *sem)
                    195: {
                    196:   __do_down(sem, TASK_UNINTERRUPTIBLE);
                    197: }
                    198: 
                    199: int
                    200: __down_interruptible (struct semaphore *sem)
                    201: {
                    202:   return __do_down (sem, TASK_INTERRUPTIBLE); 
                    203: }
                    204: 
                    205: void
                    206: __sleep_on (struct wait_queue **q, int state)
                    207: {
                    208:   unsigned long flags;
                    209: 
                    210:   if (!q)
                    211:     return;
                    212:   save_flags (flags);
                    213:   if (!linux_auto_config)
                    214:     {
                    215:       assert_wait ((event_t) q, state == TASK_INTERRUPTIBLE ? TRUE : FALSE);
                    216:       sti ();
                    217:       schedule ();
                    218:       restore_flags (flags);
                    219:       return;
                    220:     }
                    221:   
                    222:   add_wait_queue (q, NULL);
                    223:   sti ();
                    224:   while (auto_config_queue)
                    225:     schedule ();
                    226:   restore_flags (flags);
                    227: }
                    228: 
                    229: void
                    230: sleep_on (struct wait_queue **q)
                    231: {
                    232:   __sleep_on (q, TASK_UNINTERRUPTIBLE);
                    233: }
                    234: 
                    235: void
                    236: interruptible_sleep_on (struct wait_queue **q)
                    237: {
                    238:   __sleep_on (q, TASK_INTERRUPTIBLE);
                    239: }
                    240: 
                    241: void
                    242: wake_up (struct wait_queue **q)
                    243: {
                    244:   unsigned long flags;
                    245: 
                    246:   if (! linux_auto_config)
                    247:     {
                    248:       if (q != &wait_for_request)      /* ??? by OKUJI Yoshinori. */
                    249:        {
                    250:          save_flags (flags);
                    251:          thread_wakeup ((event_t) q);
                    252:          restore_flags (flags);
                    253:        }
                    254:       return;
                    255:     }
                    256: 
                    257:   if (auto_config_queue == q)
                    258:     auto_config_queue = NULL;
                    259: }
                    260: 
                    261: void
                    262: __wait_on_buffer (struct buffer_head *bh)
                    263: {
                    264:   unsigned long flags;
                    265: 
                    266:   save_flags (flags);
                    267:   if (! linux_auto_config)
                    268:     {
                    269:       while (1)
                    270:        {
                    271:          cli ();
                    272:          run_task_queue (&tq_disk);
                    273:          if (! buffer_locked (bh))
                    274:            break;
                    275:          bh->b_wait = (struct wait_queue *) 1;
                    276:          assert_wait ((event_t) bh, FALSE);
                    277:          sti ();
                    278:          schedule ();
                    279:        }
                    280:       restore_flags (flags);
                    281:       return;
                    282:     }
                    283: 
                    284:   sti ();
                    285:   while (buffer_locked (bh))
                    286:     {
                    287:       run_task_queue (&tq_disk);
                    288:       schedule ();
                    289:     }
                    290:   restore_flags (flags);
                    291: }
                    292: 
                    293: void
                    294: unlock_buffer (struct buffer_head *bh)
                    295: {
                    296:   unsigned long flags;
                    297: 
                    298:   save_flags (flags);
                    299:   cli ();
                    300:   clear_bit (BH_Lock, &bh->b_state);
                    301:   if (bh->b_wait && ! linux_auto_config)
                    302:     {
                    303:       bh->b_wait = NULL;
                    304:       thread_wakeup ((event_t) bh);
                    305:     }
                    306:   restore_flags (flags);
                    307: }
                    308: 
                    309: void
                    310: schedule (void)
                    311: {
                    312:   if (intr_count)
                    313:     printk ("Aiee: scheduling in interrupt %p\n",
                    314:            __builtin_return_address (0));
                    315:   
                    316:   handle_soft_intr ();
                    317:   run_task_queue (&tq_scheduler);
                    318: 
                    319:   if (!linux_auto_config)
                    320:     thread_block (0);
                    321: }
                    322: 
                    323: void
                    324: linux_sched_init (void)
                    325: {
                    326:   /*
                    327:    * Install software interrupt handlers.
                    328:    */
                    329:   init_bh (TIMER_BH, timer_bh);
                    330:   init_bh (TQUEUE_BH, tqueue_bh);
                    331:   init_bh (IMMEDIATE_BH, immediate_bh);
                    332: }
                    333: 
                    334: /*
                    335:  * Linux timers.
                    336:  *
                    337:  * Copyright (C) 1996 The University of Utah and the Computer Systems
                    338:  * Laboratory at the University of Utah (CSL)
                    339:  *
                    340:  * This program is free software; you can redistribute it and/or modify
                    341:  * it under the terms of the GNU General Public License as published by
                    342:  * the Free Software Foundation; either version 2, or (at your option)
                    343:  * any later version.
                    344:  *
                    345:  * This program is distributed in the hope that it will be useful,
                    346:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                    347:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                    348:  * GNU General Public License for more details.
                    349:  *
                    350:  * You should have received a copy of the GNU General Public License
                    351:  * along with this program; if not, write to the Free Software
                    352:  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
                    353:  *
                    354:  *      Author: Shantanu Goel, University of Utah CSL
                    355:  */
                    356: 
                    357: unsigned long volatile jiffies = 0;
                    358: 
                    359: /*
                    360:  * Mask of active timers.
                    361:  */
                    362: unsigned long timer_active = 0;
                    363: 
                    364: /*
                    365:  * List of timeout routines.
                    366:  */
                    367: struct timer_struct timer_table[32];
                    368: 
                    369: #define TVN_BITS 6
                    370: #define TVR_BITS 8
                    371: #define TVN_SIZE (1 << TVN_BITS)
                    372: #define TVR_SIZE (1 << TVR_BITS)
                    373: #define TVN_MASK (TVN_SIZE - 1)
                    374: #define TVR_MASK (TVR_SIZE - 1)
                    375: 
                    376: #define SLOW_BUT_DEBUGGING_TIMERS 0
                    377: 
                    378: struct timer_vec
                    379:   {
                    380:     int index;
                    381:     struct timer_list *vec[TVN_SIZE];
                    382:   };
                    383: 
                    384: struct timer_vec_root
                    385:   {
                    386:     int index;
                    387:     struct timer_list *vec[TVR_SIZE];
                    388:   };
                    389: 
                    390: static struct timer_vec tv5 =
                    391: {0};
                    392: static struct timer_vec tv4 =
                    393: {0};
                    394: static struct timer_vec tv3 =
                    395: {0};
                    396: static struct timer_vec tv2 =
                    397: {0};
                    398: static struct timer_vec_root tv1 =
                    399: {0};
                    400: 
                    401: static struct timer_vec *const tvecs[] =
                    402: {
                    403:   (struct timer_vec *) &tv1, &tv2, &tv3, &tv4, &tv5
                    404: };
                    405: 
                    406: #define NOOF_TVECS (sizeof(tvecs) / sizeof(tvecs[0]))
                    407: 
                    408: static unsigned long timer_jiffies = 0;
                    409: 
                    410: static inline void
                    411: insert_timer (struct timer_list *timer, struct timer_list **vec, int idx)
                    412: {
                    413:   if ((timer->next = vec[idx]))
                    414:     vec[idx]->prev = timer;
                    415:   vec[idx] = timer;
                    416:   timer->prev = (struct timer_list *) &vec[idx];
                    417: }
                    418: 
                    419: static inline void
                    420: internal_add_timer (struct timer_list *timer)
                    421: {
                    422:   /*
                    423:    * must be cli-ed when calling this
                    424:    */
                    425:   unsigned long expires = timer->expires;
                    426:   unsigned long idx = expires - timer_jiffies;
                    427: 
                    428:   if (idx < TVR_SIZE)
                    429:     {
                    430:       int i = expires & TVR_MASK;
                    431:       insert_timer (timer, tv1.vec, i);
                    432:     }
                    433:   else if (idx < 1 << (TVR_BITS + TVN_BITS))
                    434:     {
                    435:       int i = (expires >> TVR_BITS) & TVN_MASK;
                    436:       insert_timer (timer, tv2.vec, i);
                    437:     }
                    438:   else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS))
                    439:     {
                    440:       int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK;
                    441:       insert_timer (timer, tv3.vec, i);
                    442:     }
                    443:   else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS))
                    444:     {
                    445:       int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK;
                    446:       insert_timer (timer, tv4.vec, i);
                    447:     }
                    448:   else if (expires < timer_jiffies)
                    449:     {
                    450:       /* can happen if you add a timer with expires == jiffies,
                    451:        * or you set a timer to go off in the past
                    452:        */
                    453:       insert_timer (timer, tv1.vec, tv1.index);
                    454:     }
                    455:   else if (idx < 0xffffffffUL)
                    456:     {
                    457:       int i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
                    458:       insert_timer (timer, tv5.vec, i);
                    459:     }
                    460:   else
                    461:     {
                    462:       /* Can only get here on architectures with 64-bit jiffies */
                    463:       timer->next = timer->prev = timer;
                    464:     }
                    465: }
                    466: 
                    467: void
                    468: add_timer (struct timer_list *timer)
                    469: {
                    470:   unsigned long flags;
                    471: 
                    472:   save_flags (flags);
                    473:   cli ();
                    474: #if SLOW_BUT_DEBUGGING_TIMERS
                    475:   if (timer->next || timer->prev)
                    476:     {
                    477:       printk ("add_timer() called with non-zero list from %p\n",
                    478:              __builtin_return_address (0));
                    479:       goto out;
                    480:     }
                    481: #endif
                    482:   internal_add_timer (timer);
                    483: #if SLOW_BUT_DEBUGGING_TIMERS
                    484: out:
                    485: #endif
                    486:   restore_flags (flags);
                    487: }
                    488: 
                    489: static inline int
                    490: detach_timer (struct timer_list *timer)
                    491: {
                    492:   int ret = 0;
                    493:   struct timer_list *next, *prev;
                    494: 
                    495:   next = timer->next;
                    496:   prev = timer->prev;
                    497:   if (next)
                    498:     {
                    499:       next->prev = prev;
                    500:     }
                    501:   if (prev)
                    502:     {
                    503:       ret = 1;
                    504:       prev->next = next;
                    505:     }
                    506:   return ret;
                    507: }
                    508: 
                    509: int
                    510: del_timer (struct timer_list *timer)
                    511: {
                    512:   int ret;
                    513:   unsigned long flags;
                    514: 
                    515:   save_flags (flags);
                    516:   cli ();
                    517:   ret = detach_timer (timer);
                    518:   timer->next = timer->prev = 0;
                    519:   restore_flags (flags);
                    520:   return ret;
                    521: }
                    522: 
                    523: static inline void
                    524: run_old_timers (void)
                    525: {
                    526:   struct timer_struct *tp;
                    527:   unsigned long mask;
                    528: 
                    529:   for (mask = 1, tp = timer_table + 0; mask; tp++, mask += mask)
                    530:     {
                    531:       if (mask > timer_active)
                    532:        break;
                    533:       if (!(mask & timer_active))
                    534:        continue;
                    535:       if (tp->expires > jiffies)
                    536:        continue;
                    537:       timer_active &= ~mask;
                    538:       tp->fn ();
                    539:       sti ();
                    540:     }
                    541: }
                    542: 
                    543: static inline void
                    544: cascade_timers (struct timer_vec *tv)
                    545: {
                    546:   /* cascade all the timers from tv up one level */
                    547:   struct timer_list *timer;
                    548: 
                    549:   timer = tv->vec[tv->index];
                    550:   /*
                    551:    * We are removing _all_ timers from the list, so we don't  have to
                    552:    * detach them individually, just clear the list afterwards.
                    553:    */
                    554:   while (timer)
                    555:     {
                    556:       struct timer_list *tmp = timer;
                    557:       timer = timer->next;
                    558:       internal_add_timer (tmp);
                    559:     }
                    560:   tv->vec[tv->index] = NULL;
                    561:   tv->index = (tv->index + 1) & TVN_MASK;
                    562: }
                    563: 
                    564: static inline void
                    565: run_timer_list (void)
                    566: {
                    567:   cli ();
                    568:   while ((long) (jiffies - timer_jiffies) >= 0)
                    569:     {
                    570:       struct timer_list *timer;
                    571: 
                    572:       if (!tv1.index)
                    573:        {
                    574:          int n = 1;
                    575: 
                    576:          do
                    577:            {
                    578:              cascade_timers (tvecs[n]);
                    579:            }
                    580:          while (tvecs[n]->index == 1 && ++n < NOOF_TVECS);
                    581:        }
                    582:       while ((timer = tv1.vec[tv1.index]))
                    583:        {
                    584:          void (*fn) (unsigned long) = timer->function;
                    585:          unsigned long data = timer->data;
                    586: 
                    587:          detach_timer (timer);
                    588:          timer->next = timer->prev = NULL;
                    589:          sti ();
                    590:          fn (data);
                    591:          cli ();
                    592:        }
                    593:       ++timer_jiffies;
                    594:       tv1.index = (tv1.index + 1) & TVR_MASK;
                    595:     }
                    596:   sti ();
                    597: }
                    598: 
                    599: /*
                    600:  * Timer software interrupt handler.
                    601:  */
                    602: static void
                    603: timer_bh (void)
                    604: {
                    605:   run_old_timers ();
                    606:   run_timer_list ();
                    607: }
                    608: 
                    609: #if 0
                    610: int linux_timer_print = 0;
                    611: #endif
                    612: 
                    613: /*
                    614:  * Timer interrupt handler.
                    615:  */
                    616: void
                    617: linux_timer_intr (void)
                    618: {
                    619:   (*(unsigned long *) &jiffies)++;
                    620:   mark_bh (TIMER_BH);
                    621:   if (tq_timer)
                    622:     mark_bh (TQUEUE_BH);
                    623: #if 0
                    624:   if (linux_timer_print)
                    625:     printf ("linux_timer_intr: pic_mask[0] %x\n", pic_mask[0]);
                    626: #endif
                    627: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.