Review Board 1.7.16


Add common implementation for a scheduler context with a dedicated thread

Review Request #129 - Created Jan. 24, 2009 and submitted

Russell Bryant
/trunk
Reviewers
asterisk-dev
Asterisk
There are a number of modules that create a scheduler context.  Some use a dedicated thread, while others process the scheduler context within the context of a thread that handles other things as well.  I have noticed a number of bugs in both types of implementations related to race conditions between checking how much time until the next scheduled entry and sleeping for an appropriate amount of time.

To address the problems found in the implementations that use a dedicated thread, I have written this patch.  This patch adds a common implementation of a scheduler context that uses a dedicated thread for processing.

chan_iax2 has been updated to use this new API for its dedicated scheduler thread instead of the one that was written into chan_iax2 directly.  The previous implementation has some race conditions that can lead to the scheduler thread sleeping longer than it is supposed to, leading to scheduled actions not running when they are supposed to.  Bugs caused by this type of thing are often very subtle and difficult to track down.
It compiles.  Basic chan_iax2 usage appears unaffected.

Diff revision 2 (Latest)

1 2
1 2

  1. /trunk/channels/chan_iax2.c: Loading...
  2. /trunk/include/asterisk/sched.h: Loading...
  3. /trunk/main/sched.c: Loading...
/trunk/channels/chan_iax2.c
Revision 171450 New Change
[20] 302 lines
[+20] [+] int (*iax2_regfunk)(const char *username, int onoff) = NULL;
303
		\
303
		\
304
		ast_log(LOG_NOTICE, msg " IAX_COMMAND_RTKEY to rotate key to '%s'\n", digest); \
304
		ast_log(LOG_NOTICE, msg " IAX_COMMAND_RTKEY to rotate key to '%s'\n", digest); \
305
	} while(0)
305
	} while(0)
306

    
   
306

   
307
static	struct io_context *io;
307
static	struct io_context *io;
308
static	struct sched_context *sched;
308
static	struct ast_sched_thread *sched;
309

    
   
309

   
310
static int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH;
310
static int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH;
311

    
   
311

   
312
static int iaxdebug = 0;
312
static int iaxdebug = 0;
313

    
   
313

   
[+20] [20] 16 lines
[+20] [+] static int adsi = 0;
330
static int iax2_encryption = 0;
330
static int iax2_encryption = 0;
331

    
   
331

   
332
static struct ast_flags globalflags = { 0 };
332
static struct ast_flags globalflags = { 0 };
333

    
   
333

   
334
static pthread_t netthreadid = AST_PTHREADT_NULL;
334
static pthread_t netthreadid = AST_PTHREADT_NULL;
335
static pthread_t schedthreadid = AST_PTHREADT_NULL;

   
336
AST_MUTEX_DEFINE_STATIC(sched_lock);

   
337
static ast_cond_t sched_cond;

   
338

    
   
335

   
339
enum iax2_state {
336
enum iax2_state {
340
	IAX_STATE_STARTED = 		(1 << 0),
337
	IAX_STATE_STARTED = 		(1 << 0),
341
	IAX_STATE_AUTHENTICATED = 	(1 << 1),
338
	IAX_STATE_AUTHENTICATED = 	(1 << 1),
342
	IAX_STATE_TBD = 		(1 << 2),
339
	IAX_STATE_TBD = 		(1 << 2),
[+20] [20] 913 lines
[+20] [+] static int __schedule_action(void (*func)(const void *data), const void *data, const char *funcname)
1256
	return -1;
1253
	return -1;
1257
}
1254
}
1258
#define schedule_action(func, data) __schedule_action(func, data, __PRETTY_FUNCTION__)
1255
#define schedule_action(func, data) __schedule_action(func, data, __PRETTY_FUNCTION__)
1259
#endif
1256
#endif
1260

    
   
1257

   
1261
static int iax2_sched_replace(int id, struct sched_context *con, int when, ast_sched_cb callback, const void *data)
1258
static int iax2_sched_replace(int id, struct ast_sched_thread *st, int when, 

    
   
1259
		ast_sched_cb callback, const void *data)
1262
{
1260
{
1263
	AST_SCHED_REPLACE(id, con, when, callback, data);
1261
	ast_sched_thread_del(st, id);
1264
	signal_condition(&sched_lock, &sched_cond);

   
1265

    
   
1262

   
1266
	return id;
1263
	return ast_sched_thread_add(st, when, callback, data);
1267
}
1264
}
1268

    
   
1265

   
1269
static int iax2_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data)
1266
static int iax2_sched_add(struct ast_sched_thread *st, int when, 

    
   
1267
		ast_sched_cb callback, const void *data)
1270
{
1268
{
1271
	int res;
1269
	return ast_sched_thread_add(st, when, callback, data);
1272

    
   

   
1273
	res = ast_sched_add(con, when, callback, data);

   
1274
	signal_condition(&sched_lock, &sched_cond);

   
1275

    
   

   
1276
	return res;

   
1277
}
1270
}
1278

    
   
1271

   
1279
static int send_ping(const void *data);
1272
static int send_ping(const void *data);
1280

    
   
1273

   
1281
static void __send_ping(const void *data)
1274
static void __send_ping(const void *data)
[+20] [20] 238 lines
[+20] [+] static void iax2_destroy_helper(struct chan_iax2_pvt *pvt)
1520
		}
1513
		}
1521

    
   
1514

   
1522
		ast_clear_flag(pvt, IAX_MAXAUTHREQ);
1515
		ast_clear_flag(pvt, IAX_MAXAUTHREQ);
1523
	}
1516
	}
1524
	/* No more pings or lagrq's */
1517
	/* No more pings or lagrq's */
1525
	AST_SCHED_DEL_SPINLOCK(sched, pvt->pingid, &iaxsl[pvt->callno]);
1518
	AST_SCHED_DEL_SPINLOCK(ast_sched_thread_get_context(sched), pvt->pingid, &iaxsl[pvt->callno]);
1526
	AST_SCHED_DEL_SPINLOCK(sched, pvt->lagid, &iaxsl[pvt->callno]);
1519
	AST_SCHED_DEL_SPINLOCK(ast_sched_thread_get_context(sched), pvt->lagid, &iaxsl[pvt->callno]);
1527
	AST_SCHED_DEL(sched, pvt->autoid);
1520
	ast_sched_thread_del(sched, pvt->autoid);
1528
	AST_SCHED_DEL(sched, pvt->authid);
1521
	ast_sched_thread_del(sched, pvt->authid);
1529
	AST_SCHED_DEL(sched, pvt->initid);
1522
	ast_sched_thread_del(sched, pvt->initid);
1530
	AST_SCHED_DEL(sched, pvt->jbid);
1523
	ast_sched_thread_del(sched, pvt->jbid);
1531
	AST_SCHED_DEL(sched, pvt->keyrotateid);
1524
	ast_sched_thread_del(sched, pvt->keyrotateid);
1532
}
1525
}
1533

    
   
1526

   
1534
static void iax2_frame_free(struct iax_frame *fr)
1527
static void iax2_frame_free(struct iax_frame *fr)
1535
{
1528
{
1536
	AST_SCHED_DEL(sched, fr->retrans);
1529
	ast_sched_thread_del(sched, fr->retrans);
1537
	iax_frame_free(fr);
1530
	iax_frame_free(fr);
1538
}
1531
}
1539

    
   
1532

   
1540
static int scheduled_destroy(const void *vid)
1533
static int scheduled_destroy(const void *vid)
1541
{
1534
{
[+20] [20] 178 lines
[+20] [+] static int make_trunk(unsigned short callno, int locked)
1720
		if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) {
1713
		if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) {
1721
			/*!
1714
			/*!
1722
			 * \note We delete these before switching the slot, because if
1715
			 * \note We delete these before switching the slot, because if
1723
			 * they fire in the meantime, they will generate a warning.
1716
			 * they fire in the meantime, they will generate a warning.
1724
			 */
1717
			 */
1725
			AST_SCHED_DEL(sched, iaxs[callno]->pingid);
1718
			ast_sched_thread_del(sched, iaxs[callno]->pingid);
1726
			AST_SCHED_DEL(sched, iaxs[callno]->lagid);
1719
			ast_sched_thread_del(sched, iaxs[callno]->lagid);
1727
			iaxs[x] = iaxs[callno];
1720
			iaxs[x] = iaxs[callno];
1728
			iaxs[x]->callno = x;
1721
			iaxs[x]->callno = x;
1729
			iaxs[callno] = NULL;
1722
			iaxs[callno] = NULL;
1730
			/* Update the two timers that should have been started */
1723
			/* Update the two timers that should have been started */
1731
			iaxs[x]->pingid = iax2_sched_add(sched, 
1724
			iaxs[x]->pingid = iax2_sched_add(sched, 
[+20] [20] 1455 lines
[+20] [+] static int schedule_delivery(struct iax_frame *fr, int updatehistory, int fromtrunk, unsigned int *tsout)
3187
				return -1;
3180
				return -1;
3188
		}
3181
		}
3189

    
   
3182

   
3190
		jb_reset(iaxs[fr->callno]->jb);
3183
		jb_reset(iaxs[fr->callno]->jb);
3191

    
   
3184

   
3192
		AST_SCHED_DEL(sched, iaxs[fr->callno]->jbid);
3185
		ast_sched_thread_del(sched, iaxs[fr->callno]->jbid);
3193

    
   
3186

   
3194
		/* deliver this frame now */
3187
		/* deliver this frame now */
3195
		if (tsout)
3188
		if (tsout)
3196
			*tsout = fr->ts;
3189
			*tsout = fr->ts;
3197
		__do_deliver(fr);
3190
		__do_deliver(fr);
[+20] [20] 29 lines
[+20] [+] static int iax2_transmit(struct iax_frame *fr)
3227
	AST_LIST_INSERT_TAIL(&frame_queue, fr, list);
3220
	AST_LIST_INSERT_TAIL(&frame_queue, fr, list);
3228
	AST_LIST_UNLOCK(&frame_queue);
3221
	AST_LIST_UNLOCK(&frame_queue);
3229
	/* Wake up the network and scheduler thread */
3222
	/* Wake up the network and scheduler thread */
3230
	if (netthreadid != AST_PTHREADT_NULL)
3223
	if (netthreadid != AST_PTHREADT_NULL)
3231
		pthread_kill(netthreadid, SIGURG);
3224
		pthread_kill(netthreadid, SIGURG);
3232
	signal_condition(&sched_lock, &sched_cond);
3225
	ast_sched_thread_poke(sched);
3233
	return 0;
3226
	return 0;
3234
}
3227
}
3235

    
   
3228

   
3236

    
   
3229

   
3237

    
   
3230

   
[+20] [20] 125 lines
[+20] [+] static struct iax2_peer *realtime_peer(const char *peername, struct sockaddr_in *sin)
3363

    
   
3356

   
3364
	if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
3357
	if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
3365
		ast_copy_flags(peer, &globalflags, IAX_RTAUTOCLEAR|IAX_RTCACHEFRIENDS);
3358
		ast_copy_flags(peer, &globalflags, IAX_RTAUTOCLEAR|IAX_RTCACHEFRIENDS);
3366
		if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) {
3359
		if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) {
3367
 			if (peer->expire > -1) {
3360
 			if (peer->expire > -1) {
3368
 				if (!ast_sched_del(sched, peer->expire)) {
3361
 				if (!ast_sched_thread_del(sched, peer->expire)) {
3369
 					peer->expire = -1;
3362
 					peer->expire = -1;
3370
 					peer_unref(peer);
3363
 					peer_unref(peer);
3371
 				}
3364
 				}
3372
 			}
3365
 			}
3373
 			peer->expire = iax2_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, peer_ref(peer));
3366
 			peer->expire = iax2_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, peer_ref(peer));
[+20] [20] 547 lines
[+20] [+] static int iax2_hangup(struct ast_channel *c)
3921
		/* If we were already gone to begin with, destroy us now */
3914
		/* If we were already gone to begin with, destroy us now */
3922
		if (iaxs[callno] && alreadygone) {
3915
		if (iaxs[callno] && alreadygone) {
3923
			ast_debug(1, "Really destroying %s now...\n", c->name);
3916
			ast_debug(1, "Really destroying %s now...\n", c->name);
3924
			iax2_destroy(callno);
3917
			iax2_destroy(callno);
3925
		} else if (iaxs[callno]) {
3918
		} else if (iaxs[callno]) {
3926
			if (ast_sched_add(sched, 10000, scheduled_destroy, CALLNO_TO_PTR(callno)) < 0) {
3919
			if (ast_sched_thread_add(sched, 10000, scheduled_destroy, CALLNO_TO_PTR(callno)) < 0) {
3927
				ast_log(LOG_ERROR, "Unable to schedule iax2 callno %d destruction?!!  Destroying immediately.\n", callno);
3920
				ast_log(LOG_ERROR, "Unable to schedule iax2 callno %d destruction?!!  Destroying immediately.\n", callno);
3928
				iax2_destroy(callno);
3921
				iax2_destroy(callno);
3929
			}
3922
			}
3930
		}
3923
		}
3931
	} else if (c->tech_pvt) {
3924
	} else if (c->tech_pvt) {
[+20] [20] 92 lines
[+20] [+] static int iax2_key_rotate(const void *vpvt)
4024
	};
4017
	};
4025

    
   
4018

   
4026
	ast_mutex_lock(&iaxsl[pvt->callno]);
4019
	ast_mutex_lock(&iaxsl[pvt->callno]);
4027

    
   
4020

   
4028
	pvt->keyrotateid = 
4021
	pvt->keyrotateid = 
4029
		ast_sched_add(sched, 120000 + (ast_random() % 180001), iax2_key_rotate, vpvt);
4022
		ast_sched_thread_add(sched, 120000 + (ast_random() % 180001), iax2_key_rotate, vpvt);
4030

    
   
4023

   
4031
	snprintf(key, sizeof(key), "%lX", ast_random());
4024
	snprintf(key, sizeof(key), "%lX", ast_random());
4032

    
   
4025

   
4033
	MD5Init(&md5);
4026
	MD5Init(&md5);
4034
	MD5Update(&md5, (unsigned char *) key, strlen(key));
4027
	MD5Update(&md5, (unsigned char *) key, strlen(key));
[+20] [20] 3040 lines
[+20] [+] static void register_peer_exten(struct iax2_peer *peer, int onoff)
7075
static void prune_peers(void);
7068
static void prune_peers(void);
7076

    
   
7069

   
7077
static void unlink_peer(struct iax2_peer *peer)
7070
static void unlink_peer(struct iax2_peer *peer)
7078
{
7071
{
7079
	if (peer->expire > -1) {
7072
	if (peer->expire > -1) {
7080
		if (!ast_sched_del(sched, peer->expire)) {
7073
		if (!ast_sched_thread_del(sched, peer->expire)) {
7081
			peer->expire = -1;
7074
			peer->expire = -1;
7082
			peer_unref(peer);
7075
			peer_unref(peer);
7083
		}
7076
		}
7084
	}
7077
	}
7085

    
   
7078

   
7086
	if (peer->pokeexpire > -1) {
7079
	if (peer->pokeexpire > -1) {
7087
		if (!ast_sched_del(sched, peer->pokeexpire)) {
7080
		if (!ast_sched_thread_del(sched, peer->pokeexpire)) {
7088
			peer->pokeexpire = -1;
7081
			peer->pokeexpire = -1;
7089
			peer_unref(peer);
7082
			peer_unref(peer);
7090
		}
7083
		}
7091
	}
7084
	}
7092

    
   
7085

   
[+20] [20] 63 lines
[+20] [+] static void reg_source_db(struct iax2_peer *p)
7156
					memset(&p->addr, 0, sizeof(p->addr));
7149
					memset(&p->addr, 0, sizeof(p->addr));
7157
					p->addr.sin_family = AF_INET;
7150
					p->addr.sin_family = AF_INET;
7158
					p->addr.sin_addr = in;
7151
					p->addr.sin_addr = in;
7159
					p->addr.sin_port = htons(atoi(c));
7152
					p->addr.sin_port = htons(atoi(c));
7160
 					if (p->expire > -1) {
7153
 					if (p->expire > -1) {
7161
 						if (!ast_sched_del(sched, p->expire)) {
7154
 						if (!ast_sched_thread_del(sched, p->expire)) {
7162
 							p->expire = -1;
7155
 							p->expire = -1;
7163
 							peer_unref(p);
7156
 							peer_unref(p);
7164
 						}
7157
 						}
7165
 					}
7158
 					}
7166
  					ast_devstate_changed(AST_DEVICE_UNKNOWN, "IAX2/%s", p->name); /* Activate notification */
7159
  					ast_devstate_changed(AST_DEVICE_UNKNOWN, "IAX2/%s", p->name); /* Activate notification */
[+20] [20] 85 lines
[+20] [+] static int update_registry(struct sockaddr_in *sin, int callno, char *devtype, int fd, unsigned short refresh)
7252

    
   
7245

   
7253
	/* Store socket fd */
7246
	/* Store socket fd */
7254
	p->sockfd = fd;
7247
	p->sockfd = fd;
7255
	/* Setup the expiry */
7248
	/* Setup the expiry */
7256
	if (p->expire > -1) {
7249
	if (p->expire > -1) {
7257
		if (!ast_sched_del(sched, p->expire)) {
7250
		if (!ast_sched_thread_del(sched, p->expire)) {
7258
			p->expire = -1;
7251
			p->expire = -1;
7259
			peer_unref(p);
7252
			peer_unref(p);
7260
		}
7253
		}
7261
	}
7254
	}
7262
	/* treat an unspecified refresh interval as the minimum */
7255
	/* treat an unspecified refresh interval as the minimum */
[+20] [20] 1475 lines
[+20] [+] retryowner:
8738
			} else if (f.subclass == AST_CONTROL_CONGESTION) {
8731
			} else if (f.subclass == AST_CONTROL_CONGESTION) {
8739
				iaxs[fr->callno]->owner->hangupcause = AST_CAUSE_CONGESTION;
8732
				iaxs[fr->callno]->owner->hangupcause = AST_CAUSE_CONGESTION;
8740
			}
8733
			}
8741
		}
8734
		}
8742
		if (f.frametype == AST_FRAME_IAX) {
8735
		if (f.frametype == AST_FRAME_IAX) {
8743
			AST_SCHED_DEL(sched, iaxs[fr->callno]->initid);
8736
			ast_sched_thread_del(sched, iaxs[fr->callno]->initid);
8744
			/* Handle the IAX pseudo frame itself */
8737
			/* Handle the IAX pseudo frame itself */
8745
			if (iaxdebug)
8738
			if (iaxdebug)
8746
				ast_debug(1, "IAX subclass %d received\n", f.subclass);
8739
				ast_debug(1, "IAX subclass %d received\n", f.subclass);
8747

    
   
8740

   
8748
                        /* Update last ts unless the frame's timestamp originated with us. */
8741
                        /* Update last ts unless the frame's timestamp originated with us. */
[+20] [20] 476 lines
[+20] [+] retryowner2:
9225
					else					
9218
					else					
9226
						peer->historicms = iaxs[fr->callno]->pingtime;
9219
						peer->historicms = iaxs[fr->callno]->pingtime;
9227

    
   
9220

   
9228
					/* Remove scheduled iax2_poke_noanswer */
9221
					/* Remove scheduled iax2_poke_noanswer */
9229
					if (peer->pokeexpire > -1) {
9222
					if (peer->pokeexpire > -1) {
9230
						if (!ast_sched_del(sched, peer->pokeexpire)) {
9223
						if (!ast_sched_thread_del(sched, peer->pokeexpire)) {
9231
							peer_unref(peer);
9224
							peer_unref(peer);
9232
							peer->pokeexpire = -1;
9225
							peer->pokeexpire = -1;
9233
						}
9226
						}
9234
					}
9227
					}
9235
					/* Schedule the next cycle */
9228
					/* Schedule the next cycle */
[+20] [20] 1107 lines
[+20] [+] static int iax2_poke_peer(struct iax2_peer *peer, int heldcall)
10343
	/* Speed up retransmission times for this qualify call */
10336
	/* Speed up retransmission times for this qualify call */
10344
	iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1;
10337
	iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1;
10345
	iaxs[peer->callno]->peerpoke = peer;
10338
	iaxs[peer->callno]->peerpoke = peer;
10346

    
   
10339

   
10347
 	if (peer->pokeexpire > -1) {
10340
 	if (peer->pokeexpire > -1) {
10348
 		if (!ast_sched_del(sched, peer->pokeexpire)) {
10341
 		if (!ast_sched_thread_del(sched, peer->pokeexpire)) {
10349
 			peer->pokeexpire = -1;
10342
 			peer->pokeexpire = -1;
10350
 			peer_unref(peer);
10343
 			peer_unref(peer);
10351
 		}
10344
 		}
10352
 	}
10345
 	}
10353
 
10346
 
[+20] [20] 104 lines
[+20] [+] static struct ast_channel *iax2_request(const char *type, int format, void *data, int *cause)
10458
	}
10451
	}
10459

    
   
10452

   
10460
	return c;
10453
	return c;
10461
}
10454
}
10462

    
   
10455

   
10463
static void *sched_thread(void *ignore)

   
10464
{

   
10465
	int count;

   
10466
	int res;

   
10467
	struct timeval wait;

   
10468
	struct timespec ts;

   
10469

    
   

   
10470
	for (;;) {

   
10471
		pthread_testcancel();

   
10472
		ast_mutex_lock(&sched_lock);

   
10473
		res = ast_sched_wait(sched);

   
10474
		if ((res > 1000) || (res < 0))

   
10475
			res = 1000;

   
10476
		wait = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000));

   
10477
		ts.tv_sec = wait.tv_sec;

   
10478
		ts.tv_nsec = wait.tv_usec * 1000;

   
10479
		ast_cond_timedwait(&sched_cond, &sched_lock, &ts);

   
10480
		ast_mutex_unlock(&sched_lock);

   
10481
		pthread_testcancel();

   
10482

    
   

   
10483
		count = ast_sched_runq(sched);

   
10484
		if (count >= 20)

   
10485
			ast_debug(1, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count);

   
10486
	}

   
10487

    
   

   
10488
	return NULL;

   
10489
}

   
10490

    
   

   
10491
static void *network_thread(void *ignore)
10456
static void *network_thread(void *ignore)
10492
{
10457
{
10493
	/* Our job is simple: Send queued messages, retrying if necessary.  Read frames 
10458
	/* Our job is simple: Send queued messages, retrying if necessary.  Read frames 
10494
	   from the network, and queue them for delivery to the channels */
10459
	   from the network, and queue them for delivery to the channels */
10495
	int res, count, wakeup;
10460
	int res, count, wakeup;
[+20] [20] 77 lines
[+20] [+] static int start_network_thread(void)
10573
			AST_LIST_LOCK(&idle_list);
10538
			AST_LIST_LOCK(&idle_list);
10574
			AST_LIST_INSERT_TAIL(&idle_list, thread, list);
10539
			AST_LIST_INSERT_TAIL(&idle_list, thread, list);
10575
			AST_LIST_UNLOCK(&idle_list);
10540
			AST_LIST_UNLOCK(&idle_list);
10576
		}
10541
		}
10577
	}
10542
	}
10578
	ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL);

   
10579
	ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL);
10543
	ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL);
10580
	ast_verb(2, "%d helper threads started\n", threadcount);
10544
	ast_verb(2, "%d helper threads started\n", threadcount);
10581
	return 0;
10545
	return 0;
10582
}
10546
}
10583

    
   
10547

   
[+20] [20] 262 lines
[+20] [+] static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly)
10846
							peer->addr.sin_port = 0;
10810
							peer->addr.sin_port = 0;
10847
						}
10811
						}
10848
					}
10812
					}
10849
				} else {
10813
				} else {
10850
					/* Non-dynamic.  Make sure we become that way if we're not */
10814
					/* Non-dynamic.  Make sure we become that way if we're not */
10851
					AST_SCHED_DEL(sched, peer->expire);
10815
					ast_sched_thread_del(sched, peer->expire);
10852
					ast_clear_flag(peer, IAX_DYNAMIC);
10816
					ast_clear_flag(peer, IAX_DYNAMIC);
10853
					if (ast_dnsmgr_lookup(v->value, &peer->addr, &peer->dnsmgr, srvlookup ? "_iax._udp" : NULL))
10817
					if (ast_dnsmgr_lookup(v->value, &peer->addr, &peer->dnsmgr, srvlookup ? "_iax._udp" : NULL))
10854
						return peer_unref(peer);
10818
						return peer_unref(peer);
10855
					if (!peer->addr.sin_port)
10819
					if (!peer->addr.sin_port)
10856
						peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
10820
						peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
[+20] [20] 362 lines
[+20] [+] static void delete_users(void)
11219

    
   
11183

   
11220
	ao2_callback(users, 0, user_delme_cb, NULL);
11184
	ao2_callback(users, 0, user_delme_cb, NULL);
11221

    
   
11185

   
11222
	AST_LIST_LOCK(&registrations);
11186
	AST_LIST_LOCK(&registrations);
11223
	while ((reg = AST_LIST_REMOVE_HEAD(&registrations, entry))) {
11187
	while ((reg = AST_LIST_REMOVE_HEAD(&registrations, entry))) {
11224
		AST_SCHED_DEL(sched, reg->expire);
11188
		ast_sched_thread_del(sched, reg->expire);
11225
		if (reg->callno) {
11189
		if (reg->callno) {
11226
			int callno = reg->callno;
11190
			int callno = reg->callno;
11227
			ast_mutex_lock(&iaxsl[callno]);
11191
			ast_mutex_lock(&iaxsl[callno]);
11228
			if (iaxs[callno]) {
11192
			if (iaxs[callno]) {
11229
				iaxs[callno]->reg = NULL;
11193
				iaxs[callno]->reg = NULL;
[+20] [20] 1172 lines
[+20] [+] static int __unload_module(void)
12402
	
12366
	
12403
	/* Grab the sched lock resource to keep it away from threads about to die */
12367
	/* Grab the sched lock resource to keep it away from threads about to die */
12404
	/* Cancel the network thread, close the net socket */
12368
	/* Cancel the network thread, close the net socket */
12405
	if (netthreadid != AST_PTHREADT_NULL) {
12369
	if (netthreadid != AST_PTHREADT_NULL) {
12406
		AST_LIST_LOCK(&frame_queue);
12370
		AST_LIST_LOCK(&frame_queue);
12407
		ast_mutex_lock(&sched_lock);

   
12408
		pthread_cancel(netthreadid);
12371
		pthread_cancel(netthreadid);
12409
		ast_cond_signal(&sched_cond);

   
12410
		ast_mutex_unlock(&sched_lock);	/* Release the schedule lock resource */

   
12411
		AST_LIST_UNLOCK(&frame_queue);
12372
		AST_LIST_UNLOCK(&frame_queue);
12412
		pthread_join(netthreadid, NULL);
12373
		pthread_join(netthreadid, NULL);
12413
	}
12374
	}
12414
	if (schedthreadid != AST_PTHREADT_NULL) {

   
12415
		ast_mutex_lock(&sched_lock);

   
12416
		pthread_cancel(schedthreadid);

   
12417
		ast_cond_signal(&sched_cond);

   
12418
		ast_mutex_unlock(&sched_lock);

   
12419
		pthread_join(schedthreadid, NULL);

   
12420
	}

   
12421

    
   
12375

   

    
   
12376
	sched = ast_sched_thread_destroy(sched);

    
   
12377
	
12422
	/* Call for all threads to halt */
12378
	/* Call for all threads to halt */
12423
	AST_LIST_LOCK(&idle_list);
12379
	AST_LIST_LOCK(&idle_list);
12424
	while ((thread = AST_LIST_REMOVE_HEAD(&idle_list, list)))
12380
	while ((thread = AST_LIST_REMOVE_HEAD(&idle_list, list)))
12425
		pthread_cancel(thread->threadid);
12381
		pthread_cancel(thread->threadid);
12426
	AST_LIST_UNLOCK(&idle_list);
12382
	AST_LIST_UNLOCK(&idle_list);
[+20] [20] 27 lines
[+20] static int __unload_module(void)
12454
	ast_cli_unregister_multiple(cli_iax2, ARRAY_LEN(cli_iax2));
12410
	ast_cli_unregister_multiple(cli_iax2, ARRAY_LEN(cli_iax2));
12455
	ast_unregister_switch(&iax2_switch);
12411
	ast_unregister_switch(&iax2_switch);
12456
	ast_channel_unregister(&iax2_tech);
12412
	ast_channel_unregister(&iax2_tech);
12457
	delete_users();
12413
	delete_users();
12458
	iax_provision_unload();
12414
	iax_provision_unload();
12459
	sched_context_destroy(sched);

   
12460
	reload_firmware(1);
12415
	reload_firmware(1);
12461

    
   
12416

   
12462
	for (x = 0; x < ARRAY_LEN(iaxsl); x++) {
12417
	for (x = 0; x < ARRAY_LEN(iaxsl); x++) {
12463
		ast_mutex_destroy(&iaxsl[x]);
12418
		ast_mutex_destroy(&iaxsl[x]);
12464
	}
12419
	}
[+20] [20] 81 lines
[+20] [+] static int load_module(void)
12546

    
   
12501

   
12547
	for (x = 0; x < ARRAY_LEN(iaxsl); x++) {
12502
	for (x = 0; x < ARRAY_LEN(iaxsl); x++) {
12548
		ast_mutex_init(&iaxsl[x]);
12503
		ast_mutex_init(&iaxsl[x]);
12549
	}
12504
	}
12550

    
   
12505

   
12551
	ast_cond_init(&sched_cond, NULL);
12506
	if (!(sched = ast_sched_thread_create())) {
12552

    
   
12507
		ast_log(LOG_ERROR, "Failed to create scheduler thread\n");
12553
	if (!(sched = sched_context_create())) {

   
12554
		ast_log(LOG_ERROR, "Failed to create scheduler context\n");

   
12555
		return AST_MODULE_LOAD_FAILURE;
12508
		return AST_MODULE_LOAD_FAILURE;
12556
	}
12509
	}
12557

    
   
12510

   
12558
	if (!(io = io_context_create())) {
12511
	if (!(io = io_context_create())) {
12559
		ast_log(LOG_ERROR, "Failed to create I/O context\n");
12512
		ast_log(LOG_ERROR, "Failed to create I/O context\n");
12560
		sched_context_destroy(sched);
12513
		sched = ast_sched_thread_destroy(sched);
12561
		return AST_MODULE_LOAD_FAILURE;
12514
		return AST_MODULE_LOAD_FAILURE;
12562
	}
12515
	}
12563

    
   
12516

   
12564
	if (!(netsock = ast_netsock_list_alloc())) {
12517
	if (!(netsock = ast_netsock_list_alloc())) {
12565
		ast_log(LOG_ERROR, "Failed to create netsock list\n");
12518
		ast_log(LOG_ERROR, "Failed to create netsock list\n");
12566
		io_context_destroy(io);
12519
		io_context_destroy(io);
12567
		sched_context_destroy(sched);
12520
		sched = ast_sched_thread_destroy(sched);
12568
		return AST_MODULE_LOAD_FAILURE;
12521
		return AST_MODULE_LOAD_FAILURE;
12569
	}
12522
	}
12570
	ast_netsock_init(netsock);
12523
	ast_netsock_init(netsock);
12571
	
12524
	
12572
	outsock = ast_netsock_list_alloc();
12525
	outsock = ast_netsock_list_alloc();
12573
	if (!outsock) {
12526
	if (!outsock) {
12574
		ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
12527
		ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
12575
		io_context_destroy(io);
12528
		io_context_destroy(io);
12576
		sched_context_destroy(sched);
12529
		sched = ast_sched_thread_destroy(sched);
12577
		return AST_MODULE_LOAD_FAILURE;
12530
		return AST_MODULE_LOAD_FAILURE;
12578
	}
12531
	}
12579
	ast_netsock_init(outsock);
12532
	ast_netsock_init(outsock);
12580

    
   
12533

   
12581
	ast_cli_register_multiple(cli_iax2, ARRAY_LEN(cli_iax2));
12534
	ast_cli_register_multiple(cli_iax2, ARRAY_LEN(cli_iax2));
[+20] [20] 55 lines
/trunk/include/asterisk/sched.h
Revision 171450 New Change
 
/trunk/main/sched.c
Revision 171450 New Change
 
  1. /trunk/channels/chan_iax2.c: Loading...
  2. /trunk/include/asterisk/sched.h: Loading...
  3. /trunk/main/sched.c: Loading...

https://reviewboard.asterisk.org/ runs on a server provided by Digium, Inc. and uses bandwidth donated to the open source Asterisk community by API Digital Communications in Huntsville, AL USA.
Please report problems with this site to asteriskteam@digium.com.