|
|
1.1 ! root 1: /* ! 2: * Linux timers. ! 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 <linux/sched.h> ! 31: #include <linux/timer.h> ! 32: #include <linux/interrupt.h> ! 33: #include <asm/system.h> ! 34: ! 35: unsigned long volatile jiffies = 0; ! 36: ! 37: /* ! 38: * Mask of active timers. ! 39: */ ! 40: unsigned long timer_active = 0; ! 41: ! 42: /* ! 43: * List of timeout routines. ! 44: */ ! 45: struct timer_struct timer_table[32]; ! 46: ! 47: /* ! 48: * The head for the timer-list has a "expires" field of MAX_UINT, ! 49: * and the sorting routine counts on this.. ! 50: */ ! 51: static struct timer_list timer_head = ! 52: { ! 53: &timer_head, &timer_head, ~0, 0, NULL ! 54: }; ! 55: ! 56: #define SLOW_BUT_DEBUGGING_TIMERS 0 ! 57: ! 58: void ! 59: add_timer(struct timer_list *timer) ! 60: { ! 61: unsigned long flags; ! 62: struct timer_list *p; ! 63: ! 64: #if SLOW_BUT_DEBUGGING_TIMERS ! 65: if (timer->next || timer->prev) { ! 66: printk("add_timer() called with non-zero list from %p\n", ! 67: __builtin_return_address(0)); ! 68: return; ! 69: } ! 70: #endif ! 71: p = &timer_head; ! 72: save_flags(flags); ! 73: cli(); ! 74: do { ! 75: p = p->next; ! 76: } while (timer->expires > p->expires); ! 77: timer->next = p; ! 78: timer->prev = p->prev; ! 79: p->prev = timer; ! 80: timer->prev->next = timer; ! 81: restore_flags(flags); ! 82: } ! 83: ! 84: int ! 85: del_timer(struct timer_list *timer) ! 86: { ! 87: unsigned long flags; ! 88: #if SLOW_BUT_DEBUGGING_TIMERS ! 89: struct timer_list * p; ! 90: ! 91: p = &timer_head; ! 92: save_flags(flags); ! 93: cli(); ! 94: while ((p = p->next) != &timer_head) { ! 95: if (p == timer) { ! 96: timer->next->prev = timer->prev; ! 97: timer->prev->next = timer->next; ! 98: timer->next = timer->prev = NULL; ! 99: restore_flags(flags); ! 100: return 1; ! 101: } ! 102: } ! 103: if (timer->next || timer->prev) ! 104: printk("del_timer() called from %p with timer not initialized\n", ! 105: __builtin_return_address(0)); ! 106: restore_flags(flags); ! 107: return 0; ! 108: #else ! 109: struct timer_list * next; ! 110: int ret = 0; ! 111: save_flags(flags); ! 112: cli(); ! 113: if ((next = timer->next) != NULL) { ! 114: (next->prev = timer->prev)->next = next; ! 115: timer->next = timer->prev = NULL; ! 116: ret = 1; ! 117: } ! 118: restore_flags(flags); ! 119: return ret; ! 120: #endif ! 121: } ! 122: ! 123: /* ! 124: * Timer software interrupt handler. ! 125: */ ! 126: void ! 127: timer_bh() ! 128: { ! 129: unsigned long mask; ! 130: struct timer_struct *tp; ! 131: struct timer_list * timer; ! 132: ! 133: cli(); ! 134: while ((timer = timer_head.next) != &timer_head ! 135: && timer->expires <= jiffies) { ! 136: void (*fn)(unsigned long) = timer->function; ! 137: unsigned long data = timer->data; ! 138: ! 139: timer->next->prev = timer->prev; ! 140: timer->prev->next = timer->next; ! 141: timer->next = timer->prev = NULL; ! 142: sti(); ! 143: fn(data); ! 144: cli(); ! 145: } ! 146: sti(); ! 147: ! 148: for (mask = 1, tp = timer_table; mask; tp++, mask <<= 1) { ! 149: if (mask > timer_active) ! 150: break; ! 151: if ((mask & timer_active) ! 152: && tp->expires > jiffies) { ! 153: timer_active &= ~mask; ! 154: (*tp->fn)(); ! 155: sti(); ! 156: } ! 157: } ! 158: } ! 159: ! 160: int linux_timer_print = 0; ! 161: ! 162: /* ! 163: * Timer interrupt handler. ! 164: */ ! 165: void ! 166: linux_timer_intr() ! 167: { ! 168: unsigned long mask; ! 169: struct timer_struct *tp; ! 170: extern int pic_mask[]; ! 171: ! 172: jiffies++; ! 173: ! 174: for (mask = 1, tp = timer_table; mask; tp++, mask += mask) { ! 175: if (mask > timer_active) ! 176: break; ! 177: if (!(mask & timer_active)) ! 178: continue; ! 179: if (tp->expires > jiffies) ! 180: continue; ! 181: mark_bh(TIMER_BH); ! 182: } ! 183: if (timer_head.next->expires <= jiffies) ! 184: mark_bh(TIMER_BH); ! 185: if (tq_timer != &tq_last) ! 186: mark_bh(TQUEUE_BH); ! 187: if (linux_timer_print) ! 188: printf ("linux_timer_intr: pic_mask[0] %x\n", pic_mask[0]); ! 189: } ! 190:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.