* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* @(#)clock.c 5.3 (Berkeley) 5/12/91
* $Id: clock.c,v 5.2.1.5 91/05/07 22:17:49 jsp Alpha $
* Modelled on kernel object of the same name.
* Use of a heap-based mechanism was rejected:
* 1. more complex implementation needed.
* 2. not obvious that a list is too slow for Amd.
typedef struct callout callout
;
callout
*c_next
; /* List of callouts */
void (*c_fn
)(); /* Function to call */
voidp c_closure
; /* Closure to pass to call */
time_t c_time
; /* Time of call */
int c_id
; /* Unique identifier */
static callout callouts
; /* List of pending callouts */
static callout
*free_callouts
; /* Cache of free callouts */
static int nfree_callouts
; /* Number on free list */
static int callout_id
; /* Next free callout identifier */
time_t next_softclock
; /* Time of next call to softclock() */
* Number of callout slots we keep on the free list
#define CALLOUT_FREE_SLOP 10
* Global assumption: valid id's are non-zero.
#define CID_ALLOC() (++callout_id)
static callout
*alloc_callout(P_void
);
static callout
*alloc_callout()
callout
*cp
= free_callouts
;
free_callouts
= free_callouts
->c_next
;
static void free_callout
P((callout
*cp
));
static void free_callout(cp
)
if (nfree_callouts
> CALLOUT_FREE_SLOP
) {
cp
->c_next
= free_callouts
;
* (*fn)(closure) will be called at clocktime() + secs
int timeout
P((unsigned int secs
, void (*fn
)(), voidp closure
));
int timeout(secs
, fn
, closure
)
time_t t
= clocktime() + secs
;
* Allocate and fill in a new callout structure
callout
*cpnew
= alloc_callout();
cpnew
->c_closure
= closure
;
cpnew
->c_id
= CID_ALLOC();
* Find the correct place in the list
for (cp
= &callouts
; cp2
= cp
->c_next
; cp
= cp2
)
* Return callout identifier
void untimeout
P((int id
));
for (cp
= &callouts
; cp2
= cp
->c_next
; cp
= cp2
) {
cp
->c_next
= cp2
->c_next
;
* Reschedule after clock changed
void reschedule_timeouts
P((time_t now
, time_t then
));
void reschedule_timeouts(now
, then
)
for (cp
= callouts
.c_next
; cp
; cp
= cp
->c_next
) {
if (cp
->c_time
>= now
&& cp
->c_time
<= then
) {
plog(XLOG_WARNING
, "job %d rescheduled to run immediately", cp
->c_id
);
dlog("rescheduling job %d back %d seconds",
cp
->c_id
, cp
->c_time
- now
);
next_softclock
= cp
->c_time
= now
;
* While there are more callouts waiting...
while ((cp
= callouts
.c_next
) && cp
->c_time
<= now
) {
* Extract first from list, save fn & closure and
* unlink callout from list and free.
* The free is done first because
* it is quite common that the
* function will call timeout()
* and try to allocate a callout
voidp closure
= cp
->c_closure
;
callouts
.c_next
= cp
->c_next
;
/*dlog("Calling %#x(%#x)", fn, closure);*/
} while (task_notify_todo
);
* Return number of seconds to next event,
* or 0 if there is no event.
if (cp
= callouts
.c_next
)