[Asterisk-cvs] asterisk devicestate.c,1.2,1.3

kpfleming at lists.digium.com kpfleming at lists.digium.com
Sun Jul 10 08:58:31 CDT 2005


Update of /usr/cvsroot/asterisk
In directory localhost.localdomain:/tmp/cvs-serv13932

Modified Files:
	devicestate.c 
Log Message:
simplify locking (use a single lock, no deadlock possible)


Index: devicestate.c
===================================================================
RCS file: /usr/cvsroot/asterisk/devicestate.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- devicestate.c	10 Jul 2005 12:09:40 -0000	1.2
+++ devicestate.c	10 Jul 2005 13:06:54 -0000	1.3
@@ -44,7 +44,6 @@
 static AST_LIST_HEAD_STATIC(state_changes, state_change);
 
 static pthread_t change_thread = AST_PTHREADT_NULL;
-AST_MUTEX_DEFINE_STATIC(change_pending_lock);
 static pthread_cond_t change_pending;
 
 int ast_parse_device_state(const char *device)
@@ -138,6 +137,7 @@
 	AST_LIST_UNLOCK(&devstate_cbs);
 }
 
+/*--- do_state_change: Notify callback watchers of change, and notify PBX core for hint updates */
 static void do_state_change(const char *device)
 {
 	int state;
@@ -155,7 +155,6 @@
 	ast_hint_state_changed(device);
 }
 
-/*--- ast_device_state_changed: Notify callback watchers of change, and notify PBX core for hint updates */
 int ast_device_state_changed(const char *fmt, ...) 
 {
 	char buf[AST_MAX_EXTENSION];
@@ -183,15 +182,10 @@
 		strcpy(change->device, device);
 		AST_LIST_LOCK(&state_changes);
 		AST_LIST_INSERT_TAIL(&state_changes, change, list);
-		if (AST_LIST_FIRST(&state_changes) == change) {
-			AST_LIST_UNLOCK(&state_changes);
+		if (AST_LIST_FIRST(&state_changes) == change)
 			/* the list was empty, signal the thread */
-			ast_mutex_lock(&change_pending_lock);
 			pthread_cond_signal(&change_pending);
-			ast_mutex_unlock(&change_pending_lock);
-		} else {
-			AST_LIST_UNLOCK(&state_changes);
-		}
+		AST_LIST_UNLOCK(&state_changes);
 	}
 
 	return 1;
@@ -201,20 +195,21 @@
 {
 	struct state_change *cur;
 
+	AST_LIST_LOCK(&state_changes);
 	for(;;) {
-		ast_mutex_lock(&change_pending_lock);
-		pthread_cond_wait(&change_pending, &change_pending_lock);
-		for (;;) {
-			AST_LIST_LOCK(&state_changes);
-			cur = AST_LIST_REMOVE_HEAD(&state_changes, list);
+		/* the list lock will _always_ be held at this point in the loop */
+		cur = AST_LIST_REMOVE_HEAD(&state_changes, list);
+		if (cur) {
+			/* we got an entry, so unlock the list while we process it */
 			AST_LIST_UNLOCK(&state_changes);
-			if (!cur)
-				break;
-
 			do_state_change(cur->device);
 			free(cur);
+			AST_LIST_LOCK(&state_changes);
+		} else {
+			/* there was no entry, so atomically unlock the list and wait for
+			   the condition to be signalled (returns with the lock held) */
+			pthread_cond_wait(&change_pending, &state_changes.lock);
 		}
-		ast_mutex_unlock(&change_pending_lock);
 	}
 
 	return NULL;




More information about the svn-commits mailing list