| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 1999 - 2005, Digium, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-04-15 17:34:14 +00:00
										 |  |  |  * Mark Spencer <markster@digium.com> | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * See http://www.asterisk.org for more information about
 | 
					
						
							|  |  |  |  * the Asterisk project. Please do not directly contact | 
					
						
							|  |  |  |  * any of the maintainers of this project for assistance; | 
					
						
							|  |  |  |  * the project provides a web site, mailing lists and IRC | 
					
						
							|  |  |  |  * channels for your use. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software, distributed under the terms of | 
					
						
							|  |  |  |  * the GNU General Public License Version 2. See the LICENSE file | 
					
						
							|  |  |  |  * at the top of the source tree. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  | /*! \file
 | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  |  * \brief Scheduler Routines (from cheops-NG) | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-12-30 21:18:06 +00:00
										 |  |  |  * \author Mark Spencer <markster@digium.com> | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-07 18:54:56 +00:00
										 |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | #ifdef DEBUG_SCHEDULER
 | 
					
						
							| 
									
										
										
										
											2006-05-05 18:11:55 +00:00
										 |  |  | #define DEBUG(a) do { \
 | 
					
						
							|  |  |  | 	if (option_debug) \ | 
					
						
							|  |  |  | 		DEBUG_M(a) \ | 
					
						
							|  |  |  | 	} while (0) | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | #define DEBUG(a) 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <sys/time.h>
 | 
					
						
							| 
									
										
										
										
											2003-11-21 18:38:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-21 06:02:45 +00:00
										 |  |  | #include "asterisk/sched.h"
 | 
					
						
							|  |  |  | #include "asterisk/channel.h"
 | 
					
						
							|  |  |  | #include "asterisk/lock.h"
 | 
					
						
							| 
									
										
										
										
											2005-07-15 23:00:47 +00:00
										 |  |  | #include "asterisk/utils.h"
 | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | #include "asterisk/linkedlists.h"
 | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | #include "asterisk/dlinkedlists.h"
 | 
					
						
							|  |  |  | #include "asterisk/hashtab.h"
 | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | struct sched { | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 	AST_DLLIST_ENTRY(sched) list; | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 	int id;                       /*!< ID number of event */ | 
					
						
							|  |  |  | 	struct timeval when;          /*!< Absolute time event should take place */ | 
					
						
							|  |  |  | 	int resched;                  /*!< When to reschedule */ | 
					
						
							|  |  |  | 	int variable;                 /*!< Use return value from callback to reschedule */ | 
					
						
							| 
									
										
										
										
											2007-09-21 14:40:10 +00:00
										 |  |  | 	const void *data;             /*!< Data */ | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 	ast_sched_cb callback;        /*!< Callback */ | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct sched_context { | 
					
						
							| 
									
										
										
										
											2003-11-21 18:38:42 +00:00
										 |  |  | 	ast_mutex_t lock; | 
					
						
							| 
									
										
										
										
											2006-07-12 18:28:31 +00:00
										 |  |  | 	unsigned int eventcnt;                  /*!< Number of events processed */ | 
					
						
							|  |  |  | 	unsigned int schedcnt;                  /*!< Number of outstanding schedule events */ | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 	unsigned int highwater;					/*!< highest count so far */ | 
					
						
							|  |  |  | 	AST_DLLIST_HEAD_NOLOCK(, sched) schedq;   /*!< Schedule entry and main queue */ | 
					
						
							|  |  |  | 	struct ast_hashtab *schedq_ht;             /*!< hash table for fast searching */ | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef SCHED_MAX_CACHE
 | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 	AST_LIST_HEAD_NOLOCK(, sched) schedc;   /*!< Cache of unused schedule structures and how many */ | 
					
						
							| 
									
										
										
										
											2006-07-12 18:28:31 +00:00
										 |  |  | 	unsigned int schedccnt; | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* hash routines for sched */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int sched_cmp(const void *a, const void *b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const struct sched *as = a; | 
					
						
							|  |  |  | 	const struct sched *bs = b; | 
					
						
							|  |  |  | 	return as->id != bs->id; /* return 0 on a match like strcmp would */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static unsigned int sched_hash(const void *obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const struct sched *s = obj; | 
					
						
							|  |  |  | 	unsigned int h = s->id; | 
					
						
							|  |  |  | 	return h; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | struct sched_context *sched_context_create(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct sched_context *tmp; | 
					
						
							| 
									
										
										
										
											2006-03-18 19:16:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!(tmp = ast_calloc(1, sizeof(*tmp)))) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_init(&tmp->lock); | 
					
						
							|  |  |  | 	tmp->eventcnt = 1; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 	tmp->schedq_ht = ast_hashtab_create(23, sched_cmp, ast_hashtab_resize_java, ast_hashtab_newsize_java, sched_hash, 1); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 	return tmp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void sched_context_destroy(struct sched_context *con) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 	struct sched *s; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-21 18:38:42 +00:00
										 |  |  | 	ast_mutex_lock(&con->lock); | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-23 16:50:12 +00:00
										 |  |  | #ifdef SCHED_MAX_CACHE
 | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 	/* Eliminate the cache */ | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 	while ((s = AST_LIST_REMOVE_HEAD(&con->schedc, list))) | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 		ast_free(s); | 
					
						
							| 
									
										
										
										
											2001-04-23 16:50:12 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 	/* And the queue */ | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 	while ((s = AST_DLLIST_REMOVE_HEAD(&con->schedq, list))) | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 		ast_free(s); | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ast_hashtab_destroy(con->schedq_ht, NULL); | 
					
						
							|  |  |  | 	con->schedq_ht = NULL; | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 	/* And the context */ | 
					
						
							| 
									
										
										
										
											2003-11-21 18:38:42 +00:00
										 |  |  | 	ast_mutex_unlock(&con->lock); | 
					
						
							| 
									
										
										
										
											2004-06-22 17:42:14 +00:00
										 |  |  | 	ast_mutex_destroy(&con->lock); | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 	ast_free(con); | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct sched *sched_alloc(struct sched_context *con) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 	struct sched *tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * We keep a small cache of schedule entries | 
					
						
							|  |  |  | 	 * to minimize the number of necessary malloc()'s | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | #ifdef SCHED_MAX_CACHE
 | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 	if ((tmp = AST_LIST_REMOVE_HEAD(&con->schedc, list))) | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 		con->schedccnt--; | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 		tmp = ast_calloc(1, sizeof(*tmp)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 	return tmp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void sched_release(struct sched_context *con, struct sched *tmp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Add to the cache, or just free() if we | 
					
						
							|  |  |  | 	 * already have too many cache entries | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SCHED_MAX_CACHE	 
 | 
					
						
							|  |  |  | 	if (con->schedccnt < SCHED_MAX_CACHE) { | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 		AST_LIST_INSERT_HEAD(&con->schedc, tmp, list); | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 		con->schedccnt++; | 
					
						
							|  |  |  | 	} else | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 		ast_free(tmp); | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-08 17:41:03 +00:00
										 |  |  | /*! \brief
 | 
					
						
							|  |  |  |  * Return the number of milliseconds  | 
					
						
							|  |  |  |  * until the next scheduled event | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | int ast_sched_wait(struct sched_context *con) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int ms; | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-24 18:51:41 +00:00
										 |  |  | 	DEBUG(ast_debug(1, "ast_sched_wait()\n")); | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-21 18:38:42 +00:00
										 |  |  | 	ast_mutex_lock(&con->lock); | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 	if (AST_DLLIST_EMPTY(&con->schedq)) { | 
					
						
							| 
									
										
										
										
											2003-11-21 18:38:42 +00:00
										 |  |  | 		ms = -1; | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 		ms = ast_tvdiff_ms(AST_DLLIST_FIRST(&con->schedq)->when, ast_tvnow()); | 
					
						
							| 
									
										
										
										
											2003-11-21 18:38:42 +00:00
										 |  |  | 		if (ms < 0) | 
					
						
							|  |  |  | 			ms = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ast_mutex_unlock(&con->lock); | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 	return ms; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-08 17:41:03 +00:00
										 |  |  | /*! \brief
 | 
					
						
							|  |  |  |  * Take a sched structure and put it in the | 
					
						
							|  |  |  |  * queue, such that the soonest event is | 
					
						
							|  |  |  |  * first in the list.  | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | static void schedule(struct sched_context *con, struct sched *s) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 	struct sched *cur = NULL; | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 	int ret; | 
					
						
							|  |  |  | 	int df = 0; | 
					
						
							|  |  |  | 	int de = 0; | 
					
						
							|  |  |  | 	struct sched *first = AST_DLLIST_FIRST(&con->schedq); | 
					
						
							|  |  |  | 	struct sched *last = AST_DLLIST_LAST(&con->schedq); | 
					
						
							| 
									
										
										
										
											2008-05-07 21:11:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 	if (first) | 
					
						
							|  |  |  | 		df = ast_tvdiff_us(s->when, first->when); | 
					
						
							|  |  |  | 	if (last) | 
					
						
							|  |  |  | 		de = ast_tvdiff_us(s->when, last->when); | 
					
						
							| 
									
										
										
										
											2008-05-07 21:11:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 	if (df < 0) | 
					
						
							|  |  |  | 		df = -df; | 
					
						
							|  |  |  | 	if (de < 0) | 
					
						
							|  |  |  | 		de = -de; | 
					
						
							| 
									
										
										
										
											2008-05-07 21:11:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (df < de) { | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 		AST_DLLIST_TRAVERSE(&con->schedq, cur, list) { | 
					
						
							|  |  |  | 			if (ast_tvcmp(s->when, cur->when) == -1) { | 
					
						
							|  |  |  | 				AST_DLLIST_INSERT_BEFORE(&con->schedq, cur, s, list); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-05-07 21:11:33 +00:00
										 |  |  | 		if (!cur) { | 
					
						
							|  |  |  | 			AST_DLLIST_INSERT_TAIL(&con->schedq, s, list); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 		AST_DLLIST_TRAVERSE_BACKWARDS(&con->schedq, cur, list) { | 
					
						
							|  |  |  | 			if (ast_tvcmp(s->when, cur->when) == 1) { | 
					
						
							|  |  |  | 				AST_DLLIST_INSERT_AFTER(&con->schedq, cur, s, list); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-05-07 21:11:33 +00:00
										 |  |  | 		if (!cur) { | 
					
						
							|  |  |  | 			AST_DLLIST_INSERT_HEAD(&con->schedq, s, list); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 	ret = ast_hashtab_insert_safe(con->schedq_ht, s); | 
					
						
							|  |  |  | 	if (!ret) | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING,"Schedule Queue entry %d is already in table!\n",s->id); | 
					
						
							| 
									
										
										
										
											2008-05-07 21:11:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 	con->schedcnt++; | 
					
						
							| 
									
										
										
										
											2008-05-07 21:11:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 	if (con->schedcnt > con->highwater) | 
					
						
							|  |  |  | 		con->highwater = con->schedcnt; | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-08 17:41:03 +00:00
										 |  |  | /*! \brief
 | 
					
						
							| 
									
										
										
										
											2005-07-15 23:00:47 +00:00
										 |  |  |  * given the last event *tv and the offset in milliseconds 'when', | 
					
						
							|  |  |  |  * computes the next value, | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int sched_settime(struct timeval *tv, int when) | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-07-15 23:00:47 +00:00
										 |  |  | 	struct timeval now = ast_tvnow(); | 
					
						
							| 
									
										
										
										
											2003-07-27 03:53:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-25 13:42:51 +00:00
										 |  |  | 	/*ast_debug(1, "TV -> %lu,%lu\n", tv->tv_sec, tv->tv_usec);*/ | 
					
						
							| 
									
										
										
										
											2005-07-15 23:00:47 +00:00
										 |  |  | 	if (ast_tvzero(*tv))	/* not supplied, default to now */ | 
					
						
							|  |  |  | 		*tv = now; | 
					
						
							|  |  |  | 	*tv = ast_tvadd(*tv, ast_samp2tv(when, 1000)); | 
					
						
							|  |  |  | 	if (ast_tvcmp(*tv, now) < 0) { | 
					
						
							| 
									
										
										
										
											2007-06-24 18:51:41 +00:00
										 |  |  | 		ast_debug(1, "Request to schedule in the past?!?!\n"); | 
					
						
							| 
									
										
										
										
											2005-07-15 23:00:47 +00:00
										 |  |  | 		*tv = now; | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-21 14:40:10 +00:00
										 |  |  | int ast_sched_replace_variable(int old_id, struct sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) | 
					
						
							| 
									
										
										
										
											2007-08-17 14:07:44 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-08-30 20:31:45 +00:00
										 |  |  | 	/* 0 means the schedule item is new; do not delete */ | 
					
						
							| 
									
										
										
										
											2008-05-02 02:33:04 +00:00
										 |  |  | 	if (old_id > 0) { | 
					
						
							|  |  |  | 		AST_SCHED_DEL(con, old_id); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-08-17 14:07:44 +00:00
										 |  |  | 	return ast_sched_add_variable(con, when, callback, data, variable); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2005-08-22 22:55:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-08 17:41:03 +00:00
										 |  |  | /*! \brief
 | 
					
						
							|  |  |  |  * Schedule callback(data) to happen when ms into the future | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-09-21 14:40:10 +00:00
										 |  |  | int ast_sched_add_variable(struct sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct sched *tmp; | 
					
						
							| 
									
										
										
										
											2003-11-21 18:38:42 +00:00
										 |  |  | 	int res = -1; | 
					
						
							| 
									
										
										
										
											2007-06-24 18:51:41 +00:00
										 |  |  | 	DEBUG(ast_debug(1, "ast_sched_add()\n")); | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 	if (!when) { | 
					
						
							| 
									
										
										
										
											2003-11-12 08:57:23 +00:00
										 |  |  | 		ast_log(LOG_NOTICE, "Scheduled event in 0 ms?\n"); | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2003-11-21 18:38:42 +00:00
										 |  |  | 	ast_mutex_lock(&con->lock); | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 	if ((tmp = sched_alloc(con))) { | 
					
						
							|  |  |  | 		tmp->id = con->eventcnt++; | 
					
						
							|  |  |  | 		tmp->callback = callback; | 
					
						
							|  |  |  | 		tmp->data = data; | 
					
						
							|  |  |  | 		tmp->resched = when; | 
					
						
							| 
									
										
										
										
											2005-08-22 22:55:06 +00:00
										 |  |  | 		tmp->variable = variable; | 
					
						
							| 
									
										
										
										
											2006-05-05 18:11:55 +00:00
										 |  |  | 		tmp->when = ast_tv(0, 0); | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 		if (sched_settime(&tmp->when, when)) { | 
					
						
							|  |  |  | 			sched_release(con, tmp); | 
					
						
							| 
									
										
										
										
											2003-11-21 18:38:42 +00:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 			schedule(con, tmp); | 
					
						
							| 
									
										
										
										
											2003-11-21 18:38:42 +00:00
										 |  |  | 			res = tmp->id; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-07-15 22:21:31 +00:00
										 |  |  | #ifdef DUMP_SCHEDULER
 | 
					
						
							|  |  |  | 	/* Dump contents of the context while we have the lock so nothing gets screwed up by accident. */ | 
					
						
							| 
									
										
										
										
											2006-05-05 18:11:55 +00:00
										 |  |  | 	if (option_debug) | 
					
						
							|  |  |  | 		ast_sched_dump(con); | 
					
						
							| 
									
										
										
										
											2005-07-15 22:21:31 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2003-11-21 20:41:43 +00:00
										 |  |  | 	ast_mutex_unlock(&con->lock); | 
					
						
							| 
									
										
										
										
											2003-11-21 18:38:42 +00:00
										 |  |  | 	return res; | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-21 14:40:10 +00:00
										 |  |  | int ast_sched_replace(int old_id, struct sched_context *con, int when, ast_sched_cb callback, const void *data) | 
					
						
							| 
									
										
										
										
											2007-08-17 14:07:44 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-02 02:33:04 +00:00
										 |  |  | 	if (old_id > -1) { | 
					
						
							|  |  |  | 		AST_SCHED_DEL(con, old_id); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-08-17 14:07:44 +00:00
										 |  |  | 	return ast_sched_add(con, when, callback, data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-21 14:40:10 +00:00
										 |  |  | int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data) | 
					
						
							| 
									
										
										
										
											2005-08-22 22:55:06 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	return ast_sched_add_variable(con, when, callback, data, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | const void *ast_sched_find_data(struct sched_context *con, int id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct sched tmp,*res; | 
					
						
							|  |  |  | 	tmp.id = id; | 
					
						
							|  |  |  | 	res = ast_hashtab_lookup(con->schedq_ht, &tmp); | 
					
						
							|  |  |  | 	if (res) | 
					
						
							|  |  |  | 		return res->data; | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2006-03-08 17:41:03 +00:00
										 |  |  | /*! \brief
 | 
					
						
							|  |  |  |  * Delete the schedule entry with number | 
					
						
							|  |  |  |  * "id".  It's nearly impossible that there | 
					
						
							|  |  |  |  * would be two or more in the list with that | 
					
						
							|  |  |  |  * id. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2008-07-30 22:38:58 +00:00
										 |  |  | #ifndef AST_DEVMODE
 | 
					
						
							| 
									
										
										
										
											2008-07-18 16:48:18 +00:00
										 |  |  | int ast_sched_del(struct sched_context *con, int id) | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2008-07-18 16:33:56 +00:00
										 |  |  | int _ast_sched_del(struct sched_context *con, int id, const char *file, int line, const char *function) | 
					
						
							| 
									
										
										
										
											2008-07-18 16:48:18 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 	struct sched *s, tmp; | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 	DEBUG(ast_debug(1, "ast_sched_del(%d)\n", id)); | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2003-11-21 18:38:42 +00:00
										 |  |  | 	ast_mutex_lock(&con->lock); | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 	/* OK, this is the heart of the sched performance upgrade.
 | 
					
						
							|  |  |  | 	   If we have 4700 peers, we can have 4700+ entries in the | 
					
						
							|  |  |  | 	   schedq list. searching this would take time. So, I add a  | 
					
						
							|  |  |  | 	   hashtab to the context to keep track of each entry, by id. | 
					
						
							|  |  |  | 	   I also leave the linked list alone, almost, --  I implement | 
					
						
							|  |  |  |        a doubly-linked list instead, because it would do little good | 
					
						
							|  |  |  | 	   to look up the id in a hashtab, and then have to run thru  | 
					
						
							|  |  |  | 	   a couple thousand entries to remove it from the schedq list! */ | 
					
						
							|  |  |  | 	tmp.id = id; | 
					
						
							|  |  |  | 	s = ast_hashtab_lookup(con->schedq_ht, &tmp); | 
					
						
							|  |  |  | 	if (s) { | 
					
						
							|  |  |  | 		struct sched *x = AST_DLLIST_REMOVE(&con->schedq, s, list); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if (!x) | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING,"sched entry %d not in the schedq list?\n", s->id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!ast_hashtab_remove_this_object(con->schedq_ht, s)) | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING,"Found sched entry %d, then couldn't remove it?\n", s->id); | 
					
						
							|  |  |  | 		con->schedcnt--; | 
					
						
							|  |  |  | 		sched_release(con, s); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2005-07-15 22:21:31 +00:00
										 |  |  | #ifdef DUMP_SCHEDULER
 | 
					
						
							|  |  |  | 	/* Dump contents of the context while we have the lock so nothing gets screwed up by accident. */ | 
					
						
							| 
									
										
										
										
											2006-05-05 18:11:55 +00:00
										 |  |  | 	if (option_debug) | 
					
						
							|  |  |  | 		ast_sched_dump(con); | 
					
						
							| 
									
										
										
										
											2005-07-15 22:21:31 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2003-11-21 18:38:42 +00:00
										 |  |  | 	ast_mutex_unlock(&con->lock); | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-21 18:38:42 +00:00
										 |  |  | 	if (!s) { | 
					
						
							| 
									
										
										
										
											2007-06-24 18:51:41 +00:00
										 |  |  | 		ast_debug(1, "Attempted to delete nonexistent schedule entry %d!\n", id); | 
					
						
							| 
									
										
										
										
											2008-07-30 22:38:58 +00:00
										 |  |  | #ifndef AST_DEVMODE
 | 
					
						
							| 
									
										
										
										
											2008-07-18 17:10:34 +00:00
										 |  |  | 		ast_assert(s != NULL); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2008-07-18 16:33:56 +00:00
										 |  |  | 		_ast_assert(0, "s != NULL", file, line, function); | 
					
						
							| 
									
										
										
										
											2008-07-18 17:10:34 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2003-11-21 18:38:42 +00:00
										 |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | char *ast_sched_report(struct sched_context *con, char *buf, int bufsiz, struct ast_cb_names *cbnames) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int *countlist,i; | 
					
						
							|  |  |  | 	struct sched *cur; | 
					
						
							|  |  |  | 	char buf2[1200]; | 
					
						
							|  |  |  | 	ast_sched_cb xxx = NULL; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	buf[0] = 0; | 
					
						
							|  |  |  | 	sprintf(buf, " Highwater = %d\n schedcnt = %d\n", con->highwater, con->schedcnt); | 
					
						
							|  |  |  | 	countlist = ast_calloc(sizeof(int),cbnames->numassocs+1); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	AST_DLLIST_TRAVERSE(&con->schedq, cur, list) { | 
					
						
							|  |  |  | 		/* match the callback to the cblist */ | 
					
						
							|  |  |  | 		for (i=0;i<cbnames->numassocs;i++) { | 
					
						
							|  |  |  | 			if (cur->callback == cbnames->cblist[i]) | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (i < cbnames->numassocs) | 
					
						
							|  |  |  | 			countlist[i]++; | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			xxx = cur->callback; | 
					
						
							|  |  |  | 			countlist[cbnames->numassocs]++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for (i=0;i<cbnames->numassocs;i++) { | 
					
						
							|  |  |  | 		sprintf(buf2,"    %s : %d\n", cbnames->list[i], countlist[i]); | 
					
						
							|  |  |  | 		strcat(buf, buf2); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	sprintf(buf2,"   <unknown:%p> : %d\n", xxx, countlist[cbnames->numassocs]); | 
					
						
							|  |  |  | 	strcat( buf, buf2); | 
					
						
							|  |  |  | 	return buf; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2006-05-05 18:11:55 +00:00
										 |  |  | /*! \brief Dump the contents of the scheduler to LOG_DEBUG */ | 
					
						
							| 
									
										
										
										
											2005-07-15 22:21:31 +00:00
										 |  |  | void ast_sched_dump(const struct sched_context *con) | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct sched *q; | 
					
						
							| 
									
										
										
										
											2005-07-15 23:00:47 +00:00
										 |  |  | 	struct timeval tv = ast_tvnow(); | 
					
						
							| 
									
										
										
										
											2001-04-23 16:50:12 +00:00
										 |  |  | #ifdef SCHED_MAX_CACHE
 | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 	ast_debug(1, "Asterisk Schedule Dump (%d in Q, %d Total, %d Cache, %d high-water)\n", con->schedcnt, con->eventcnt - 1, con->schedccnt, con->highwater); | 
					
						
							| 
									
										
										
										
											2001-04-23 16:50:12 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 	ast_debug(1, "Asterisk Schedule Dump (%d in Q, %d Total, %d high-water)\n", con->schedcnt, con->eventcnt - 1, con->highwater); | 
					
						
							| 
									
										
										
										
											2001-04-23 16:50:12 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-25 13:42:51 +00:00
										 |  |  | 	ast_debug(1, "=============================================================\n"); | 
					
						
							|  |  |  | 	ast_debug(1, "|ID    Callback          Data              Time  (sec:ms)   |\n"); | 
					
						
							|  |  |  | 	ast_debug(1, "+-----+-----------------+-----------------+-----------------+\n"); | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 	AST_DLLIST_TRAVERSE(&con->schedq, q, list) { | 
					
						
							| 
									
										
										
										
											2007-06-25 13:42:51 +00:00
										 |  |  | 		struct timeval delta = ast_tvsub(q->when, tv); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ast_debug(1, "|%.4d | %-15p | %-15p | %.6ld : %.6ld |\n",  | 
					
						
							|  |  |  | 			q->id, | 
					
						
							|  |  |  | 			q->callback, | 
					
						
							|  |  |  | 			q->data, | 
					
						
							| 
									
										
										
										
											2008-05-15 10:56:29 +00:00
										 |  |  | 			(long)delta.tv_sec, | 
					
						
							| 
									
										
										
										
											2007-06-25 13:42:51 +00:00
										 |  |  | 			(long int)delta.tv_usec); | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-06-25 13:42:51 +00:00
										 |  |  | 	ast_debug(1, "=============================================================\n"); | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-08 17:41:03 +00:00
										 |  |  | /*! \brief
 | 
					
						
							|  |  |  |  * Launch all events which need to be run at this time. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | int ast_sched_runq(struct sched_context *con) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct sched *current; | 
					
						
							|  |  |  | 	struct timeval tv; | 
					
						
							| 
									
										
										
										
											2006-07-12 18:28:31 +00:00
										 |  |  | 	int numevents; | 
					
						
							| 
									
										
										
										
											2003-11-21 22:05:08 +00:00
										 |  |  | 	int res; | 
					
						
							| 
									
										
										
										
											2006-07-12 18:28:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-24 18:51:41 +00:00
										 |  |  | 	DEBUG(ast_debug(1, "ast_sched_runq()\n")); | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2003-11-21 18:38:42 +00:00
										 |  |  | 	ast_mutex_lock(&con->lock); | 
					
						
							| 
									
										
										
										
											2006-07-12 18:28:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 	for (numevents = 0; !AST_DLLIST_EMPTY(&con->schedq); numevents++) { | 
					
						
							| 
									
										
										
										
											2005-07-15 23:00:47 +00:00
										 |  |  | 		/* schedule all events which are going to expire within 1ms.
 | 
					
						
							|  |  |  | 		 * We only care about millisecond accuracy anyway, so this will | 
					
						
							|  |  |  | 		 * help us get more than one event at one time if they are very | 
					
						
							|  |  |  | 		 * close together. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		tv = ast_tvadd(ast_tvnow(), ast_tv(0, 1000)); | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 		if (ast_tvcmp(AST_DLLIST_FIRST(&con->schedq)->when, tv) != -1) | 
					
						
							| 
									
										
										
										
											2006-07-12 18:28:31 +00:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 		current = AST_DLLIST_REMOVE_HEAD(&con->schedq, list); | 
					
						
							|  |  |  | 		if (!ast_hashtab_remove_this_object(con->schedq_ht, current)) | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR,"Sched entry %d was in the schedq list but not in the hashtab???\n", current->id); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-07-12 18:28:31 +00:00
										 |  |  | 		con->schedcnt--; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * At this point, the schedule queue is still intact.  We | 
					
						
							|  |  |  | 		 * have removed the first event and the rest is still there, | 
					
						
							|  |  |  | 		 * so it's permissible for the callback to add new events, but | 
					
						
							|  |  |  | 		 * trying to delete itself won't work because it isn't in | 
					
						
							|  |  |  | 		 * the schedule queue.  If that's what it wants to do, it  | 
					
						
							|  |  |  | 		 * should return 0. | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2003-11-21 22:05:08 +00:00
										 |  |  | 			 | 
					
						
							| 
									
										
										
										
											2006-07-12 18:28:31 +00:00
										 |  |  | 		ast_mutex_unlock(&con->lock); | 
					
						
							|  |  |  | 		res = current->callback(current->data); | 
					
						
							|  |  |  | 		ast_mutex_lock(&con->lock); | 
					
						
							| 
									
										
										
										
											2003-11-21 22:05:08 +00:00
										 |  |  | 			 | 
					
						
							| 
									
										
										
										
											2006-07-12 18:28:31 +00:00
										 |  |  | 		if (res) { | 
					
						
							|  |  |  | 		 	/*
 | 
					
						
							|  |  |  | 			 * If they return non-zero, we should schedule them to be | 
					
						
							|  |  |  | 			 * run again. | 
					
						
							|  |  |  | 			 */ | 
					
						
							|  |  |  | 			if (sched_settime(¤t->when, current->variable? res : current->resched)) { | 
					
						
							|  |  |  | 				sched_release(con, current); | 
					
						
							|  |  |  | 			} else | 
					
						
							|  |  |  | 				schedule(con, current); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			/* No longer needed, so release it */ | 
					
						
							|  |  |  | 		 	sched_release(con, current); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-07-12 18:28:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-21 18:38:42 +00:00
										 |  |  | 	ast_mutex_unlock(&con->lock); | 
					
						
							| 
									
										
										
										
											2006-07-12 18:28:31 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	return numevents; | 
					
						
							| 
									
										
										
										
											1999-10-13 04:15:49 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2005-04-13 18:46:35 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | long ast_sched_when(struct sched_context *con,int id) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 	struct sched *s, tmp; | 
					
						
							| 
									
										
										
										
											2006-07-12 18:28:31 +00:00
										 |  |  | 	long secs = -1; | 
					
						
							| 
									
										
										
										
											2007-06-24 18:51:41 +00:00
										 |  |  | 	DEBUG(ast_debug(1, "ast_sched_when()\n")); | 
					
						
							| 
									
										
										
										
											2005-04-13 18:46:35 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_lock(&con->lock); | 
					
						
							| 
									
										
										
										
											2008-04-16 20:09:39 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* these next 2 lines replace a lookup loop */ | 
					
						
							|  |  |  | 	tmp.id = id; | 
					
						
							|  |  |  | 	s = ast_hashtab_lookup(con->schedq_ht, &tmp); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 	if (s) { | 
					
						
							| 
									
										
										
										
											2005-07-15 23:00:47 +00:00
										 |  |  | 		struct timeval now = ast_tvnow(); | 
					
						
							| 
									
										
										
										
											2006-04-06 15:55:15 +00:00
										 |  |  | 		secs = s->when.tv_sec - now.tv_sec; | 
					
						
							| 
									
										
										
										
											2005-04-13 18:46:35 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	ast_mutex_unlock(&con->lock); | 
					
						
							| 
									
										
										
										
											2006-05-05 17:09:27 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2005-04-13 18:46:35 +00:00
										 |  |  | 	return secs; | 
					
						
							|  |  |  | } |