|
|
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.