#include "config.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <dispatch/dispatch.h>
#include "misc.h"
#include "plog.h"
#include "schedule.h"
#include "var.h"
#include "gcmalloc.h"
#include "power_mgmt.h"
#include "localconf.h"
#if !defined(__LP64__)
#define FIXY2038PROBLEM
#endif
extern int terminated;
#ifdef FIXY2038PROBLEM
#define Y2038TIME_T 0x7fffffff
static time_t launched;
static time_t deltaY2038;
#endif
static TAILQ_HEAD(_schedtree, sched) sctree;
void
timer_handler(struct sched *sched)
{
if (slept_at || woke_at)
sched->dead = 1;
TAILQ_REMOVE(&sctree, sched, chain);
if (!sched->dead) {
if (sched->func != NULL && !terminated) {
(sched->func)(sched->param);
}
}
racoon_free(sched);
}
schedule_ref
sched_new(time_t tick, void (*func) (void *), void *param)
{
static schedule_ref next_ref = 1;
struct sched *new_sched;
if (next_ref == 0)
next_ref++;
new_sched = (struct sched *)racoon_malloc(sizeof(*new_sched));
if (new_sched == NULL)
return 0;
new_sched->ref = next_ref++;
new_sched->dead = 0;
new_sched->func = func;
new_sched->param = param;
new_sched->xtime = current_time() + tick;
TAILQ_INSERT_TAIL(&sctree, new_sched, chain);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, tick * NSEC_PER_SEC), dispatch_get_main_queue(),
^{
timer_handler(new_sched);
});
return new_sched->ref;
}
time_t
current_time()
{
time_t n;
#ifdef FIXY2038PROBLEM
time_t t;
time(&n);
t = n - launched;
if (t < 0)
t += deltaY2038;
return t;
#else
return time(&n);
#endif
}
int
sched_is_dead(schedule_ref ref)
{
struct sched *sc;
if (ref == 0)
return 1;
TAILQ_FOREACH(sc, &sctree, chain) {
if (sc->ref == ref) {
if (sc->dead)
return 1;
return 0;
}
}
return 1;
}
int
sched_get_time(schedule_ref ref, time_t *time)
{
struct sched *sc;
if (ref != 0) {
TAILQ_FOREACH(sc, &sctree, chain) {
if (sc->ref == ref) {
if (sc->dead)
return 0;
*time = sc->xtime;
return 1;
}
}
}
return 0;
}
void
sched_kill(schedule_ref ref)
{
struct sched *sc;
if (ref != 0) {
TAILQ_FOREACH(sc, &sctree, chain) {
if (sc->ref == ref) {
sc->dead = 1;
return;
}
}
}
}
void
sched_killall(void)
{
struct sched *sc;
TAILQ_FOREACH(sc, &sctree, chain)
sc->dead = 1;
}
void
sched_scrub_param(void *param)
{
struct sched *sc;
TAILQ_FOREACH(sc, &sctree, chain) {
if (sc->param == param) {
sc->dead = 1;
}
}
}
void
sched_init()
{
#ifdef FIXY2038PROBLEM
time(&launched);
deltaY2038 = Y2038TIME_T - launched;
#endif
TAILQ_INIT(&sctree);
return;
}