[asterisk-commits] kmoore: branch kmoore/scheduler r410980 - in /team/kmoore/scheduler: include/...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Mar 21 08:33:21 CDT 2014


Author: kmoore
Date: Fri Mar 21 08:33:05 2014
New Revision: 410980

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=410980
Log:
Make ast_sched_del non-blocking

Modified:
    team/kmoore/scheduler/include/asterisk/sched.h
    team/kmoore/scheduler/main/sched.c

Modified: team/kmoore/scheduler/include/asterisk/sched.h
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/scheduler/include/asterisk/sched.h?view=diff&rev=410980&r1=410979&r2=410980
==============================================================================
--- team/kmoore/scheduler/include/asterisk/sched.h (original)
+++ team/kmoore/scheduler/include/asterisk/sched.h Fri Mar 21 08:33:05 2014
@@ -125,10 +125,9 @@
  * \brief Deletes a scheduled event
  *
  * Remove this event from being run. A procedure should not remove its own
- * event, but return 0 instead.
- *
- * The caller must not hold locks that the callback acquires when attempting
- * to delete the scheduled event. This call is blocking on callback execution.
+ * event, but return 0 instead. If a scheduled event is deleted while executing,
+ * that event will be prevented from rescheduling itself. Additional deletion
+ * attempts will result in failure, even if the callback is still executing.
  *
  * \param con scheduling context to delete item from
  * \param id ID of the scheduled item to delete

Modified: team/kmoore/scheduler/main/sched.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/scheduler/main/sched.c?view=diff&rev=410980&r1=410979&r2=410980
==============================================================================
--- team/kmoore/scheduler/main/sched.c (original)
+++ team/kmoore/scheduler/main/sched.c Fri Mar 21 08:33:05 2014
@@ -67,9 +67,10 @@
 	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 */
 	void *object;                 /*!< AO2 object for callback */
 	ast_sched_cb callback;        /*!< Callback */
+	unsigned int variable:1;      /*!< Use return value from callback to reschedule */
+	unsigned int deleted:1;       /*!< Flagged for deletion during execution */
 	ssize_t __heap_index;
 };
 
@@ -82,9 +83,10 @@
 struct ast_sched_context {
 	ast_mutex_t lock;
 	unsigned int eventcnt;                  /*!< Number of events processed */
-	unsigned int highwater;					/*!< highest count so far */
+	unsigned int highwater;			/*!< highest count so far */
 	struct ast_heap *sched_heap;
 	struct sched_thread *sched_thread;
+	struct sched *current;			/*!< Scheduler entry currently being processed */
 
 #ifdef SCHED_MAX_CACHE
 	AST_LIST_HEAD_NOLOCK(, sched) schedc;   /*!< Cache of unused schedule structures and how many */
@@ -455,6 +457,9 @@
 		}
 
 		sched_release(con, s);
+	} else if (con->current && con->current->id == id && !con->current->deleted) {
+		con->current->deleted = 1;
+		s = con->current;
 	}
 
 #ifdef DUMP_SCHEDULER
@@ -562,7 +567,6 @@
  */
 int ast_sched_runq(struct ast_sched_context *con)
 {
-	struct sched *current;
 	struct timeval when;
 	int numevents;
 	int res;
@@ -572,17 +576,17 @@
 	ast_mutex_lock(&con->lock);
 
 	when = ast_tvadd(ast_tvnow(), ast_tv(0, 1000));
-	for (numevents = 0; (current = ast_heap_peek(con->sched_heap, 1)); numevents++) {
+	for (numevents = 0; (con->current = ast_heap_peek(con->sched_heap, 1)); numevents++) {
 		/* 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.
 		 */
-		if (ast_tvcmp(current->when, when) != -1) {
+		if (ast_tvcmp(con->current->when, when) != -1) {
 			break;
 		}
 
-		current = ast_heap_pop(con->sched_heap);
+		con->current = ast_heap_pop(con->sched_heap);
 
 		/*
 		 * At this point, the schedule queue is still intact.  We
@@ -593,23 +597,27 @@
 		 * should return 0.
 		 */
 
+		ast_mutex_unlock(&con->lock);
 		res = current->callback(current->object);
-		if (res) {
+		ast_mutex_lock(&con->lock);
+
+		if (res && !con->current->deleted) {
 			/*
 			 * If they return non-zero, we should schedule them to be
 			 * run again.
 			 */
-			if (sched_settime(&current->when, current->variable? res : current->resched)) {
-				sched_release(con, current);
+			if (sched_settime(&con->current->when, con->current->variable ? res : con->current->resched)) {
+				sched_release(con, con->current);
 			} else {
-				schedule(con, current);
+				schedule(con, con->current);
 			}
 		} else {
 			/* No longer needed, so release it */
-			sched_release(con, current);
-		}
-	}
-
+			sched_release(con, con->current);
+		}
+	}
+
+	con->current = NULL;
 	ast_mutex_unlock(&con->lock);
 
 	return numevents;




More information about the asterisk-commits mailing list