⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sip_timeout.c

📁 VoIP use SIP protocol interface
💻 C
字号:
/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END *//* * Copyright 2006 Sun Microsystems, Inc.  All rights reserved. * Use is subject to license terms. */#pragma ident	"@(#)sip_timeout.c	1.12	06/08/16 SMI"/* * Simple implementation of timeout functionality. The granuality is a sec */#include <stdio.h>#include <pthread.h>#include <sys/errno.h>#include <stdlib.h>#include "sip_miscdefs.h"uint_t		sip_timeout(void *arg, void (*callback_func)(void *),		    struct timeval *timeout_time);boolean_t	sip_untimeout(uint_t);typedef struct timeout {	struct timeout *sip_timeout_next;	hrtime_t sip_timeout_val;	void (*sip_timeout_callback_func)(void *);	void *sip_timeout_callback_func_arg;	int   sip_timeout_id;} sip_timeout_t;static pthread_mutex_t timeout_mutex = PTHREAD_MUTEX_INITIALIZER;static pthread_cond_t  timeout_cond_var = PTHREAD_COND_INITIALIZER;static sip_timeout_t *timeout_list;static sip_timeout_t *timeout_current_start;static sip_timeout_t *timeout_current_end;/* * LONG_SLEEP_TIME = (24 * 60 * 60 * NANOSEC) */#define	LONG_SLEEP_TIME	(0x15180LL * 0x3B9ACA00LL)uint_t timer_id = 0;/* Invoke the callback function *//* ARGSUSED */static void *sip_run_to_functions(void *arg){	sip_timeout_t *timeout = NULL;	(void) pthread_mutex_lock(&timeout_mutex);	while (timeout_current_start != NULL) {		timeout = timeout_current_start;		if (timeout_current_end == timeout_current_start)			timeout_current_start = timeout_current_end = NULL;		else			timeout_current_start = timeout->sip_timeout_next;		(void) pthread_mutex_unlock(&timeout_mutex);		timeout->sip_timeout_callback_func(		    timeout->sip_timeout_callback_func_arg);		free(timeout);		(void) pthread_mutex_lock(&timeout_mutex);	}	(void) pthread_mutex_unlock(&timeout_mutex);	pthread_exit(NULL);	return ((void *)0);}/* * In the very very unlikely case timer id wraps around and we have two timers * with the same id. If that happens timer with the least amount of time left * will be deleted. In case both timers have same time left than the one that * was scheduled first will be deleted as it will be in the front of the list. */boolean_tsip_untimeout(uint_t id){	boolean_t	ret = B_FALSE;	sip_timeout_t	*current, *last;	last = NULL;	(void) pthread_mutex_lock(&timeout_mutex);	/* Check if this is in the to-be run list */	if (timeout_current_start != NULL) {		current = timeout_current_start;		while (current != NULL) {			if (current->sip_timeout_id == id) {				if (current == timeout_current_start) {					timeout_current_start =					    current->sip_timeout_next;				} else {					last->sip_timeout_next =					    current->sip_timeout_next;				}				if (current == timeout_current_end)					timeout_current_end = last;				if (current->sip_timeout_callback_func_arg !=				    NULL) {					free(current->					    sip_timeout_callback_func_arg);					current->sip_timeout_callback_func_arg =					    NULL;				}				free(current);				ret = B_TRUE;				break;			}			last = current;			current = current->sip_timeout_next;		}	}	/* Check if this is in the to-be scheduled list */	if (!ret && timeout_list != NULL) {		last = NULL;		current = timeout_list;		while (current != NULL) {			if (current->sip_timeout_id == id) {				if (current == timeout_list) {					timeout_list =					    current->sip_timeout_next;				} else {					last->sip_timeout_next =					    current->sip_timeout_next;				}				if (current->sip_timeout_callback_func_arg !=				    NULL) {					free(current->					    sip_timeout_callback_func_arg);					current->sip_timeout_callback_func_arg =					    NULL;				}				free(current);				ret = B_TRUE;				break;			}			last = current;			current = current->sip_timeout_next;		}	}	(void) pthread_mutex_unlock(&timeout_mutex);	return (ret);}/* * Add a new timeout */uint_tsip_timeout(void *arg, void (*callback_func)(void *),    struct timeval *timeout_time){	sip_timeout_t	*new_timeout;	sip_timeout_t	*current, *last;	hrtime_t	future_time;	uint_t		tid;#ifdef	__linux__	struct timespec	tspec;	hrtime_t	now;#endif	new_timeout = malloc(sizeof (sip_timeout_t));	if (new_timeout == NULL)		return (0);#ifdef	__linux__	if (clock_gettime(CLOCK_REALTIME, &tspec) != 0)		return (0);	now = (hrtime_t)tspec.tv_sec * (hrtime_t)NANOSEC + tspec.tv_nsec;	future_time = (hrtime_t)timeout_time->tv_sec * (hrtime_t)NANOSEC +	    (hrtime_t)(timeout_time->tv_usec * MILLISEC) + now;#else	future_time = (hrtime_t)timeout_time->tv_sec * (hrtime_t)NANOSEC +	    (hrtime_t)(timeout_time->tv_usec * MILLISEC) + gethrtime();#endif	if (future_time <= 0L) {		free(new_timeout);		return (0);	}	new_timeout->sip_timeout_next = NULL;	new_timeout->sip_timeout_val = future_time;	new_timeout->sip_timeout_callback_func = callback_func;	new_timeout->sip_timeout_callback_func_arg = arg;	(void) pthread_mutex_lock(&timeout_mutex);	timer_id++;	if (timer_id == 0)		timer_id++;	tid = timer_id;	new_timeout->sip_timeout_id = tid;	last = current = timeout_list;	while (current != NULL) {		if (current->sip_timeout_val <= new_timeout->sip_timeout_val) {			last = current;			current = current->sip_timeout_next;		} else {			break;		}	}	if (current == timeout_list) {		new_timeout->sip_timeout_next  = timeout_list;		timeout_list = new_timeout;	} else {		new_timeout->sip_timeout_next = current,		last->sip_timeout_next = new_timeout;	}	(void) pthread_cond_signal(&timeout_cond_var);	(void) pthread_mutex_unlock(&timeout_mutex);	return (tid);}/* Schedule the next timeout */static hrtime_tsip_schedule_to_functions(){	sip_timeout_t		*timeout = NULL;	sip_timeout_t		*last = NULL;	boolean_t		create_thread = B_FALSE;	hrtime_t		current_time;#ifdef	__linux__	struct timespec	tspec;#endif	/*	 * Thread is holding the mutex.	 */#ifdef	__linux__	if (clock_gettime(CLOCK_REALTIME, &tspec) != 0)		return ((hrtime_t)LONG_SLEEP_TIME + current_time);	current_time = (hrtime_t)tspec.tv_sec * (hrtime_t)NANOSEC +	    tspec.tv_nsec;#else	current_time = gethrtime();#endif	if (timeout_list == NULL)		return ((hrtime_t)LONG_SLEEP_TIME + current_time);	timeout = timeout_list;	/*	 * Get all the timeouts that have fired.	 */	while (timeout != NULL && timeout->sip_timeout_val <= current_time) {		last = timeout;		timeout = timeout->sip_timeout_next;	}	timeout = last;	if (timeout != NULL) {		if (timeout_current_end != NULL) {			timeout_current_end->sip_timeout_next = timeout_list;			timeout_current_end = timeout;		} else {			timeout_current_start = timeout_list;			timeout_current_end = timeout;			create_thread = B_TRUE;		}		timeout_list = timeout->sip_timeout_next;		timeout->sip_timeout_next = NULL;		if (create_thread) {			pthread_t	thr;			(void) pthread_create(&thr, NULL, sip_run_to_functions,			    NULL);		}	}	if (timeout_list != NULL)		return (timeout_list->sip_timeout_val);	else		return ((hrtime_t)LONG_SLEEP_TIME + current_time);}/* The timer routine *//* ARGSUSED */static void *sip_timer_thr(void *arg){	timestruc_t	to;	hrtime_t	current_time;	hrtime_t	next_timeout;	hrtime_t	delta;#ifdef	__linux__	struct timespec	tspec;#endif	to.tv_sec = time(NULL) + 5;	to.tv_nsec = 0;	(void) pthread_mutex_lock(&timeout_mutex);	for (;;) {		(void) pthread_cond_timedwait(&timeout_cond_var,		    &timeout_mutex, &to);		/*		 * We return from timedwait because we either timed out		 * or a new element was added and we need to reset the time		 */again:		next_timeout =  sip_schedule_to_functions();#ifdef	__linux__		if (clock_gettime(CLOCK_REALTIME, &tspec) != 0)			goto again; /* ??? */		current_time = (hrtime_t)tspec.tv_sec * (hrtime_t)NANOSEC +		    tspec.tv_nsec;#else		current_time = gethrtime();#endif		delta = next_timeout - current_time;		if (delta <= 0)			goto again;		to.tv_sec = time(NULL) + (delta / NANOSEC);		to.tv_nsec = delta % NANOSEC;	}	/* NOTREACHED */	return ((void *)0);}/* The init routine, starts the timer thread */voidsip_timeout_init(){	static boolean_t	timout_init = B_FALSE;	pthread_t		thread1;	(void) pthread_mutex_lock(&timeout_mutex);	if (timout_init == B_FALSE) {		timout_init = B_TRUE;		(void) pthread_mutex_unlock(&timeout_mutex);	} else {		(void) pthread_mutex_unlock(&timeout_mutex);		return;	}	(void) pthread_create(&thread1, NULL, sip_timer_thr, NULL);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -