[Asterisk-cvs] asterisk/channels chan_vpb.c,1.21,1.22

bkramer at lists.digium.com bkramer at lists.digium.com
Thu May 20 22:38:13 CDT 2004


Update of /usr/cvsroot/asterisk/channels
In directory mongoose.digium.com:/tmp/cvs-serv9288

Modified Files:
	chan_vpb.c 
Log Message:
/ updated locking


Index: chan_vpb.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_vpb.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- chan_vpb.c	20 May 2004 01:59:03 -0000	1.21
+++ chan_vpb.c	21 May 2004 02:51:05 -0000	1.22
@@ -179,7 +179,9 @@
 static struct vpb_pvt {
 
 	ast_mutex_t owner_lock;			/* Protect blocks that expect ownership to remain the same */
-	struct ast_channel *owner;		/* Channel we belong to, possibly NULL */
+	struct ast_channel *owner;		/* Channel who owns us, possibly NULL */
+
+	int golock;				/* Got owner lock ? */
 
 	int mode;				/* fxo/imediate/dialtone*/
 	int handle;				/* Handle for vpb interface */
@@ -257,6 +259,9 @@
 		return -2;
 	#endif
 
+	ast_mutex_lock(&p0->lock);
+	ast_mutex_lock(&p1->lock);
+
 	/* Bridge channels, check if we can.  I believe we always can, so find a slot.*/
 
 	ast_mutex_lock(&bridge_lock); {
@@ -278,6 +283,8 @@
 
 	if (i == max_bridges) {
 		ast_log(LOG_WARNING, "Failed to bridge %s and %s!\n", c0->name, c1->name);
+		ast_mutex_unlock(&p0->lock);
+		ast_mutex_unlock(&p1->lock);
 		return -2;
 	} else {
 		/* Set bridge pointers. You don't want to take these locks while holding bridge lock.*/
@@ -350,18 +357,15 @@
 		pthread_cond_destroy(&bridges[i].cond);	
 	} ast_mutex_unlock(&bridge_lock); 
 
-	ast_mutex_lock(&p0->lock); {
-		p0->bridge = NULL;
-	} ast_mutex_unlock(&p0->lock);
-
-	ast_mutex_lock(&p1->lock); {
-		p1->bridge = NULL;
-	} ast_mutex_unlock(&p1->lock);
+	p0->bridge = NULL;
+	p1->bridge = NULL;
 
 
 	if (option_verbose>1) 
 		ast_verbose(VERBOSE_PREFIX_2 "Bridging call done with [%s, %s] => %d\n", c0->name, c1->name, res);
 
+	ast_mutex_unlock(&p0->lock);
+	ast_mutex_unlock(&p1->lock);
 	return (res==VPB_OK)?0:-1;
 }
 
@@ -479,7 +483,7 @@
 	int endbridge = 0;
 
 	if (option_verbose > 3) 
-		ast_verbose(VERBOSE_PREFIX_4 "%s: handle_owned got event: [%d=>%d]\n",
+		ast_verbose(VERBOSE_PREFIX_4 "%s: handle_owned: got event: [%d=>%d]\n",
 			p->dev, e->type, e->data);
 
 	f.src = type;
@@ -605,7 +609,7 @@
 	}
 
 	if (option_verbose > 3) 
-		ast_verbose(VERBOSE_PREFIX_4 "%s: handle_owned: putting frame: [%d=>%d], bridge=%p\n",
+		ast_verbose(VERBOSE_PREFIX_4 "%s: handle_owned: putting frame type[%d]subclass[%d], bridge=%p\n",
 			p->dev, f.frametype, f.subclass, (void *)p->bridge);
 
 	ast_mutex_lock(&p->lock); {
@@ -658,7 +662,7 @@
 			ast_queue_frame(p->owner, &f);
 			ast_mutex_unlock(&p->owner->lock);
 		} else {
-			ast_verbose("%s: Missed event %d/%d \n",
+			ast_verbose("%s: handled_owned: Missed event %d/%d \n",
 				p->dev,f.frametype, f.subclass);
 		}
 	}
@@ -673,7 +677,7 @@
 	if (option_verbose > 3) {
 		char str[VPB_MAX_STR];
 		vpb_translate_event(e, str);
-		ast_verbose(VERBOSE_PREFIX_4 "%s: In not owned, mode=%d, event[%d][%s]=[%d]\n",
+		ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: mode=%d, event[%d][%s]=[%d]\n",
 			p->dev, p->mode, e->type,str, e->data);
 	}
 
@@ -692,7 +696,7 @@
 			if (p->mode == MODE_IMMEDIATE) 
 				vpb_new(p,AST_STATE_RING, p->context);
 			else {
-				ast_verbose(VERBOSE_PREFIX_4 "%s: In not owned, playing dialtone\n",p->dev);
+				ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: playing dialtone\n",p->dev);
 				playtone(p->handle, &Dialtone);
 				p->wantdtmf = 1;
 				p->ext[0] = 0;	/* Just to be sure & paranoid.*/
@@ -720,7 +724,7 @@
 				}
 				*/
 			} else {
-				ast_verbose(VERBOSE_PREFIX_4 "%s: Got a DIALEND when not really expected\n",p->dev);
+				ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: Got a DIALEND when not really expected\n",p->dev);
 			}
 			break;
 
@@ -750,7 +754,7 @@
 					vpb_new(p,AST_STATE_RING, "default");	      
 				} else if (!ast_canmatch_extension(NULL, "default", p->ext, 1, p->callerid)) {
 					if (option_verbose > 3) {
-						ast_verbose(VERBOSE_PREFIX_4 "%s: can't match anything in %s or default\n",
+						ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: can't match anything in %s or default\n",
 							 p->dev, p->context);
 					}
 					playtone(p->handle, &Busytone);
@@ -766,7 +770,7 @@
 	}
 
 	if (option_verbose > 3) 
-		ast_verbose(VERBOSE_PREFIX_4 "%s: Done not owned, mode=%d, [%d=>%d]\n",
+		ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: mode=%d, [%d=>%d]\n",
 			p->dev, p->mode, e->type, e->data);
 
 	return 0;
@@ -860,15 +864,34 @@
 			ast_verbose( VERBOSE_PREFIX_4 "%s: Flushing event [%d]=>%s\n",p->dev,je.type,str);
 		}
 
+		/* Check for ownership and locks */
+		if ((p->owner)&&(!p->golock)){
+			/* Need to get owner lock */
+			/* Safely grab both p->lock and p->owner->lock so that there
+			cannot be a race with something from the other side */
+			/*
+			ast_mutex_lock(&p->lock);
+			while(ast_mutex_trylock(&p->owner->lock)) {
+				ast_mutex_unlock(&p->lock);
+				usleep(1);
+				ast_mutex_lock(&p->lock);
+				if (!p->owner)
+					break;
+			}
+			if (p->owner)
+				p->golock=1;
+			*/
+		}
 		/* Two scenarios: Are you owned or not. */
-		ast_mutex_lock(&p->owner_lock);
 		if (p->owner) {
 			monitor_handle_owned(p, &e);
-			ast_mutex_unlock(&p->owner_lock);
 		} else {
-			ast_mutex_unlock(&p->owner_lock);
 			monitor_handle_notowned(p, &e);
 		}
+		if ((!p->owner)&&(p->golock)){
+			ast_mutex_unlock(&p->owner->lock);
+			ast_mutex_unlock(&p->lock);
+		}
 
 	}
 
@@ -1026,7 +1049,8 @@
 	ast_mutex_init(&tmp->record_lock);
 	ast_mutex_init(&tmp->play_lock);
 	ast_mutex_init(&tmp->play_dtmf_lock);
-	ast_mutex_init(&tmp->owner_lock);
+	
+	tmp->golock=0;
 
 	tmp->busy_timer_id = vpb_timer_get_unique_timer_id();
 	vpb_timer_open(&tmp->busy_timer, tmp->handle, tmp->busy_timer_id, TIMER_PERIOD_BUSY);
@@ -1062,8 +1086,12 @@
 	int res = 0;
 
 	if (option_verbose > 3)
-		ast_verbose(VERBOSE_PREFIX_4 " vpb indicate on %s with %d\n", p->dev, condition);
+		ast_verbose(VERBOSE_PREFIX_4 "%s: vpb indicate [%d]\n", p->dev, condition);
+	if (ast->_state != AST_STATE_UP) {
+		return res;
+	}
 
+	ast_mutex_lock(&p->lock);
 	switch(condition) {
 		case AST_CONTROL_BUSY:
 		case AST_CONTROL_CONGESTION:
@@ -1091,6 +1119,7 @@
 			res = 0;
 			break;
 	}
+	ast_mutex_unlock(&p->lock);
 	return res;
 }
 
@@ -1099,8 +1128,7 @@
 	struct vpb_pvt *p = (struct vpb_pvt *)newchan->pvt->pvt;
 
 	ast_mutex_lock(&p->lock);
-	ast_log(LOG_DEBUG, 
-		"New owner for channel %s is %s\n", p->dev, newchan->name);
+	ast_log(LOG_DEBUG, "New owner for channel %s is %s\n", p->dev, newchan->name);
 
 	if (p->owner == oldchan) {
 		p->owner = newchan;
@@ -1118,13 +1146,20 @@
 	struct vpb_pvt *p = (struct vpb_pvt *)ast->pvt->pvt;
 	char s[2];
 
+	ast_mutex_lock(&p->lock);
+
+
 	s[0] = digit;
 	s[1] = '\0';
 
+	if (option_verbose > 3)
+		ast_verbose(VERBOSE_PREFIX_4 "%s: play digit[%s]\n", p->dev, s);
+
 	ast_mutex_lock(&p->play_dtmf_lock);
 	strncat(p->play_dtmf,s,sizeof(*p->play_dtmf));
 	ast_mutex_unlock(&p->play_dtmf_lock);
 
+	ast_mutex_unlock(&p->lock);
 	return 0;
 }
 
@@ -1135,6 +1170,8 @@
 	char *s = strrchr(dest, '/');
 	char dialstring[254];
 
+	ast_mutex_lock(&p->lock);
+
 	if (s)
 		s = s + 1;
 	else
@@ -1146,10 +1183,12 @@
 		else if ((dialstring[i] == 'f') || (dialstring[i] == 'F'))
 			dialstring[i] = '&';
 	}	
+	if (option_verbose > 3)
+		ast_verbose(VERBOSE_PREFIX_4 "%s: starting call\n", p->dev);
 
 	if (ast->_state != AST_STATE_DOWN && ast->_state != AST_STATE_RESERVED) {
-		ast_log(LOG_WARNING, "vpb_call on %s neither down nor reserved!\n", 
-		ast->name);
+		ast_log(LOG_WARNING, "vpb_call on %s neither down nor reserved!\n", ast->name);
+		ast_mutex_unlock(&p->lock);
 		return -1;
 	}
 	if (p->mode != MODE_FXO)  /* Station port, ring it. */
@@ -1173,16 +1212,16 @@
 		vpb_set_call(p->handle, &call);
 
 		if (option_verbose > 1)
-			ast_verbose(VERBOSE_PREFIX_2 "Calling %s on %s \n", dialstring, ast->name); 
+			ast_verbose(VERBOSE_PREFIX_2 "%s: Calling %s on %s \n",p->dev, dialstring, ast->name); 
 
 		if (option_verbose > 2) {
 			int j;
-			ast_verbose(VERBOSE_PREFIX_2 "Dial parms for %s %d/%dms/%dms/%dms/%dms\n"
+			ast_verbose(VERBOSE_PREFIX_2 "%s: Dial parms for %s %d/%dms/%dms/%dms/%dms\n", p->dev
 				, ast->name, call.dialtones, call.dialtone_timeout
 				, call.ringback_timeout, call.inter_ringback_timeout
 				, call.answer_timeout );
 			for( j=0; !call.tone_map[j].terminate; j++ )
-				ast_verbose(VERBOSE_PREFIX_2 "Dial parms for %s tone %d->%d\n", 
+				ast_verbose(VERBOSE_PREFIX_2 "%s: Dial parms for %s tone %d->%d\n", p->dev,
 					ast->name, call.tone_map[j].tone_id, call.tone_map[j].call_id); 
 		}
 
@@ -1204,28 +1243,33 @@
 	}
 
 	if (option_verbose > 2)
-		ast_verbose(VERBOSE_PREFIX_3 " VPB Calling %s [t=%d] on %s returned %d\n", s, timeout, ast->name, res); 
+		ast_verbose(VERBOSE_PREFIX_3 "%s: VPB Calling %s [t=%d] on %s returned %d\n",p->dev , s, timeout, ast->name, res); 
 	if (res == 0) {
 		ast_setstate(ast, AST_STATE_RINGING);
 		ast_queue_control(ast,AST_CONTROL_RINGING);		
 	}
 
-	pthread_create(&p->readthread, NULL, do_chanreads, (void *)p);
+	if (!p->readthread){
+		pthread_create(&p->readthread, NULL, do_chanreads, (void *)p);
+	}
 
+	ast_mutex_unlock(&p->lock);
 	return res;
 }
 
 static int vpb_hangup(struct ast_channel *ast)
 {
-	struct vpb_pvt *p;
+	struct vpb_pvt *p = (struct vpb_pvt *)ast->pvt->pvt;
 	VPB_EVENT je;
 	char str[VPB_MAX_STR];
 
+	ast_mutex_lock(&p->lock);
 	if (option_verbose > 1) 
 		ast_verbose(VERBOSE_PREFIX_2 "%s: Hangup requested\n", ast->name);
 
 	if (!ast->pvt || !ast->pvt->pvt) {
 		ast_log(LOG_WARNING, "%s: channel not connected?\n", ast->name);
+		ast_mutex_unlock(&p->lock);
 		return 0;
 	}
 
@@ -1233,7 +1277,6 @@
 		ast_verbose( VERBOSE_PREFIX_4 "%s: Setting state down\n",ast->name);
 	ast_setstate(ast,AST_STATE_DOWN);
 
-	p = (struct vpb_pvt *)ast->pvt->pvt;
 
 	/* Stop record */
 	p->stopreads = 1;
@@ -1287,10 +1330,8 @@
 	p->ext[0]  = 0;
 	p->dialtone = 0;
 
-	ast_mutex_lock(&p->owner_lock); {
-		p->owner = NULL;
-		ast->pvt->pvt = NULL; 	 
-	} ast_mutex_unlock(&p->owner_lock);
+	p->owner = NULL;
+	ast->pvt->pvt=NULL;
 
 	ast_mutex_lock(&usecnt_lock); {
 		usecnt--;
@@ -1301,6 +1342,7 @@
 		ast_verbose(VERBOSE_PREFIX_2 "%s: Hangup complete\n", ast->name);
 
 	restart_monitor();
+	ast_mutex_unlock(&p->lock);
 	return 0;
 }
 
@@ -1309,6 +1351,10 @@
 	struct vpb_pvt *p = (struct vpb_pvt *)ast->pvt->pvt;
 	VPB_EVENT je;
 	int ret;
+	ast_mutex_lock(&p->lock);
+
+	if (option_verbose > 3)
+			ast_verbose(VERBOSE_PREFIX_4 "%s: Answering channel\n",p->dev);
 
 	if (ast->_state != AST_STATE_UP) {
 		if (p->mode == MODE_FXO){
@@ -1318,7 +1364,7 @@
 			ret = vpb_get_event_ch_async(p->handle,&je);
 			if ((ret == VPB_OK)&&(je.type != VPB_DROP)){
 				if (option_verbose > 3){
-						ast_verbose(VERBOSE_PREFIX_4 "Answer collected a wrong event!!\n");
+						ast_verbose(VERBOSE_PREFIX_4 "%s: Answer collected a wrong event!!\n",p->dev);
 				}
 				vpb_put_event(&je);
 			}
@@ -1326,7 +1372,7 @@
 		ast_setstate(ast, AST_STATE_UP);
 
 		if(option_verbose>1) 
-			ast_verbose( VERBOSE_PREFIX_2 "Answered call from %s on %s [%s]\n", 
+			ast_verbose( VERBOSE_PREFIX_2 "%s: Answered call from %s on %s [%s]\n", p->dev,
 					p->owner->callerid, ast->name,(p->mode == MODE_FXO)?"FXO":"FXS");
 
 		ast->rings = 0;
@@ -1334,13 +1380,14 @@
 			pthread_create(&p->readthread, NULL, do_chanreads, (void *)p);
 		} else {
 			if(option_verbose>3) 
-				ast_verbose(VERBOSE_PREFIX_4 "Record thread already running!!\n");
+				ast_verbose(VERBOSE_PREFIX_4 "%s: Record thread already running!!\n",p->dev);
 		}
 	} else {
 		if(option_verbose>3) {
-			ast_verbose(VERBOSE_PREFIX_4 "Answered state is up\n");
+			ast_verbose(VERBOSE_PREFIX_4 "%s: Answered state is up\n",p->dev);
 		}
 	}
+	ast_mutex_unlock(&p->lock);
 	return 0;
 }
 
@@ -1405,15 +1452,20 @@
 {
 	struct vpb_pvt *p = (struct vpb_pvt *)ast->pvt->pvt; 
 	int res = 0, fmt = 0;
+	ast_mutex_lock(&p->lock);
+	if(option_verbose>4) 
+		ast_verbose( VERBOSE_PREFIX_4 "%s: Writing to channel\n", p->dev);
 
 	if (frame->frametype != AST_FRAME_VOICE) {
 		if(option_verbose>3) 
 			ast_verbose( VERBOSE_PREFIX_4 "%s: Don't know how to handle from type %d\n", ast->name, frame->frametype);
+		ast_mutex_unlock(&p->lock);
 		return 0;
 	} else if (ast->_state != AST_STATE_UP) {
 		if(option_verbose>3) 
-			ast_verbose( VERBOSE_PREFIX_4 "%s: Writing frame type [%d,%d] on chan %s not up\n",ast->name, frame->frametype, frame->subclass, ast->name);
+			ast_verbose( VERBOSE_PREFIX_4 "%s: Attempt to Write frame type[%d]subclass[%d] on not up chan\n",ast->name, frame->frametype, frame->subclass);
 		p->lastoutput = -1;
+		ast_mutex_unlock(&p->lock);
 		return 0;
 	}
 
@@ -1449,6 +1501,7 @@
 	}
 
 	ast_mutex_unlock(&p->play_lock);
+	ast_mutex_unlock(&p->lock);
 	return 0;
 }
 
@@ -1470,12 +1523,18 @@
 	fr->offset = AST_FRIENDLY_OFFSET;
 	memset(p->buf, 0, sizeof p->buf);
 
+	if (option_verbose > 4) {
+		ast_verbose("%s: chanreads: starting thread\n", p->dev);
+	}  
 	ast_mutex_lock(&p->record_lock);
 
 	p->stopreads = 0; 
 	while (!p->stopreads && p->owner) {
 
 		ast_mutex_lock(&p->lock); {
+			if (option_verbose > 4) {
+				ast_verbose("%s: chanreads: Checking bridge \n", p->dev);
+			}  
 			if (p->bridge) {
 				if (p->bridge->c0 == p->owner && (p->bridge->flags & AST_BRIDGE_REC_CHANNEL_0))
 					bridgerec = 1;
@@ -1489,6 +1548,9 @@
 		} ast_mutex_unlock(&p->lock);
 
 		if ( (p->owner->_state != AST_STATE_UP) || !bridgerec) {
+			if (option_verbose > 4) {
+				ast_verbose("%s: chanreads: owner not up[%d] or no bridgerec[%d]\n", p->dev,p->owner->_state,bridgerec);
+			}  
 			vpb_sleep(10);
 			continue;
 		}
@@ -1512,6 +1574,9 @@
 
 		// Play DTMF digits here to avoid problem you get if playing a digit during
 		// a record operation
+		if (option_verbose > 4) {
+			ast_verbose("%s: chanreads: Checking dtmf's \n", p->dev);
+		}  
 		ast_mutex_lock(&p->play_dtmf_lock);
 		if( p->play_dtmf[0] ) {
 			// Try to ignore DTMF event we get after playing digit
@@ -1552,10 +1617,19 @@
 		p->lastinput = fmt;
 
 		/* Read only if up and not bridged, or a bridge for which we can read. */
+		if (option_verbose > 4) {
+			ast_verbose("%s: chanreads: getting buffer!\n", p->dev);
+		}  
 		if( (res = vpb_record_buf_sync(p->handle, readbuf, readlen) ) == VPB_OK ) {
+			if (option_verbose > 4) {
+				ast_verbose("%s: chanreads: got buffer!\n", p->dev);
+			}  
 			// Apply extra gain !
 			if( p->rxswgain > MAX_VPB_GAIN )
 				gain_vector(p->rxswgain - MAX_VPB_GAIN , (short*)readbuf, readlen/sizeof(short));
+			if (option_verbose > 4) {
+				ast_verbose("%s: chanreads: applied gain\n", p->dev);
+			}  
 
 			fr->subclass = afmt;
 			fr->data = readbuf;
@@ -1564,10 +1638,25 @@
 			// Using trylock here to prevent deadlock when channel is hungup
 			// (ast_hangup() immediately gets lock)
 			if (p->owner && !p->stopreads ) {
-				ast_queue_frame(p->owner, fr);
+				if (option_verbose > 4) {
+					ast_verbose("%s: chanreads: queueing buffer on frame (state[%d])\n", p->dev,p->owner->_state);
+				}  
+				
+				if (ast_mutex_trylock(&p->owner->lock)==0)  {
+					ast_queue_frame(p->owner, fr);
+					ast_mutex_unlock(&p->owner->lock);
+				} else {
+					if (option_verbose > 3) 
+						ast_verbose("%s: Couldnt get lock on owner channel to send frame!\n", p->dev);
+				}
 				if (option_verbose > 4) {
 					short * data = (short*)readbuf;
-					ast_verbose("%s: Read channel (codec=%d) %d %d\n", p->dev, fmt, data[0], data[1] );     
+					ast_verbose("%s: Read channel (codec=%d) %d %d\n", p->dev, fmt, data[0], data[1] );
+				}  
+			}
+			else {
+				if (option_verbose > 4) {
+					ast_verbose("%s: p->stopreads[%d] p->owner[%p]\n", p->dev, p->stopreads,(void *)p->owner);
 				}  
 			}
 		} else {
@@ -1611,7 +1700,7 @@
 		if (state == AST_STATE_RING)
 			tmp->rings = 1;
 		tmp->pvt->pvt = i;
-		/* set Call backs */
+		/* set call backs */
 		tmp->pvt->send_digit = vpb_digit;
 		tmp->pvt->call = vpb_call;
 		tmp->pvt->hangup = vpb_hangup;
@@ -1895,7 +1984,6 @@
 			ast_mutex_destroy(&p->record_lock);
 			ast_mutex_destroy(&p->play_lock);
 			ast_mutex_destroy(&p->play_dtmf_lock);
-			ast_mutex_destroy(&p->owner_lock);
 			p->readthread = 0;
 
 			vpb_close(p->handle);




More information about the svn-commits mailing list