Files
Arquivotheca.SunOS-4.1.4/usr.lib/libsunwindow/notify/ndet_itimer.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

213 lines
5.5 KiB
C

#ifndef lint
#ifdef sccs
static char sccsid[] = "@(#)ndet_itimer.c 1.1 94/10/31 Copyr 1985 Sun Micro";
#endif
#endif
/*
* Copyright (c) 1985 by Sun Microsystems, Inc.
*/
/*
* Ndet_itimer.c - Implement itimer specific calls that are shared among
* NTFY_REAL_ITIMER and NTFY_VIRTUAL_ITIMER.
*/
#include <sunwindow/ntfy.h>
#include <sunwindow/ndet.h>
#include <sunwindow/ndis.h> /* For ndis_enqueue */
#include <sunwindow/nint.h> /* For nint_get_func */
extern struct itimerval NOTIFY_NO_ITIMER;
extern struct itimerval NOTIFY_POLLING_ITIMER;
/*
* General utilities:
*/
pkg_private int
ndet_check_which(which, type_ptr)
int which;
NTFY_TYPE *type_ptr;
{
NTFY_TYPE type;
switch (which) {
case ITIMER_REAL: type = NTFY_REAL_ITIMER; break;
case ITIMER_VIRTUAL: type = NTFY_VIRTUAL_ITIMER; break;
default: ntfy_set_errno(NOTIFY_BAD_ITIMER); return(-1);
}
if (type_ptr)
*type_ptr = type;
return(0);
}
/* Stolen (in most part) from /sys/sys/kern_time.c */
pkg_private int
ndet_check_tv(tv)
struct timeval *tv;
{
if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
tv->tv_usec < 0 || tv->tv_usec >= 1000000) {
ntfy_set_errno(NOTIFY_INVAL);
return (-1);
}
return(0);
}
/* atv-btv */
pkg_private struct timeval
ndet_tv_subt(atv, btv)
struct timeval atv, btv;
{
if ((atv.tv_usec < btv.tv_usec) && atv.tv_sec) {
atv.tv_usec += 1000000;
atv.tv_sec--;
}
if (atv.tv_usec > btv.tv_usec)
atv.tv_usec -= btv.tv_usec;
else
atv.tv_usec = 0;
if (atv.tv_sec > btv.tv_sec)
atv.tv_sec -= btv.tv_sec;
else {
if (atv.tv_sec < btv.tv_sec)
atv.tv_usec = 0;
atv.tv_sec = 0;
}
/* Prevent getting polling constant for a result */
if (ndet_tv_equal(atv, NOTIFY_POLLING_ITIMER.it_value))
timerclear(&atv);
return(atv);
}
/* min(atv, btv) */
pkg_private struct timeval
ndet_tv_min(atv, btv)
struct timeval atv, btv;
{
struct timeval res;
res = ndet_tv_subt(atv, btv);
if (timerisset(&res))
/* Means that btv is < atv */
return(btv);
else
/* Means that atv is <= btv */
return(atv);
}
/*
* Figure the interval that has transpired since this real interval timer
* has been set. The difference between how much time the timer wants
* to wait and how long it has waited is the amount of time left to wait.
* The time left to wait is returned.
*/
pkg_private struct timeval
ndet_real_min(ntfy_itimer, current_tv)
NTFY_ITIMER *ntfy_itimer;
struct timeval current_tv;
{
struct timeval time_dif;
time_dif = ndet_tv_subt(current_tv, ntfy_itimer->set_tv);
return(ndet_tv_subt(ntfy_itimer->itimer.it_value, time_dif));
}
/*
* Update the interval until expiration by subtracting the amount of
* time on the process interval timer (current_tv) from the
* value of the process interval timer when it was last looked at by
* this client (ntfy_itimer->set_tv).
*
* Return the amount of time that this virtual interval timer has to go
* before expiration (ntfy_itimer->itimer.it_value). When the overall
* minimum time until expiration is computed, ntfy_itimer will update
* ntfy_itimer->set_tv with this value.
*/
pkg_private struct timeval
ndet_virtual_min(ntfy_itimer, current_tv)
NTFY_ITIMER *ntfy_itimer;
struct timeval current_tv;
{
struct timeval time_dif;
time_dif = ndet_tv_subt(ntfy_itimer->set_tv, current_tv);
ntfy_itimer->itimer.it_value = ndet_tv_subt(
ntfy_itimer->itimer.it_value, time_dif);
return(ntfy_itimer->itimer.it_value);
}
/*
* Dispatch notification, reset itimer value,
* remove if nothing to wait for and returns -1 else 0.
*/
pkg_private int
ndet_itimer_expired(client, condition)
NTFY_CLIENT *client;
NTFY_CONDITION *condition;
{
register NTFY_ITIMER *ntfy_itimer = condition->data.ntfy_itimer;
NTFY_CLIENT client_tmp;
NTFY_CONDITION condition_tmp;
int rc = 0;
Notify_func functions[NTFY_FUNCS_MAX];
/*
* Remember contents of following for call to ndis_enqueue because
* call to notify_set_itimer_func can invalidate.
*/
client_tmp = *client;
condition_tmp = *condition;
if (condition->func_count > 1) {
condition_tmp.callout.functions = functions;
bcopy((caddr_t)condition->callout.functions,
(caddr_t)condition_tmp.callout.functions,
sizeof(NTFY_NODE));
} else
condition_tmp.callout.function = condition->callout.function;
/* Reset itimer value from interval */
ntfy_itimer->itimer.it_value = ntfy_itimer->itimer.it_interval;
/* Remove condition if nothing to wait for */
if (!timerisset(&(ntfy_itimer->itimer.it_value))) {
Notify_func func, myfunc = nint_get_func(condition);
/*
* Enumerator (which is calling this) is designed to survive
* having condition disappear in middle of enumeration.
*/
func = notify_set_itimer_func(client->nclient, NOTIFY_FUNC_NULL,
(condition->type == NTFY_REAL_ITIMER)? ITIMER_REAL:
ITIMER_VIRTUAL,
&NOTIFY_NO_ITIMER, (struct itimerval *)0);
ntfy_assert(func == myfunc, "Error when removing itimer");
rc = -1;
}
/* Send notification */
if (ndis_enqueue(&client_tmp, &condition_tmp) != NOTIFY_OK)
ntfy_fatal_error("Error when enq condition");
return (rc);
}
pkg_private void
ndet_reset_itimer_set_tv(condition)
NTFY_CONDITION *condition;
{
int n;
if (condition->type == NTFY_REAL_ITIMER) {
n = gettimeofday(&condition->data.ntfy_itimer->set_tv, (struct timezone *)0);
/* SYSTEM CALL */
ntfy_assert(n == 0, "Unexpected error: gettimeofday");
} else {
struct itimerval process_itimer;
n = getitimer(ITIMER_VIRTUAL, &process_itimer); /*SYSTEM CALL*/
ntfy_assert(n == 0, "Unexpected error: getitimer");
condition->data.ntfy_itimer->set_tv = process_itimer.it_value;
}
}