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

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

unix.superglobalmegacorp.com

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