[asterisk-commits] rmudgett: trunk r217912 - /trunk/channels/chan_dahdi.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Sep 10 17:31:17 CDT 2009


Author: rmudgett
Date: Thu Sep 10 17:31:12 2009
New Revision: 217912

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=217912
Log:
Cleaned up chan_dahdi iflist handling and locking.

*  Fixed walking the iflist so it is always done with the iflock locked.
*  Simplified iflist walking routines.
*  Created chan_dahdi iflist insertion and extraction routines.
*  Fixed duplicate_pseudo() malloc fail handling.
*  Fixed infinite loop in action_dahdishowchannels() when showing a single channel.

Modified:
    trunk/channels/chan_dahdi.c

Modified: trunk/channels/chan_dahdi.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/channels/chan_dahdi.c?view=diff&rev=217912&r1=217911&r2=217912
==============================================================================
--- trunk/channels/chan_dahdi.c (original)
+++ trunk/channels/chan_dahdi.c Thu Sep 10 17:31:12 2009
@@ -4694,14 +4694,99 @@
 	return 0;
 }
 
-static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
-{
-	struct dahdi_pvt *p = *pvt;
+/*!
+ * \internal
+ * \brief Insert the given chan_dahdi interface structure into the interface list.
+ * \since 1.6.3
+ *
+ * \param pvt chan_dahdi private interface structure to insert.
+ *
+ * \details
+ * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
+ * Any duplicates are inserted after the existing entries.
+ *
+ * \note The new interface must not already be in the list.
+ *
+ * \return Nothing
+ */
+static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
+{
+	struct dahdi_pvt *cur;
+
+	/* Find place in middle of list for the new interface. */
+	for (cur = iflist; cur; cur = cur->next) {
+		if (pvt->channel < cur->channel) {
+			/* New interface goes before the current interface. */
+			pvt->prev = cur->prev;
+			pvt->next = cur;
+			if (cur->prev) {
+				/* Insert into the middle of the list. */
+				cur->prev->next = pvt;
+			} else {
+				/* Insert at head of list. */
+				iflist = pvt;
+			}
+			cur->prev = pvt;
+			return;
+		}
+	}
+
+	/* New interface goes onto the end of the list */
+	pvt->prev = ifend;
+	pvt->next = NULL;
+	if (ifend) {
+		ifend->next = pvt;
+	}
+	ifend = pvt;
+	if (!iflist) {
+		/* List was empty */
+		iflist = pvt;
+	}
+}
+
+/*!
+ * \internal
+ * \brief Extract the given chan_dahdi interface structure from the interface list.
+ * \since 1.6.3
+ *
+ * \param pvt chan_dahdi private interface structure to extract.
+ *
+ * \note
+ * The given interface structure can be either in the interface list or a stand alone
+ * structure that has not been put in the list if the next and prev pointers are NULL.
+ *
+ * \return Nothing
+ */
+static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
+{
+	/* Extract from the forward chain. */
+	if (pvt->prev) {
+		pvt->prev->next = pvt->next;
+	} else if (iflist == pvt) {
+		/* Node is at the head of the list. */
+		iflist = pvt->next;
+	}
+
+	/* Extract from the reverse chain. */
+	if (pvt->next) {
+		pvt->next->prev = pvt->prev;
+	} else if (ifend == pvt) {
+		/* Node is at the end of the list. */
+		ifend = pvt->prev;
+	}
+
+	/* Node is no longer in the list. */
+	pvt->prev = NULL;
+	pvt->next = NULL;
+}
+
+static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
+{
+	struct dahdi_pvt *p = pvt;
+
 	/* Remove channel from the list */
-	if (p->prev)
-		p->prev->next = p->next;
-	if (p->next)
-		p->next->prev = p->prev;
+	dahdi_iflist_extract(p);
+
 	if (p->sig_pvt) {
 		if (analog_lib_handles(p->sig, 0, 0)) {
 			analog_delete(p->sig_pvt);
@@ -4711,6 +4796,9 @@
 			sig_pri_chan_delete(p->sig_pvt);
 		}
 #endif	/* defined(HAVE_PRI) */
+	}
+	if (p->cidspill) {
+		ast_free(p->cidspill);
 	}
 	if (p->use_smdi)
 		ast_smdi_interface_unref(p->smdi_iface);
@@ -4723,63 +4811,30 @@
 	if (p->owner)
 		p->owner->tech_pvt = NULL;
 	ast_free(p);
-	*pvt = NULL;
-}
-
-static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
-{
-	int owned = 0;
-	int i = 0;
+}
+
+static void destroy_channel(struct dahdi_pvt *cur, int now)
+{
+	int i;
 
 	if (!now) {
+		/* Do not destroy the channel now if it is owned by someone. */
 		if (cur->owner) {
-			owned = 1;
-		}
-
+			return;
+		}
 		for (i = 0; i < 3; i++) {
 			if (cur->subs[i].owner) {
-				owned = 1;
-			}
-		}
-		if (!owned) {
-			if (prev) {
-				prev->next = cur->next;
-				if (prev->next)
-					prev->next->prev = prev;
-				else
-					ifend = prev;
-			} else {
-				iflist = cur->next;
-				if (iflist)
-					iflist->prev = NULL;
-				else
-					ifend = NULL;
-			}
-			destroy_dahdi_pvt(&cur);
-		}
-	} else {
-		if (prev) {
-			prev->next = cur->next;
-			if (prev->next)
-				prev->next->prev = prev;
-			else
-				ifend = prev;
-		} else {
-			iflist = cur->next;
-			if (iflist)
-				iflist->prev = NULL;
-			else
-				ifend = NULL;
-		}
-		destroy_dahdi_pvt(&cur);
-	}
-	return 0;
+				return;
+			}
+		}
+	}
+	destroy_dahdi_pvt(cur);
 }
 
 static void destroy_all_channels(void)
 {
-	int x;
-	struct dahdi_pvt *p, *pl;
+	int chan;
+	struct dahdi_pvt *p;
 
 	while (num_restart_pending) {
 		usleep(1);
@@ -4787,20 +4842,16 @@
 
 	ast_mutex_lock(&iflock);
 	/* Destroy all the interfaces and free their memory */
-	p = iflist;
-	while (p) {
-		/* Free any callerid */
-		if (p->cidspill)
-			ast_free(p->cidspill);
-		pl = p;
-		p = p->next;
-		x = pl->channel;
+	while (iflist) {
+		p = iflist;
+
+		chan = p->channel;
 #ifdef HAVE_PRI_SERVICE_MESSAGES
 		{
 			char db_chan_name[20], db_answer[5], state;
 			int why = -1;
 
-			snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, pl->span, x);
+			snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
 			if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
 				sscanf(db_answer, "%1c:%30d", &state, &why);
 			}
@@ -4811,11 +4862,9 @@
 		}
 #endif
 		/* Free associated memory */
-		if (pl)
-			destroy_dahdi_pvt(&pl);
-		ast_verb(3, "Unregistered channel %d\n", x);
-	}
-	iflist = NULL;
+		destroy_dahdi_pvt(p);
+		ast_verb(3, "Unregistered channel %d\n", chan);
+	}
 	ifcount = 0;
 	ast_mutex_unlock(&iflock);
 }
@@ -5071,8 +5120,6 @@
 	int law;
 	/*static int restore_gains(struct dahdi_pvt *p);*/
 	struct dahdi_pvt *p = ast->tech_pvt;
-	struct dahdi_pvt *tmp = NULL;
-	struct dahdi_pvt *prev = NULL;
 	struct dahdi_params par;
 
 	ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
@@ -5421,18 +5468,8 @@
 		num_restart_pending--;
 	}
 
-	tmp = iflist;
-	prev = NULL;
 	if (p->destroy) {
-		while (tmp) {
-			if (tmp == p) {
-				destroy_channel(prev, tmp, 0);
-				break;
-			} else {
-				prev = tmp;
-				tmp = tmp->next;
-			}
-		}
+		destroy_channel(p, 0);
 	}
 	ast_mutex_unlock(&iflock);
 	return 0;
@@ -9825,21 +9862,23 @@
 /* destroy a DAHDI channel, identified by its number */
 static int dahdi_destroy_channel_bynum(int channel)
 {
-	struct dahdi_pvt *tmp = NULL;
-	struct dahdi_pvt *prev = NULL;
-
-	tmp = iflist;
-	while (tmp) {
-		if (tmp->channel == channel) {
+	struct dahdi_pvt *cur;
+
+	ast_mutex_lock(&iflock);
+	for (cur = iflist; cur; cur = cur->next) {
+		if (cur->channel == channel) {
 			int x = DAHDI_FLASH;
-			ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
-			destroy_channel(prev, tmp, 1);
+
+			/* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
+			ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
+
+			destroy_channel(cur, 1);
+			ast_mutex_unlock(&iflock);
 			ast_module_unref(ast_module_info->self);
 			return RESULT_SUCCESS;
 		}
-		prev = tmp;
-		tmp = tmp->next;
-	}
+	}
+	ast_mutex_unlock(&iflock);
 	return RESULT_FAILURE;
 }
 
@@ -10108,8 +10147,7 @@
 		/* Build the stuff we're going to poll on, that is the socket of every
 		   dahdi_pvt that does not have an associated owner channel */
 		count = 0;
-		i = iflist;
-		while (i) {
+		for (i = iflist; i; i = i->next) {
 			ast_mutex_lock(&i->lock);
 			if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
 				if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
@@ -10147,7 +10185,6 @@
 				}
 			}
 			ast_mutex_unlock(&i->lock);
-			i = i->next;
 		}
 		/* Okay, now that we know what to do, release the interface lock */
 		ast_mutex_unlock(&iflock);
@@ -10172,8 +10209,7 @@
 		spoint = 0;
 		lastpass = thispass;
 		thispass = time(NULL);
-		i = iflist;
-		while (i) {
+		for (i = iflist; i; i = i->next) {
 			if (thispass != lastpass) {
 				if (!found && ((i == last) || ((i == iflist) && !last))) {
 					last = i;
@@ -10218,7 +10254,6 @@
 							handle_init_event(i, res);
 						ast_mutex_lock(&iflock);
 					}
-					i = i->next;
 					continue;
 				}
 				pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
@@ -10228,12 +10263,10 @@
 						if (!i->pri)
 #endif
 							ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
-						i = i->next;
 						continue;
 					}
 					if (!i->mwimonitor_fsk && !i->mwisendactive  && i->cid_start != CID_START_DTMF_NOALERT) {
 						ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
-						i = i->next;
 						continue;
 					}
 					res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
@@ -10317,7 +10350,6 @@
 						if (!i->pri)
 #endif
 							ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
-						i = i->next;
 						continue;
 					}
 					res = dahdi_get_event(i->subs[SUB_REAL].dfd);
@@ -10333,7 +10365,6 @@
 					ast_mutex_lock(&iflock);
 				}
 			}
-			i=i->next;
 		}
 		ast_mutex_unlock(&iflock);
 	}
@@ -10650,8 +10681,6 @@
 	int span = 0;
 	int here = 0;/*!< TRUE if the channel interface already exists. */
 	int x;
-	struct dahdi_pvt **wlist;
-	struct dahdi_pvt **wend;
 	struct analog_pvt *analog_p = NULL;
 	struct dahdi_params p;
 #ifdef HAVE_PRI
@@ -10707,21 +10736,21 @@
 				/* Allocate a DAHDI structure */
 				if (tmp->subs[SUB_REAL].dfd < 0) {
 					ast_log(LOG_ERROR, "Unable to open channel %d: %s\nhere = %d, tmp->channel = %d, channel = %d\n", channel, strerror(errno), here, tmp->channel, channel);
-					destroy_dahdi_pvt(&tmp);
+					destroy_dahdi_pvt(tmp);
 					return NULL;
 				}
 				memset(&p, 0, sizeof(p));
 				res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
 				if (res < 0) {
 					ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
-					destroy_dahdi_pvt(&tmp);
+					destroy_dahdi_pvt(tmp);
 					return NULL;
 				}
 				if (conf->is_sig_auto)
 					chan_sig = sigtype_to_signalling(p.sigtype);
 				if (p.sigtype != (chan_sig & 0x3ffff)) {
 					ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(chan_sig), sig2str(p.sigtype));
-					destroy_dahdi_pvt(&tmp);
+					destroy_dahdi_pvt(tmp);
 					return NULL;
 				}
 				tmp->law = p.curlaw;
@@ -10735,7 +10764,7 @@
 			if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
 				analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
 				if (!analog_p) {
-					destroy_dahdi_pvt(&tmp);
+					destroy_dahdi_pvt(tmp);
 					return NULL;
 				}
 				tmp->sig_pvt = analog_p;
@@ -10746,19 +10775,19 @@
 				int clear = 0;
 				if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
 					ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
-					destroy_dahdi_pvt(&tmp);
+					destroy_dahdi_pvt(tmp);
 					return NULL;
 				}
 
 				ss7 = ss7_resolve_linkset(cur_linkset);
 				if (!ss7) {
 					ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
-					destroy_dahdi_pvt(&tmp);
+					destroy_dahdi_pvt(tmp);
 					return NULL;
 				}
 				if (cur_cicbeginswith < 0) {
 					ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
-					destroy_dahdi_pvt(&tmp);
+					destroy_dahdi_pvt(tmp);
 					return NULL;
 				}
 
@@ -10786,17 +10815,17 @@
 				r2_link = dahdi_r2_get_link();
 				if (!r2_link) {
 					ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
-					destroy_dahdi_pvt(&tmp);
+					destroy_dahdi_pvt(tmp);
 					return NULL;
 				}
 				if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
 					ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
-					destroy_dahdi_pvt(&tmp);
+					destroy_dahdi_pvt(tmp);
 					return NULL;
 				}
 				if (r2_link->numchans == (sizeof(r2_link->pvts)/sizeof(r2_link->pvts[0]))) {
 					ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
-					destroy_dahdi_pvt(&tmp);
+					destroy_dahdi_pvt(tmp);
 					return NULL;
 				}
 				r2_link->pvts[r2_link->numchans++] = tmp;
@@ -10806,7 +10835,7 @@
 				if (!tmp->r2chan) {
 					openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
 					ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
-					destroy_dahdi_pvt(&tmp);
+					destroy_dahdi_pvt(tmp);
 					return NULL;
 				}
 				tmp->mfcr2 = r2_link;
@@ -10838,18 +10867,18 @@
 				offset = 0;
 				if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
 					ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
-					destroy_dahdi_pvt(&tmp);
+					destroy_dahdi_pvt(tmp);
 					return NULL;
 				}
 				if (span >= NUM_SPANS) {
 					ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
-					destroy_dahdi_pvt(&tmp);
+					destroy_dahdi_pvt(tmp);
 					return NULL;
 				} else {
 					si.spanno = 0;
 					if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
 						ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
-						destroy_dahdi_pvt(&tmp);
+						destroy_dahdi_pvt(tmp);
 						return NULL;
 					}
 					/* Store the logical span first based upon the real span */
@@ -10857,7 +10886,7 @@
 					pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
 					if (span < 0) {
 						ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
-						destroy_dahdi_pvt(&tmp);
+						destroy_dahdi_pvt(tmp);
 						return NULL;
 					}
 					myswitchtype = conf->pri.pri.switchtype;
@@ -10874,50 +10903,50 @@
 					if (!matchesdchan) {
 						if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
 							ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
-							destroy_dahdi_pvt(&tmp);
+							destroy_dahdi_pvt(tmp);
 							return NULL;
 						}
 						if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
 							ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
-							destroy_dahdi_pvt(&tmp);
+							destroy_dahdi_pvt(tmp);
 							return NULL;
 						}
 						if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
 							ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, pris[span].pri.dialplan == -1 ? "Dynamically set dialplan in ISDN" : pri_plan2str(pris[span].pri.dialplan));
-							destroy_dahdi_pvt(&tmp);
+							destroy_dahdi_pvt(tmp);
 							return NULL;
 						}
 						if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
 							ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
-							destroy_dahdi_pvt(&tmp);
+							destroy_dahdi_pvt(tmp);
 							return NULL;
 						}
 						if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
 							ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
-							destroy_dahdi_pvt(&tmp);
+							destroy_dahdi_pvt(tmp);
 							return NULL;
 						}
 						if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
 							ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
-							destroy_dahdi_pvt(&tmp);
+							destroy_dahdi_pvt(tmp);
 							return NULL;
 						}
 						if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
 							ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
-							destroy_dahdi_pvt(&tmp);
+							destroy_dahdi_pvt(tmp);
 							return NULL;
 						}
 						if (pris[span].pri.numchans >= MAX_CHANNELS) {
 							ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
 								pris[span].pri.trunkgroup);
-							destroy_dahdi_pvt(&tmp);
+							destroy_dahdi_pvt(tmp);
 							return NULL;
 						}
 
 						ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
 						pchan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
 						if (!pchan) {
-							destroy_dahdi_pvt(&tmp);
+							destroy_dahdi_pvt(tmp);
 							return NULL;
 						}
 						tmp->sig_pvt = pchan;
@@ -10959,7 +10988,7 @@
 						}
 					} else {
 						ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
-						destroy_dahdi_pvt(&tmp);
+						destroy_dahdi_pvt(tmp);
 						return NULL;
 					}
 				}
@@ -11032,7 +11061,7 @@
 			res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
 			if (res < 0) {
 				ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
-				destroy_dahdi_pvt(&tmp);
+				destroy_dahdi_pvt(tmp);
 				return NULL;
 			}
 		}
@@ -11214,7 +11243,7 @@
 			memset(&si, 0, sizeof(si));
 			if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
 				ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
-				destroy_dahdi_pvt(&tmp);
+				destroy_dahdi_pvt(tmp);
 				return NULL;
 			}
 #endif
@@ -11344,51 +11373,7 @@
 	}
 	if (tmp && !here) {
 		/* Add the new channel interface to the sorted channel interface list. */
-		wlist = &iflist;
-		wend = &ifend;
-
-		/* nothing on the iflist */
-		if (!*wlist) {
-			*wlist = tmp;
-			tmp->prev = NULL;
-			tmp->next = NULL;
-			*wend = tmp;
-		} else {
-			/* at least one member on the iflist */
-			struct dahdi_pvt *working = *wlist;
-
-			/* check if we maybe have to put it on the begining */
-			if (working->channel > tmp->channel) {
-				tmp->next = *wlist;
-				tmp->prev = NULL;
-				(*wlist)->prev = tmp;
-				*wlist = tmp;
-			} else {
-			/* go through all the members and put the member in the right place */
-				while (working) {
-					/* in the middle */
-					if (working->next) {
-						if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
-							tmp->next = working->next;
-							tmp->prev = working;
-							working->next->prev = tmp;
-							working->next = tmp;
-							break;
-						}
-					} else {
-					/* the last */
-						if (working->channel < tmp->channel) {
-							working->next = tmp;
-							tmp->next = NULL;
-							tmp->prev = working;
-							*wend = tmp;
-							break;
-						}
-					}
-					working = working->next;
-				}
-			}
-		}
+		dahdi_iflist_insert(tmp);
 	}
 	return tmp;
 }
@@ -11466,33 +11451,33 @@
 	struct dahdi_bufferinfo bi;
 	int res;
 
-	if ((p = ast_malloc(sizeof(*p)))) {
-		memcpy(p, src, sizeof(struct dahdi_pvt));
-		ast_mutex_init(&p->lock);
-		p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
-		if (p->subs[SUB_REAL].dfd < 0) {
-			ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
-			destroy_dahdi_pvt(&p);
-			return NULL;
-		}
-		res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
-		if (!res) {
-			bi.txbufpolicy = src->buf_policy;
-			bi.rxbufpolicy = src->buf_policy;
-			bi.numbufs = src->buf_no;
-			res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
-			if (res < 0) {
-				ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
-			}
-		} else
-			ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
-	}
+	p = ast_malloc(sizeof(*p));
+	if (!p) {
+		return NULL;
+	}
+	*p = *src;
+	p->next = NULL;
+	p->prev = NULL;
+	ast_mutex_init(&p->lock);
+	p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
+	if (p->subs[SUB_REAL].dfd < 0) {
+		ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
+		destroy_dahdi_pvt(p);
+		return NULL;
+	}
+	res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
+	if (!res) {
+		bi.txbufpolicy = src->buf_policy;
+		bi.rxbufpolicy = src->buf_policy;
+		bi.numbufs = src->buf_no;
+		res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
+		if (res < 0) {
+			ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
+		}
+	} else
+		ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
 	p->destroy = 1;
-	p->next = iflist;
-	p->prev = NULL;
-	iflist = p;
-	if (iflist->next)
-		iflist->next->prev = p;
+	dahdi_iflist_insert(p);
 	return p;
 }
 
@@ -11511,8 +11496,7 @@
 	char opt=0;
 	int res=0, y=0;
 	int backwards = 0;
-	struct dahdi_pvt *exitpvt, *start, *end;
-	ast_mutex_t *lock;
+	struct dahdi_pvt *exitpvt;
 	int channelmatched = 0;
 	int groupmatched = 0;
 
@@ -11532,10 +11516,6 @@
 	 * d - Force bearer capability for ISDN/SS7 call to digital.
 	 */
 
-	/* Assume we're locking the iflock */
-	lock = &iflock;
-	start = iflist;
-	end = ifend;
 	if (data) {
 		dest = ast_strdupa((char *)data);
 	} else {
@@ -11553,6 +11533,10 @@
 			return NULL;
 		}
 		groupmatch = ((ast_group_t) 1 << x);
+
+		/* Lock the interface list */
+		ast_mutex_lock(&iflock);
+
 		if (toupper(dest[0]) == 'G') {
 			if (dest[0] == 'G') {
 				backwards = 1;
@@ -11577,7 +11561,6 @@
 
 		stringp = dest;
 		s = strsep(&stringp, "/");
-		p = iflist;
 		if (!strcasecmp(s, "pseudo")) {
 			/* Special case for pseudo */
 			x = CHAN_PSEUDO;
@@ -11589,9 +11572,13 @@
 		} else {
 			channelmatch = x;
 		}
+
+		/* Lock the interface list */
+		ast_mutex_lock(&iflock);
+
+		p = iflist;
 	}
 	/* Search for an unowned channel */
-	ast_mutex_lock(lock);
 	exitpvt = p;
 	while (p && !tmp) {
 		if (roundrobin)
@@ -11665,17 +11652,17 @@
 		if (backwards) {
 			p = p->prev;
 			if (!p)
-				p = end;
+				p = ifend;
 		} else {
 			p = p->next;
 			if (!p)
-				p = start;
+				p = iflist;
 		}
 		/* stop when you roll to the one that we started from */
 		if (p == exitpvt)
 			break;
 	}
-	ast_mutex_unlock(lock);
+	ast_mutex_unlock(&iflock);
 	restart_monitor();
 	if (callwait)
 		*cause = AST_CAUSE_BUSY;
@@ -12905,12 +12892,8 @@
 	char *c;
 	char state;
 	char db_chan_name[20], db_answer[5];
-	struct dahdi_pvt *start, *tmp = NULL;
-	struct dahdi_pri *pri = NULL;
-	ast_mutex_t *lock;
-
-	lock = &iflock;
-	start = iflist;
+	struct dahdi_pvt *tmp;
+	struct dahdi_pri *pri;
 
 	if (a->argc < 5 || a->argc > 6)
 		return CLI_SHOWUSAGE;
@@ -12919,15 +12902,14 @@
 			return CLI_SHOWUSAGE;
 		if ((trunkgroup < 1) || (channel < 1))
 			return CLI_SHOWUSAGE;
+		pri = NULL;
 		for (x=0;x<NUM_SPANS;x++) {
 			if (pris[x].pri.trunkgroup == trunkgroup) {
 				pri = pris + x;
 				break;
 			}
 		}
-		if (pri) {
-			lock = &pri->pri.lock;
-		} else {
+		if (!pri) {
 			ast_cli(fd, "No such trunk group %d\n", trunkgroup);
 			return CLI_FAILURE;
 		}
@@ -12942,19 +12924,29 @@
 		for (y = 0; y < NUM_DCHANS; y++) {
 			if (pris[x].dchannels[y] == channel) {
 				pri = pris + x;
-				pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
+				if (pri->pri.enable_service_message_support) {
+					ast_mutex_lock(&pri->pri.lock);
+					pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
+					ast_mutex_unlock(&pri->pri.lock);
+				} else {
+					ast_cli(fd,
+						"\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
+						"\tNote only 4ESS and 5ESS switch types are supported.\n\n");
+				}
 				return CLI_SUCCESS;
 			}
 		}
 	}
 
 	/* or servicing a B-Channel */
-	ast_mutex_lock(lock);
-	tmp = start;
-	while (tmp) {
+	ast_mutex_lock(&iflock);
+	for (tmp = iflist; tmp; tmp = tmp->next) {
 		if (tmp->pri && tmp->channel == channel) {
 			if (!tmp->pri->enable_service_message_support) {
-				ast_cli(fd, "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n\tNote only 4ESS and 5ESS switch types are supported.\n\n");
+				ast_mutex_unlock(&iflock);
+				ast_cli(fd,
+					"\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
+					"\tNote only 4ESS and 5ESS switch types are supported.\n\n");
 				return CLI_SUCCESS;
 			}
 			why = -1;
@@ -12988,14 +12980,16 @@
 			/* case 4:  -- shutdown */
 			default:
 				ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
-			}
+				break;
+			}
+			ast_mutex_unlock(&iflock);
+			ast_mutex_lock(&tmp->pri->lock);
 			pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
-			ast_mutex_unlock(lock);
+			ast_mutex_unlock(&tmp->pri->lock);
 			return CLI_SUCCESS;
 		}
-		tmp = tmp->next;
-	}
-	ast_mutex_unlock(lock);
+	}
+	ast_mutex_unlock(&iflock);
 
 	ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
 	return CLI_FAILURE;
@@ -13615,10 +13609,14 @@
 		int x = DAHDI_FLASH;
 		ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
 
+		ast_mutex_lock(&iflock);
 		for (p = iflist; p; p = p->next) {
-			if (p->owner)
-				ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
-			}
+			if (p->owner) {
+				/* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
+				ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
+			}
+		}
+		ast_mutex_unlock(&iflock);
 		ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
 	}
 
@@ -13716,8 +13714,6 @@
 	char tmps[20] = "";
 	char statestr[20] = "";
 	char blockstr[20] = "";
-	ast_mutex_t *lock;
-	struct dahdi_pvt *start;
 
 	switch (cmd) {
 	case CLI_INIT:
@@ -13731,9 +13727,6 @@
 		return NULL;
 	}
 
-	lock = &iflock;
-	start = iflist;
-
 	/* syntax: dahdi show channels [ group <group> | context <context> ] */
 
 	if (!((a->argc == 3) || (a->argc == 5)))
@@ -13751,22 +13744,18 @@
 		}
 	}
 
-	ast_mutex_lock(lock);
 	ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
-
-	tmp = start;
-	while (tmp) {
+	ast_mutex_lock(&iflock);
+	for (tmp = iflist; tmp; tmp = tmp->next) {
 		if (filtertype) {
 			switch(filtertype) {
 			case 1: /* dahdi show channels group <group> */
 				if (!(tmp->group & targetnum)) {
-					tmp = tmp->next;
 					continue;
 				}
 				break;
 			case 2: /* dahdi show channels context <context> */
 				if (strcasecmp(tmp->context, a->argv[4])) {
-					tmp = tmp->next;
 					continue;
 				}
 				break;
@@ -13794,9 +13783,8 @@
 		snprintf(statestr, sizeof(statestr), "%s", "In Service");
 
 		ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
-		tmp = tmp->next;
-	}
-	ast_mutex_unlock(lock);
+	}
+	ast_mutex_unlock(&iflock);
 	return CLI_SUCCESS;
 #undef FORMAT
 #undef FORMAT2
@@ -13809,8 +13797,6 @@
 	struct dahdi_confinfo ci;
 	struct dahdi_params ps;
 	int x;
-	ast_mutex_t *lock;
-	struct dahdi_pvt *start;
 
 	switch (cmd) {
 	case CLI_INIT:
@@ -13823,17 +13809,13 @@
 		return NULL;
 	}
 
-	lock = &iflock;
-	start = iflist;
-
 	if (a->argc != 4)
 		return CLI_SHOWUSAGE;
 
 	channel = atoi(a->argv[3]);
 
-	ast_mutex_lock(lock);
-	tmp = start;
-	while (tmp) {
+	ast_mutex_lock(&iflock);
+	for (tmp = iflist; tmp; tmp = tmp->next) {
 		if (tmp->channel == channel) {
 			ast_cli(a->fd, "Channel: %d\n", tmp->channel);
 			ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
@@ -13969,14 +13951,13 @@
 					ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
 				}
 			}
-			ast_mutex_unlock(lock);
+			ast_mutex_unlock(&iflock);
 			return CLI_SUCCESS;
 		}
-		tmp = tmp->next;
-	}
+	}
+	ast_mutex_unlock(&iflock);
 
 	ast_cli(a->fd, "Unable to find given channel %d\n", channel);
-	ast_mutex_unlock(lock);
 	return CLI_FAILURE;
 }
 
@@ -14207,7 +14188,6 @@
 	float gain;
 	int tx;
 	int res;
-	ast_mutex_t *lock;
 	struct dahdi_pvt *tmp = NULL;
 
 	switch (cmd) {
@@ -14226,8 +14206,6 @@
 		return NULL;
 	}
 
-	lock = &iflock;
-
 	if (a->argc != 6)
 		return CLI_SHOWUSAGE;
 
@@ -14241,7 +14219,7 @@
 	channel = atoi(a->argv[4]);
 	gain = atof(a->argv[5]);
 
-	ast_mutex_lock(lock);
+	ast_mutex_lock(&iflock);
 	for (tmp = iflist; tmp; tmp = tmp->next) {
 
 		if (tmp->channel != channel)
@@ -14257,7 +14235,7 @@
 
 		if (res) {
 			ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
-			ast_mutex_unlock(lock);
+			ast_mutex_unlock(&iflock);
 			return CLI_FAILURE;
 		}
 
@@ -14265,7 +14243,7 @@
 			tx ? "tx" : "rx", gain, channel);
 		break;
 	}
-	ast_mutex_unlock(lock);
+	ast_mutex_unlock(&iflock);
 
 	if (tmp)
 		return CLI_SUCCESS;
@@ -14366,13 +14344,15 @@
 }
 static struct dahdi_pvt *find_channel(int channel)
 {
-	struct dahdi_pvt *p = iflist;
-	while (p) {
+	struct dahdi_pvt *p;
+
+	ast_mutex_lock(&iflock);
+	for (p = iflist; p; p = p->next) {
 		if (p->channel == channel) {
 			break;
 		}
-		p = p->next;
-	}
+	}
+	ast_mutex_unlock(&iflock);
 	return p;
 }
 
@@ -14502,15 +14482,15 @@
 
 	ast_mutex_lock(&iflock);
 
-	tmp = iflist;
-	while (tmp) {
+	for (tmp = iflist; tmp; tmp = tmp->next) {
 		if (tmp->channel > 0) {
-			int alm = get_alarms(tmp);
+			int alm;
 
 			/* If a specific channel is queried for, only deliver status for that channel */
 			if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
 				continue;
 
+			alm = get_alarms(tmp);
 			channels++;
 			if (tmp->owner) {
 				/* Add data if we have a current call */
@@ -14553,8 +14533,6 @@
 					alarm2str(alm), idText);
 			}
 		}
-
-		tmp = tmp->next;
 	}
 
 	ast_mutex_unlock(&iflock);
@@ -15052,15 +15030,15 @@
 	ast_manager_unregister("DAHDIShowChannels");
 	ast_manager_unregister("DAHDIRestart");
 	ast_channel_unregister(&dahdi_tech);
+
+	/* Hangup all interfaces if they have an owner */
 	ast_mutex_lock(&iflock);
-	/* Hangup all interfaces if they have an owner */
-	p = iflist;
-	while (p) {
+	for (p = iflist; p; p = p->next) {
 		if (p->owner)
 			ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
-		p = p->next;
 	}
 	ast_mutex_unlock(&iflock);
+
 	ast_mutex_lock(&monlock);
 	if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
 		pthread_cancel(monitor_thread);




More information about the asterisk-commits mailing list