1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (c) 2002 Cray Inc.
5 * Copyright (c) 2002 Eric Hoffman
7 * This file is part of Lustre, http://www.lustre.org.
9 * Lustre is free software; you can redistribute it and/or
10 * modify it under the terms of version 2 of the GNU General Public
11 * License as published by the Free Software Foundation.
13 * Lustre is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with Lustre; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 * this file implements a simple priority-queue based timer system. when
25 * combined with a file which implements now() and block(), it can
26 * be used to provide course-grained time-based callbacks.
34 void (*function)(void *);
41 typedef struct thunk *thunk;
48 extern when now(void);
52 static void (*block_function)(when);
53 static int number_of_timers;
54 static int size_of_pqueue;
58 static void heal(int where)
61 int right=(where<<1)+1;
65 if (left <= number_of_timers)
66 if (timers[left]->w < timers[min]->w) min=left;
67 if (right <= number_of_timers)
68 if (timers[right]->w < timers[min]->w) min=right;
71 timers[where]=timers[min];
77 static void add_pqueue(int i)
81 if ((i>1) && (timers[i]->w< timers[parent]->w)){
83 timers[i]=timers[parent];
89 static void add_timer(timer t)
91 if (size_of_pqueue<(number_of_timers+2)){
92 int oldsize=size_of_pqueue;
93 timer *new=(void *)malloc(sizeof(struct timer)*(size_of_pqueue+=10));
94 memcpy(new,timers,sizeof(timer)*oldsize);
97 timers[++number_of_timers]=t;
98 add_pqueue(number_of_timers);
101 /* Function: register_timer
102 * Arguments: interval: the time interval from the current time when
103 * the timer function should be called
104 * function: the function to call when the time has expired
105 * argument: the argument to call it with.
106 * Returns: a pointer to a timer structure
108 timer register_timer(when interval,
109 void (*function)(void *),
112 timer t=(timer)malloc(sizeof(struct timer));
115 t->function=function;
116 t->interval=interval;
120 if (!internal && (number_of_timers==1))
121 block_function(t->w);
125 /* Function: remove_timer
129 * remove_timer removes a timer from the system, insuring
130 * that it will never be called. It does not actually
131 * free the timer due to reentrancy issues.
134 void remove_timer(timer t)
146 timers[1]=timers[number_of_timers--];
148 if (!current->disable) {
149 (*current->function)(current->arg);
154 when next_timer(void)
158 while (number_of_timers && (timers[1]->w <= here)) timer_fire();
159 if (number_of_timers) return(timers[1]->w);
163 /* Function: timer_loop
167 * timer_loop() is the blocking dispatch function for the timer.
168 * Is calls the block() function registered with init_timer,
169 * and handles associated with timers that have been registered.
179 for (z=thunks;z;z=z->next) (*z->f)(z->a);
181 if (number_of_timers){
182 if (timers[1]->w > here){
183 (*block_function)(timers[1]->w);
189 for (z=thunks;z;z=z->next) (*z->f)(z->a);
190 (*block_function)(0);
196 /* Function: register_thunk
197 * Arguments: f: the function to call
198 * a: the single argument to call it with
200 * Thunk functions get called at irregular intervals, they
201 * should not assume when, or take a particularily long
202 * amount of time. Thunks are for background cleanup tasks.
204 void register_thunk(void (*f)(void *),void *a)
206 thunk t=(void *)malloc(sizeof(struct thunk));
213 /* Function: initialize_timer
214 * Arguments: block: the function to call to block for the specified interval
216 * initialize_timer() must be called before any other timer function,
217 * including timer_loop.
219 void initialize_timer(void (*block)(when))
221 block_function=block;
224 timers=(timer *)malloc(sizeof(timer)*size_of_pqueue);