sip_timeout.c revision 2c2c41837e330b002c4220a39638150db504fe0e
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * CDDL HEADER START
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * The contents of this file are subject to the terms of the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Common Development and Distribution License (the "License").
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * You may not use this file except in compliance with the License.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * See the License for the specific language governing permissions
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * and limitations under the License.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * When distributing Covered Code, include this CDDL HEADER in each
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * If applicable, add the following below this CDDL HEADER, with the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * fields enclosed by brackets "[]" replaced with your own identifying
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * information: Portions Copyright [yyyy] [name of copyright owner]
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * CDDL HEADER END
2c2c41837e330b002c4220a39638150db504fe0evi * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Use is subject to license terms.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#pragma ident "%Z%%M% %I% %E% SMI"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Simple implementation of timeout functionality. The granuality is a sec
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viuint_t sip_timeout(void *arg, void (*callback_func)(void *),
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vitypedef struct timeout {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi void (*sip_timeout_callback_func)(void *);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vistatic pthread_mutex_t timeout_mutex = PTHREAD_MUTEX_INITIALIZER;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vistatic pthread_cond_t timeout_cond_var = PTHREAD_COND_INITIALIZER;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * LONG_SLEEP_TIME = (24 * 60 * 60 * NANOSEC)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Invoke the callback function
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/* ARGSUSED */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vistatic void *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ((void *)0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * In the very very unlikely case timer id wraps around and we have two timers
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * with the same id. If that happens timer with the least amount of time left
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * will be deleted. In case both timers have same time left than the one that
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * was scheduled first will be deleted as it will be in the front of the list.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Check if this is in the to-be run list
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Check if this is in the to-be scheduled list
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Add a new timeout
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi now = (hrtime_t)tspec.tv_sec * (hrtime_t)NANOSEC + tspec.tv_nsec;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi future_time = (hrtime_t)timeout_time->tv_sec * (hrtime_t)NANOSEC +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi future_time = (hrtime_t)timeout_time->tv_sec * (hrtime_t)NANOSEC +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (hrtime_t)(timeout_time->tv_usec * MILLISEC) + gethrtime();
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (future_time <= 0L) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (current->sip_timeout_val <= new_timeout->sip_timeout_val) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Schedule the next timeout
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Thread is holding the mutex.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi current_time = (hrtime_t)tspec.tv_sec * (hrtime_t)NANOSEC +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Get all the timeouts that have fired.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (timeout != NULL && timeout->sip_timeout_val <= current_time) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * The timer routine
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/* ARGSUSED */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vistatic void *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi for (;;) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * We return from timedwait because we either timed out
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * or a new element was added and we need to reset the time
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi current_time = (hrtime_t)tspec.tv_sec * (hrtime_t)NANOSEC +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /* NOTREACHED */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ((void *)0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * The init routine, starts the timer thread