1/*	$NetBSD: schedule.c,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
2
3/*	$KAME: schedule.c,v 1.19 2001/11/05 10:53:19 sakane Exp $	*/
4
5/*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "config.h"
35
36#include <sys/types.h>
37#include <sys/param.h>
38#include <sys/time.h>
39#include <sys/queue.h>
40#include <sys/socket.h>
41
42#include <stdlib.h>
43#include <stdio.h>
44#include <string.h>
45#include <errno.h>
46#include <time.h>
47#include <dispatch/dispatch.h>
48
49#include "misc.h"
50#include "plog.h"
51#include "schedule.h"
52#include "var.h"
53#include "gcmalloc.h"
54#include "power_mgmt.h"
55#include "localconf.h"
56
57#if !defined(__LP64__)
58// year 2038 problem and fix for 32-bit only
59#define FIXY2038PROBLEM
60#endif
61
62
63extern int		terminated;
64
65#ifdef FIXY2038PROBLEM
66#define Y2038TIME_T	0x7fffffff
67static time_t launched;		/* time when the program launched. */
68static time_t deltaY2038;
69#endif
70
71static TAILQ_HEAD(_schedtree, sched) sctree;
72
73
74void
75timer_handler(struct sched *sched)
76{
77	if (slept_at || woke_at)
78        sched->dead = 1;
79
80    TAILQ_REMOVE(&sctree, sched, chain);
81
82    if (!sched->dead) {
83        if (sched->func != NULL && !terminated) {
84			(sched->func)(sched->param);
85        }
86    }
87    racoon_free(sched);
88}
89
90/*
91 * add new schedule to schedule table.
92 */
93schedule_ref
94sched_new(time_t tick, void (*func) (void *), void *param)
95{
96    static schedule_ref next_ref = 1;
97	struct sched *new_sched;
98
99    if (next_ref == 0)
100        next_ref++;
101
102	new_sched = (struct sched *)racoon_malloc(sizeof(*new_sched));
103	if (new_sched == NULL)
104		return 0;
105
106    new_sched->ref = next_ref++;
107    new_sched->dead = 0;
108	new_sched->func = func;
109	new_sched->param = param;
110    new_sched->xtime = current_time() + tick;
111
112	/* add to schedule table */
113	TAILQ_INSERT_TAIL(&sctree, new_sched, chain);
114    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, tick * NSEC_PER_SEC), dispatch_get_main_queue(),
115                   ^{
116                       timer_handler(new_sched);
117                   });
118
119	return new_sched->ref;
120}
121
122/* get current time.
123 * if defined FIXY2038PROBLEM, base time is the time when called sched_init().
124 * Otherwise, conform to time(3).
125 */
126time_t
127current_time()
128{
129	time_t n;
130#ifdef FIXY2038PROBLEM
131	time_t t;
132
133	time(&n);
134	t = n - launched;
135	if (t < 0)
136		t += deltaY2038;
137
138	return t;
139#else
140	return time(&n);
141#endif
142}
143
144int
145sched_is_dead(schedule_ref ref)
146{
147    struct sched *sc;
148
149    if (ref == 0)
150        return 1;
151    TAILQ_FOREACH(sc, &sctree, chain) {
152		if (sc->ref == ref) {
153            if (sc->dead)
154                return 1;
155            return 0;
156        }
157	}
158    return 1;
159}
160
161
162int
163sched_get_time(schedule_ref ref, time_t *time)
164{
165    struct sched *sc;
166
167    if (ref != 0) {
168        TAILQ_FOREACH(sc, &sctree, chain) {
169            if (sc->ref == ref) {
170                if (sc->dead)
171                    return 0;
172                *time = sc->xtime;
173                return 1;
174            }
175        }
176    }
177    return 0;
178}
179
180void
181sched_kill(schedule_ref ref)
182{
183    struct sched *sc;
184
185    if (ref != 0) {
186        TAILQ_FOREACH(sc, &sctree, chain) {
187            if (sc->ref == ref) {
188                sc->dead = 1;
189                return;
190            }
191        }
192	}
193}
194
195void
196sched_killall(void)
197{
198	struct sched *sc;
199
200	TAILQ_FOREACH(sc, &sctree, chain)
201        sc->dead = 1;
202}
203
204
205/* XXX this function is probably unnecessary. */
206void
207sched_scrub_param(void *param)
208{
209	struct sched *sc;
210
211	TAILQ_FOREACH(sc, &sctree, chain) {
212		if (sc->param == param) {
213			sc->dead = 1;
214        }
215	}
216}
217
218/* initialize schedule table */
219void
220sched_init()
221{
222#ifdef FIXY2038PROBLEM
223	time(&launched);
224
225	deltaY2038 = Y2038TIME_T - launched;
226#endif
227
228	TAILQ_INIT(&sctree);
229	return;
230}
231
232