timer.c revision 298523461941e171ce97ea8b76892ac01bb7a49f
#include <stddef.h>
#include <stdlib.h>
#include <isc/assertions.h>
#include <isc/unexpect.h>
#include <isc/condition.h>
/*
* We use macros instead of calling the os_ routines directly because
* the capital letters make the locking stand out.
*
* We INSIST that they succeed since there's no way for us to continue
* if they fail.
*/
#define VALID_TIMER(t) ((t) != NULL && \
(t)->magic == TIMER_MAGIC)
struct timer_t {
/* Not locked. */
unsigned int magic;
/* Locked by timer lock. */
unsigned int references;
/* Locked by manager lock. */
void * arg;
unsigned int index;
};
#define VALID_MANAGER(m) ((m) != NULL && \
(m)->magic == TIMER_MANAGER_MAGIC)
struct timer_manager_t {
/* Not locked. */
unsigned int magic;
/* Locked by manager lock. */
unsigned int nscheduled;
};
static boolean_t
return (TRUE);
return (FALSE);
}
static void
}
static inline void
/*
* The caller must ensure locking.
*/
if (first_time) {
else
} else
} else {
/* Idle timer. */
} else {
}
} else {
/*
* Time touched is in the future! Make it now.
*/
}
}
}
static inline isc_result
/*
* The caller must ensure locking.
*/
/*
* Already scheduled.
*/
case -1:
break;
case 1:
break;
case 0:
/* Nothing to do. */
break;
}
} else {
if (result != ISC_R_SUCCESS) {
return (ISC_R_NOMEMORY);
}
manager->nscheduled++;
}
/*
* If this timer is at the head of the queue, we must wake up the
* run thread so it doesn't sleep too long.
*/
return (ISC_R_SUCCESS);
}
static inline void
/*
* The caller must ensure locking.
*/
need_wakeup = TRUE;
manager->nscheduled--;
if (need_wakeup)
}
}
static void
/*
* The caller must ensure locking.
*/
}
{
/*
* Create a new 'type' timer managed by 'manager'. The timers
* parameters are specified by 'absolute' and 'interval'. Events
* will be posted to 'task' and when dispatched 'action' will be
* called with 'arg' as the arg value. The new timer is returned
* in 'timerp'.
*/
/*
* Get current time.
*/
if (result != ISC_R_SUCCESS) {
"os_time_get() failed: %s",
return (ISC_R_UNEXPECTED);
}
return (ISC_R_NOMEMORY);
return (ISC_R_UNEXPECTED);
}
/*
* Note we don't have to lock the timer like we normally would because
* there are no external references to it yet.
*/
if (result == ISC_R_SUCCESS)
return (result);
}
{
/*
* Change the timer's type, absolute, and interval values to the
* given values.
*/
/*
* Get current time.
*/
if (result != ISC_R_SUCCESS) {
"os_time_get() failed: %s",
return (ISC_R_UNEXPECTED);
}
return (result);
}
/*
* Make 'timer' inactive, and purge any pending timer events for
* this timer in the timer's task's event queue.
*/
return (ISC_R_SUCCESS);
}
/*
* Set the last-touched time of 'timer' to the current time.
*/
if (result != ISC_R_SUCCESS) {
"os_time_get() failed: %s",
return (ISC_R_UNEXPECTED);
}
return (ISC_R_SUCCESS);
}
void
/*
* Attach *timerp to timer.
*/
timer->references++;
}
void
/*
* Detach *timerp from its timer.
*/
timer->references--;
if (timer->references == 0)
free_timer = TRUE;
if (free_timer)
}
static void *
printf("timer run thread awake\n");
if (manager->nscheduled > 0) {
&timeout);
} else {
}
}
return (NULL);
}
/*
* Create a timer manager.
*/
return (ISC_R_NOMEMORY);
manager->nscheduled = 0;
if (result != ISC_R_SUCCESS) {
return (ISC_R_NOMEMORY);
}
return (ISC_R_UNEXPECTED);
}
"os_condition_init() failed");
return (ISC_R_UNEXPECTED);
}
"os_thread_create() failed");
return (ISC_R_UNEXPECTED);
}
return (ISC_R_SUCCESS);
}
void
/*
* Destroy a timer manager.
*/
/*
* Wait for thread to exit.
*/
"os_thread_join() failed");
/*
* Clean up.
*/
}