Index: Makefile =================================================================== RCS file: /usr/cvsroot/asterisk/Makefile,v retrieving revision 1.95 diff -u -u -r1.95 Makefile --- Makefile 13 Jun 2004 21:25:09 -0000 1.95 +++ Makefile 15 Jun 2004 02:40:20 -0000 @@ -26,15 +26,12 @@ #PROC=athlon OPTIONS+=-m64 endif -else -ifeq (${OSARCH},FreeBSD) -PROC=$(shell uname -m) -else -ifeq (${OSARCH},OpenBSD) -PROC=$(shell uname -m) -endif endif + +ifeq ($(findstring BSD,${OSARCH}),BSD) +PROC=$(shell uname -m) endif + # Pentium Pro Optimize #PROC=i686 @@ -121,9 +118,13 @@ CFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi) CFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi) ifeq (${OSARCH},FreeBSD) -CFLAGS+=-pthread -INCLUDE+=-I/usr/local/include -endif +H323LIBNAME=h323_FreeBSD_x86_r_s +PWLIBNAME=pt_FreeBSD_x86_r_s +OSVERSION=$(shell make -V OSVERSION -f /usr/share/mk/bsd.port.subdir.mk) +CFLAGS+=$(if ${OSVERSION}<500016,-D_THREAD_SAFE) +LIBS+=$(if ${OSVERSION}<502102,-lc_r,-pthread) +INCLUDE+=-I/usr/local/include -I/usr/local/include/spandsp +endif # FreeBSD ifeq (${OSARCH},OpenBSD) CFLAGS+=-pthread endif @@ -161,14 +162,6 @@ ifeq (${OSARCH},Linux) LIBS=-ldl -lpthread endif -ifeq (${OSARCH},OpenBSD) -LIBS=-pthread -else -ifeq (${OSARCH},FreeBSD) -LIBS=-pthread -else -endif -endif LIBS+=-lncurses -lm ifeq (${OSARCH},Linux) LIBS+=-lresolv #-lnjamd @@ -258,7 +251,7 @@ fi asterisk: editline/libedit.a db1-ast/libdb1.a stdtime/libtime.a $(OBJS) - $(CC) $(DEBUG) -o asterisk $(ASTLINK) $(OBJS) $(LIBEDIT) db1-ast/libdb1.a stdtime/libtime.a $(LIBS) + $(CC) $(CFLAGS) $(DEBUG) -o asterisk $(ASTLINK) $(OBJS) $(LIBEDIT) db1-ast/libdb1.a stdtime/libtime.a $(LIBS) muted: muted.o $(CC) -o muted muted.o Index: asterisk.c =================================================================== RCS file: /usr/cvsroot/asterisk/asterisk.c,v retrieving revision 1.91 diff -u -u -r1.91 asterisk.c --- asterisk.c 13 Jun 2004 21:25:09 -0000 1.91 +++ asterisk.c 15 Jun 2004 02:40:20 -0000 @@ -49,6 +49,7 @@ #include "asterisk.h" #include #include +#include #if defined(__FreeBSD__) #include @@ -1553,6 +1554,11 @@ term_init(); printf(term_end()); fflush(stdout); + + /* Test recursive mutex locking. */ + if(test_for_thread_safety()) + ast_verbose("Warning! Asterisk is not thread safe.\n"); + if (option_console && !option_verbose) ast_verbose("[ Reading Master Configuration ]"); ast_readconfig(); Index: cli.c =================================================================== RCS file: /usr/cvsroot/asterisk/cli.c,v retrieving revision 1.42 diff -u -u -r1.42 cli.c --- cli.c 11 Jun 2004 00:18:30 -0000 1.42 +++ cli.c 15 Jun 2004 02:40:20 -0000 @@ -181,8 +181,8 @@ char timestr[256]; int pos = 0; #define SECOND (1) -#define MIN (SECOND*60) -#define HOUR (MIN*60) +#define MINUTE (SECOND*60) +#define HOUR (MINUTE*60) #define DAY (HOUR*24) #define WEEK (DAY*7) #define YEAR (DAY*365) @@ -222,9 +222,9 @@ else pos += sprintf(timestr + pos, "1 hour, "); } - if (timeval > MIN) { - mins = (timeval / MIN); - timeval -= (mins * MIN); + if (timeval > MINUTE) { + mins = (timeval / MINUTE); + timeval -= (mins * MINUTE); if (mins > 1) pos += sprintf(timestr + pos, "%d minutes, ", mins); else if (mins > 0) Index: db.c =================================================================== RCS file: /usr/cvsroot/asterisk/db.c,v retrieving revision 1.8 diff -u -u -r1.8 db.c --- db.c 9 Jun 2004 01:45:07 -0000 1.8 +++ db.c 15 Jun 2004 02:40:21 -0000 @@ -33,7 +33,11 @@ #include #include #include +#if defined(__FreeBSD__) +#include +#else #include "db1-ast/include/db.h" +#endif #include "asterisk.h" #include "astconf.h" Index: sched.c =================================================================== RCS file: /usr/cvsroot/asterisk/sched.c,v retrieving revision 1.11 diff -u -u -r1.11 sched.c --- sched.c 21 Nov 2003 22:05:08 -0000 1.11 +++ sched.c 15 Jun 2004 02:40:21 -0000 @@ -63,6 +63,7 @@ struct sched_context *tmp; tmp = malloc(sizeof(struct sched_context)); if (tmp) { + memset(tmp, 0, sizeof(struct sched_context)); ast_mutex_init(&tmp->lock); tmp->eventcnt = 1; tmp->schedcnt = 0; @@ -97,6 +98,7 @@ } /* And the context */ ast_mutex_unlock(&con->lock); + ast_mutex_destroy(&con->lock); free(con); } Index: utils.c =================================================================== RCS file: /usr/cvsroot/asterisk/utils.c,v retrieving revision 1.7 diff -u -u -r1.7 utils.c --- utils.c 12 Jun 2004 14:53:53 -0000 1.7 +++ utils.c 15 Jun 2004 02:40:21 -0000 @@ -11,6 +11,8 @@ #include #include +#include +#include #include #include @@ -22,9 +24,9 @@ AST_MUTEX_DEFINE_STATIC(__mutex); -int gethostbyname_r (const char *name, struct hostent *ret, char *buf, - size_t buflen, struct hostent **result, - int *h_errnop) +static int gethostbyname_r (const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, + int *h_errnop) { int hsave; struct hostent *ph; @@ -143,3 +145,60 @@ return NULL; return &hp->hp; } + + +/* This is a regression test for recursive mutexes. + test_for_thread_safety() will return 0 if recursive mutex locks are + working properly, and non-zero if they are not working properly. */ + +AST_MUTEX_DEFINE_STATIC(test_lock); +AST_MUTEX_DEFINE_STATIC(test_lock2); +static pthread_t test_thread; +static int lock_count = 0; +static int test_errors = 0; + +static void *test_thread_body(void *data) +{ + ast_mutex_lock(&test_lock); + lock_count += 10; + if(lock_count != 10) test_errors++; + ast_mutex_lock(&test_lock); + lock_count += 10; + if(lock_count != 20) test_errors++; + ast_mutex_lock(&test_lock2); + ast_mutex_unlock(&test_lock); + lock_count -= 10; + if(lock_count != 10) test_errors++; + ast_mutex_unlock(&test_lock); + lock_count -= 10; + ast_mutex_unlock(&test_lock2); + if(lock_count != 0) test_errors++; + return NULL; +} + +int test_for_thread_safety(void) +{ + ast_mutex_lock(&test_lock2); + ast_mutex_lock(&test_lock); + lock_count += 1; + ast_mutex_lock(&test_lock); + lock_count += 1; + pthread_create(&test_thread, NULL, test_thread_body, NULL); + pthread_yield(); + usleep(100); + if(lock_count != 2) test_errors++; + ast_mutex_unlock(&test_lock); + lock_count -= 1; + pthread_yield(); + usleep(100); + if(lock_count != 1) test_errors++; + ast_mutex_unlock(&test_lock); + lock_count -= 1; + if(lock_count != 0) test_errors++; + ast_mutex_unlock(&test_lock2); + pthread_yield(); + usleep(100); + if(lock_count != 0) test_errors++; + pthread_join(test_thread, NULL); + return(test_errors); /* return 0 on success. */ +} Index: agi/Makefile =================================================================== RCS file: /usr/cvsroot/asterisk/agi/Makefile,v retrieving revision 1.7 diff -u -u -r1.7 Makefile --- agi/Makefile 4 May 2004 01:46:01 -0000 1.7 +++ agi/Makefile 15 Jun 2004 02:40:21 -0000 @@ -22,10 +22,10 @@ for x in $(AGIS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(AGI_DIR) ; done eagi-test: eagi-test.o - $(CC) -o eagi-test eagi-test.o - + $(CC) $(CFLAGS) -o eagi-test eagi-test.o + eagi-sphinx-test: eagi-sphinx-test.o - $(CC) -o eagi-sphinx-test eagi-sphinx-test.o + $(CC) $(CFLAGS) -o eagi-sphinx-test eagi-sphinx-test.o clean: rm -f *.so *.o look .depend eagi-test eagi-sphinx-test Index: apps/Makefile =================================================================== RCS file: /usr/cvsroot/asterisk/apps/Makefile,v retrieving revision 1.67 diff -u -u -r1.67 Makefile --- apps/Makefile 11 Jun 2004 14:06:30 -0000 1.67 +++ apps/Makefile 15 Jun 2004 02:40:21 -0000 @@ -87,7 +87,7 @@ $(CC) $(SOLINK) -o $@ $< -lodbc look: look.c - gcc -pipe -O6 -g look.c -o look -lncurses + $(CC) $(CFLAGS) look.c -o look -lncurses ifneq ($(wildcard .depend),) include .depend Index: apps/app_dial.c =================================================================== RCS file: /usr/cvsroot/asterisk/apps/app_dial.c,v retrieving revision 1.71 diff -u -u -r1.71 app_dial.c --- apps/app_dial.c 14 Jun 2004 19:43:41 -0000 1.71 +++ apps/app_dial.c 15 Jun 2004 02:40:21 -0000 @@ -122,7 +122,7 @@ } } -#define MAX 256 +#define AST_MAX_WATCHERS 256 static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect) { @@ -134,7 +134,7 @@ int orig = *to; struct ast_frame *f; struct ast_channel *peer = NULL; - struct ast_channel *watchers[MAX]; + struct ast_channel *watchers[AST_MAX_WATCHERS]; int pos; int single; int moh=0; Index: apps/app_queue.c =================================================================== RCS file: /usr/cvsroot/asterisk/apps/app_queue.c,v retrieving revision 1.69 diff -u -u -r1.69 app_queue.c --- apps/app_queue.c 13 Jun 2004 19:45:59 -0000 1.69 +++ apps/app_queue.c 15 Jun 2004 02:40:21 -0000 @@ -628,7 +628,7 @@ return 0; } -#define MAX 256 +#define AST_MAX_WATCHERS 256 static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect, char *digit) { @@ -641,7 +641,7 @@ int orig = *to; struct ast_frame *f; struct localuser *peer = NULL; - struct ast_channel *watchers[MAX]; + struct ast_channel *watchers[AST_MAX_WATCHERS]; int pos; struct ast_channel *winner; struct ast_channel *in = qe->chan; Index: astman/Makefile =================================================================== RCS file: /usr/cvsroot/asterisk/astman/Makefile,v retrieving revision 1.8 diff -u -u -r1.8 Makefile --- astman/Makefile 4 Jun 2004 15:44:14 -0000 1.8 +++ astman/Makefile 15 Jun 2004 02:40:21 -0000 @@ -4,7 +4,7 @@ CFLAGS+=-DNO_AST_MM OSARCH=$(shell uname -s) -ifeq (${OSARCH},FreeBSD) +ifeq ($(findstring BSD,${OSARCH}),BSD) CFLAGS+=-I/usr/local/include -L/usr/local/lib endif Index: cdr/Makefile =================================================================== RCS file: /usr/cvsroot/asterisk/cdr/Makefile,v retrieving revision 1.22 diff -u -u -r1.22 Makefile --- cdr/Makefile 31 May 2004 19:40:22 -0000 1.22 +++ cdr/Makefile 15 Jun 2004 02:40:21 -0000 @@ -18,7 +18,7 @@ CFLAGS+=-fPIC OSARCH=$(shell uname -s) -ifeq (${OSARCH},FreeBSD) +ifeq ($(findstring BSD,${OSARCH}),BSD) SOLINK+=-L/usr/local/lib endif Index: channels/Makefile =================================================================== RCS file: /usr/cvsroot/asterisk/channels/Makefile,v retrieving revision 1.54 diff -u -u -r1.54 Makefile --- channels/Makefile 4 Jun 2004 15:44:14 -0000 1.54 +++ channels/Makefile 15 Jun 2004 02:40:21 -0000 @@ -33,24 +33,37 @@ # #CHANNEL_LIBS+=chan_vofr -ifeq (${OSARCH},OpenBSD) -MYSQLLIB=-L/usr/local/lib/mysql -lmysqlclient -CFLAGS+=-I/usr/local/include -PTLIB=-lpt_OpenBSD_x86_r -H323LIB=-lh323_OpenBSD_x86_r -CHANH323LIB=-L/usr/local/lib -else +ifeq (${OSARCH},Linux) MYSQLLIB=-L/usr/lib/mysql -lmysqlclient PTLIB=-lpt_linux_x86_r H323LIB=-lh323_linux_x86_r CHANH323LIB=-ldl +SOLINK+=-ldl -lpthread endif -ifneq (${OSARCH},Darwin) +ifeq ($(findstring BSD,${OSARCH}),BSD) +MYSQLLIB=-L/usr/local/lib/mysql -lmysqlclient CHANNEL_LIBS+=chan_oss.so +CFLAGS+=-I/usr/local/include +SOLINK+=-L/usr/local/lib endif + +ifeq (${OSARCH},OpenBSD) +PTLIB=-lpt_OpenBSD_x86_r +H323LIB=-lh323_OpenBSD_x86_r +endif + ifeq (${OSARCH},FreeBSD) -SOLINK+=-L/usr/local/lib +HAS_OPENH323=$(shell if [ -f $(OPENH323DIR)/lib/lib$(H323LIBNAME).a ]; then echo "Yes"; fi) +HAS_PWLIB=$(shell if [ -f $(PWLIBDIR)/lib/lib$(PWLIBNAME).a ]; then echo "Yes"; fi) +ifeq (${HAS_OPENH323}${HAS_PWLIB},YesYes) +CHANNEL_LIBS+=chan_h323.so +H323LIB=-l$(H323LIBNAME) +PTLIB=-l$(PWLIBNAME) +endif +endif #FreeBSD + +ifneq (${OSARCH},Darwin) CHANNEL_LIBS+=chan_oss.so endif @@ -132,8 +145,11 @@ chan_oss.o: chan_oss.c busy.h ringtone.h ifeq (${OSARCH},OpenBSD) +OSS_LIB=-lossaudio +endif +ifeq ($(findstring BSD,${OSARCH}),BSD) chan_oss.so: chan_oss.o - $(CC) $(SOLINK) -o $@ chan_oss.o -lossaudio + $(CC) $(SOLINK) -o $@ chan_oss.o $(OSS_LIB) endif chan_iax2.so: chan_iax2.o iax2-parser.o @@ -167,7 +183,7 @@ chan_alsa.so: chan_alsa.o - $(CC) $(SOLINK) -o $@ $< -lasound -lm -ldl + $(CC) $(SOLINK) -o $@ $< -lasound -lm chan_nbs.so: chan_nbs.o $(CC) $(SOLINK) -o $@ $< -lnbs @@ -176,11 +192,13 @@ $(CXX) -c $(CFLAGS) -o $@ chan_vpb.c chan_vpb.so: chan_vpb.o - $(CXX) $(SOLINK) -o $@ $< -lvpb -lpthread -lm -ldl + $(CXX) $(SOLINK) -o $@ $< -lvpb -lm chan_h323.so: chan_h323.o h323/libchanh323.a - $(CC) $(SOLINK) -o $@ $< h323/libchanh323.a $(CHANH323LIB) -L$(PWLIBDIR)/lib $(PTLIB) -L$(OPENH323DIR)/lib $(H323LIB) -L/usr/lib -lpthread -lcrypto -lssl -lexpat + $(CC) $(SOLINK) -o $@ $< h323/libchanh323.a -L$(PWLIBDIR)/lib $(PTLIB) -L$(OPENH323DIR)/lib $(H323LIB) -L/usr/lib -lcrypto -lssl -lexpat +h323/libchanh323.a h323/ast_h323.o: + $(MAKE) -C h323 all #chan_modem.so : chan_modem.o # $(CC) -rdynamic -shared -Xlinker -x -o $@ $< Index: channels/chan_h323.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_h323.c,v retrieving revision 1.58 diff -u -u -r1.58 chan_h323.c --- channels/chan_h323.c 14 Jun 2004 21:18:52 -0000 1.58 +++ channels/chan_h323.c 15 Jun 2004 02:40:24 -0000 @@ -55,7 +55,8 @@ #include #include #include -#ifdef __OpenBSD__ +#include +#if defined(BSD) #include #ifndef IPTOS_MINCOST #define IPTOS_MINCOST 0x02 @@ -186,8 +187,10 @@ } if (!cur) { ast_log(LOG_WARNING, "%p is not in list?!?! \n", cur); - } else + } else { + ast_mutex_destroy(&p->lock); free(p); + } } static void oh323_destroy(struct oh323_pvt *p) @@ -1812,10 +1815,20 @@ set_rtp_peer: oh323_set_rtp_peer, }; +static int initialized = 0; int load_module() { int res; + if ( ! initialized ) { + initialized++; + ast_mutex_init(&userl.lock); + ast_mutex_init(&peerl.peerl); + ast_mutex_init(&aliasl.lock); + ast_mutex_init(&iflock); + ast_mutex_init(&usecnt_lock); + ast_mutex_init(&monlock); + } res = reload_config(); @@ -1946,6 +1959,13 @@ /* unregister channel type */ ast_channel_unregister(type); + if ( initialized ) { + initialized = 0; + ast_mutex_destroy(&iflock); + ast_mutex_destroy(&usecnt_lock); + ast_mutex_destroy(&monlock); + } + return 0; } Index: channels/chan_iax2.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_iax2.c,v retrieving revision 1.153 diff -u -u -r1.153 chan_iax2.c --- channels/chan_iax2.c 14 Jun 2004 03:12:46 -0000 1.153 +++ channels/chan_iax2.c 15 Jun 2004 02:40:25 -0000 @@ -507,7 +507,7 @@ struct iax2_dpcache *peer; /* For linking in peers */ } *dpcache; -static ast_mutex_t dpcache_lock; +AST_MUTEX_DEFINE_STATIC(dpcache_lock); static void iax_debug_output(const char *data) { @@ -6864,11 +6864,16 @@ ast_log(LOG_ERROR, "Out of memory\n"); return -1; } - - ast_mutex_init(&iaxq.lock); - ast_mutex_init(&userl.lock); - ast_mutex_init(&peerl.lock); - + { + static int initialized = 0; + if ( ! initialized ) { + initialized++; + ast_mutex_init(&iaxq.lock); + ast_mutex_init(&userl.lock); + ast_mutex_init(&peerl.lock); + ast_mutex_init(&waresl.lock); + } + } ast_cli_register(&cli_show_users); ast_cli_register(&cli_show_channels); ast_cli_register(&cli_show_peers); Index: channels/chan_mgcp.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_mgcp.c,v retrieving revision 1.54 diff -u -u -r1.54 chan_mgcp.c --- channels/chan_mgcp.c 9 Jun 2004 01:45:07 -0000 1.54 +++ channels/chan_mgcp.c 15 Jun 2004 02:40:26 -0000 @@ -3501,18 +3501,21 @@ } if (!e) { + /* Allocate wildcard endpoint */ e = malloc(sizeof(struct mgcp_endpoint)); ep_reload = 0; } - /* Allocate wildcard endpoint */ - e = malloc(sizeof(struct mgcp_endpoint)); if (e) { if (!ep_reload) { - memset(e, 0, sizeof(struct mgcp_endpoint)); - strncpy(e->name, v->value, sizeof(e->name) - 1); - e->needaudit = 1; - } + memset(e, 0, sizeof(struct mgcp_endpoint)); + ast_mutex_init(&e->lock); + ast_mutex_init(&e->rqnt_queue_lock); + ast_mutex_init(&e->cmd_queue_lock); + strncpy(e->name, v->value, sizeof(e->name) - 1); + e->needaudit = 1; + } + strncpy(gw->wcardep, v->value, sizeof(gw->wcardep)-1); //strcpy(e->name, "aaln/*"); /* XXX Should we really check for uniqueness?? XXX */ @@ -3545,6 +3548,8 @@ if (sub) { ast_verbose(VERBOSE_PREFIX_3 "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name); memset(sub, 0, sizeof(struct mgcp_subchannel)); + ast_mutex_init(&sub->lock); + ast_mutex_init(&sub->cx_queue_lock); sub->parent = e; sub->id = i; snprintf(sub->txident, sizeof(sub->txident), "%08x", rand()); @@ -3594,6 +3599,9 @@ if (e) { if (!ep_reload) { memset(e, 0, sizeof(struct mgcp_endpoint)); + ast_mutex_init(&e->lock); + ast_mutex_init(&e->rqnt_queue_lock); + ast_mutex_init(&e->cmd_queue_lock); strncpy(e->name, v->value, sizeof(e->name) - 1); e->needaudit = 1; } @@ -3633,8 +3641,6 @@ /* ASSUME we're onhook */ e->hookstate = MGCP_ONHOOK; snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08x", rand()); - ast_mutex_init(&e->rqnt_queue_lock); - ast_mutex_init(&e->cmd_queue_lock); } for (i = 0, sub = NULL; i < MAX_SUBS; i++) { @@ -3652,13 +3658,14 @@ if (!ep_reload) { ast_verbose(VERBOSE_PREFIX_3 "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name); memset(sub, 0, sizeof(struct mgcp_subchannel)); + ast_mutex_init(&sub->lock); + ast_mutex_init(&sub->cx_queue_lock); strncpy(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic) - 1); sub->parent = e; sub->id = i; snprintf(sub->txident, sizeof(sub->txident), "%08x", rand()); sub->cxmode = MGCP_CX_INACTIVE; sub->next = e->sub; - ast_mutex_init(&sub->cx_queue_lock); e->sub = sub; } sub->nat = nat; Index: channels/chan_sip.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v retrieving revision 1.411 diff -u -u -r1.411 chan_sip.c --- channels/chan_sip.c 14 Jun 2004 21:47:08 -0000 1.411 +++ channels/chan_sip.c 15 Jun 2004 02:40:28 -0000 @@ -2023,11 +2023,11 @@ struct sip_pvt *p; p = malloc(sizeof(struct sip_pvt)); - ast_mutex_init(&p->lock); if (!p) return NULL; /* Keep track of stuff */ memset(p, 0, sizeof(struct sip_pvt)); + ast_mutex_init(&p->lock); p->initid = -1; p->autokillid = -1; p->stateid = -1; Index: channels/chan_skinny.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_skinny.c,v retrieving revision 1.46 diff -u -u -r1.46 chan_skinny.c --- channels/chan_skinny.c 14 Jun 2004 21:18:52 -0000 1.46 +++ channels/chan_skinny.c 15 Jun 2004 02:40:28 -0000 @@ -1104,6 +1104,7 @@ l = malloc(sizeof(struct skinny_line));; if (l) { memset(l, 0, sizeof(struct skinny_line)); + ast_mutex_init(&l->lock); strncpy(l->name, v->value, sizeof(l->name) - 1); /* XXX Should we check for uniqueness?? XXX */ @@ -1145,6 +1146,7 @@ if (sub) { ast_verbose(VERBOSE_PREFIX_3 "Allocating Skinny subchannel '%d' on %s@%s\n", i, l->name, d->name); memset(sub, 0, sizeof(struct skinny_subchannel)); + ast_mutex_init(&sub->lock); sub->parent = l; /* Make a call*ID */ sub->callid = callnums; Index: channels/chan_vpb.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_vpb.c,v retrieving revision 1.26 diff -u -u -r1.26 chan_vpb.c --- channels/chan_vpb.c 9 Jun 2004 01:45:08 -0000 1.26 +++ channels/chan_vpb.c 15 Jun 2004 02:40:29 -0000 @@ -279,7 +279,6 @@ bridges[i].fo = fo; bridges[i].c0 = c0; bridges[i].c1 = c1; - ast_mutex_init(&bridges[i].lock); pthread_cond_init(&bridges[i].cond, NULL); } } ast_mutex_unlock(&bridge_lock); @@ -975,8 +974,11 @@ bridges = (vpb_bridge_t *)malloc(max_bridges * sizeof(vpb_bridge_t) ); if(!bridges) ast_log(LOG_ERROR, "Failed to initialize bridges\n"); - else + else { memset(bridges,0,max_bridges * sizeof(vpb_bridge_t)); + for(int i = 0; i < max_bridges; i++ ) + ast_mutex_init(&bridges[i].lock); + } } if(!echo_cancel) { if (model==vpb_model_v4pci) { @@ -1062,6 +1064,7 @@ tmp->vpb_model = vpb_model_v4pci; } + ast_mutex_init(&tmp->owner_lock); ast_mutex_init(&tmp->lock); ast_mutex_init(&tmp->record_lock); ast_mutex_init(&tmp->play_lock); Index: channels/chan_zap.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_zap.c,v retrieving revision 1.268 diff -u -u -r1.268 chan_zap.c --- channels/chan_zap.c 14 Jun 2004 21:40:57 -0000 1.268 +++ channels/chan_zap.c 15 Jun 2004 02:40:30 -0000 @@ -5723,6 +5723,7 @@ return NULL; } memset(tmp, 0, sizeof(struct zt_pvt)); + ast_mutex_init(&tmp->lock); ifcount++; for (x=0;x<3;x++) tmp->subs[x].zfd = -1; @@ -6049,7 +6050,7 @@ tmp->propconfno = -1; } tmp->transfer = transfer; - ast_mutex_init(&tmp->lock); + /* XXX ast_mutex_init(&tmp->lock); */ strncpy(tmp->defcontext,context,sizeof(tmp->defcontext)-1); strncpy(tmp->language, language, sizeof(tmp->language)-1); strncpy(tmp->musicclass, musicclass, sizeof(tmp->musicclass)-1); @@ -8845,11 +8846,11 @@ int load_module(void) { int res; - #ifdef ZAPATA_PRI int y,i; memset(pris, 0, sizeof(pris)); for (y=0;y #include +#include +#include #define AST_PTHREADT_NULL (pthread_t) -1 #define AST_PTHREADT_STOP (pthread_t) -2 @@ -28,13 +30,23 @@ 0x20 } } #endif -#ifdef __FreeBSD__ +#ifdef BSD #ifdef __GNUC__ #define AST_MUTEX_INIT_W_CONSTRUCTORS #else #define AST_MUTEX_INIT_ON_FIRST_USE #endif -#endif /* __FreeBSD__ */ +#endif /* BSD */ + +/* From now on, Asterisk REQUIRES Recursive (not error checking) mutexes + and will not run without them. */ +#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP +#define PTHREAD_MUTEX_INIT_VAULE PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP +#define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE_NP +#else +#define PTHREAD_MUTEX_INIT_VAULE PTHREAD_MUTEX_INITIALIZER +#define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE +#endif /* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */ #ifdef DEBUG_THREADS @@ -47,15 +59,7 @@ #include #include -/* From now on, Asterisk REQUIRES Recursive (not error checking) mutexes - and will not run without them. */ -#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP -#define AST_MUTEX_INIT_VAULE { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, NULL, 0, NULL, 0 } -#define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE_NP -#else -#define AST_MUTEX_INIT_VAULE { PTHREAD_MUTEX_INITIALIZER, NULL, 0, NULL, 0 } -#define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE -#endif /* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */ +#define AST_MUTEX_INIT_VAULE { PTHREAD_MUTEX_INIT_VAULE, NULL, 0, NULL, 0 } struct ast_mutex_info { pthread_mutex_t mutex; @@ -67,26 +71,86 @@ typedef struct ast_mutex_info ast_mutex_t; -static inline int ast_pthread_mutex_init(ast_mutex_t *t, pthread_mutexattr_t *attr) +static inline int __ast_pthread_mutex_init_attr(char *filename, int lineno, char *func, + char* mutex_name, ast_mutex_t *t, + pthread_mutexattr_t *attr) { - t->file = NULL; - t->lineno = 0; - t->func = 0; +#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS + if((t->mutex) != ((pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER)) { + fprintf(stderr, "%s line %d (%s): Error: mutex '%s' is already initialized.\n", + filename, lineno, func, mutex_name); + fprintf(stderr, "%s line %d (%s): Error: previously initialization of mutex '%s'.\n", + t->file, t->lineno, t->func, mutex_name); +#ifdef THREAD_CRASH + DO_THREAD_CRASH; +#endif + return 0; + } +#endif + t->file = filename; + t->lineno = lineno; + t->func = func; t->thread = 0; return pthread_mutex_init(&t->mutex, attr); } -static inline int ast_mutex_init(ast_mutex_t *t) +static inline int __ast_pthread_mutex_init(char *filename, int lineno, char *func, + char* mutex_name, ast_mutex_t *t) { static pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, AST_MUTEX_KIND); - return ast_pthread_mutex_init(t, &attr); + return __ast_pthread_mutex_init_attr(filename, lineno, func, mutex_name, t, &attr); } +#define ast_mutex_init(pmutex) __ast_pthread_mutex_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex) +#define ast_pthread_mutex_init(pmutex,attr) __ast_pthread_mutex_init_attr(__FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex, attr) + +static inline int __ast_pthread_mutex_destroy(char *filename, int lineno, char *func, + char* mutex_name, ast_mutex_t *t) +{ + int res; +#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS + if((t->mutex) == ((pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER)) { + fprintf(stderr, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n", + filename, lineno, func, mutex_name); + } +#endif + res = pthread_mutex_trylock(&t->mutex); + switch( res ) { + case 0: + pthread_mutex_unlock(&t->mutex); + break; + case EINVAL: + fprintf(stderr, "%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n", + filename, lineno, func, mutex_name); + break; + case EBUSY: + fprintf(stderr, "%s line %d (%s): Error: attemp to destroy locked mutex '%s'.\n", + filename, lineno, func, mutex_name); + fprintf(stderr, "%s line %d (%s): Error: '%s' was locked here.\n", + t->file, t->lineno, t->func, mutex_name); + break; + } + res = pthread_mutex_destroy(&t->mutex); + if (res) + fprintf(stderr, "%s line %d (%s): Error destroying mutex: %s\n", + filename, lineno, func, strerror(res)); +#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP + else + t->mutex = PTHREAD_MUTEX_INIT_VAULE; +#endif + t->file = filename; + t->lineno = lineno; + t->func = func; + return res; +} + +#define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a) + #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) /* if AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope - constrictors/destructors to create/destroy mutexes. */ + constrictors/destructors to create/destroy mutexes. */ #define __AST_MUTEX_DEFINE(scope,mutex) \ scope ast_mutex_t mutex = AST_MUTEX_INIT_VAULE; \ static void __attribute__ ((constructor)) init_##mutex(void) \ @@ -97,7 +161,7 @@ { \ ast_mutex_destroy(&mutex); \ } -#elif defined(AST_MUTEX_INIT_ON_FIRST_USE) || !defined(AST_MUTEX_INIT_W_CONSTRUCTORS) +#elif defined(AST_MUTEX_INIT_ON_FIRST_USE) /* if AST_MUTEX_INIT_ON_FIRST_USE is defined, mutexes are created on first use. The performance impact on FreeBSD should be small since the pthreads library does this itself to initialize errror checking @@ -105,16 +169,46 @@ does the initialization itself on first use. */ #define __AST_MUTEX_DEFINE(scope,mutex) \ scope ast_mutex_t mutex = AST_MUTEX_INIT_VAULE +#else /* AST_MUTEX_INIT_W_CONSTRUCTORS */ +/* By default, use static initialization of mutexes.*/ +#define __AST_MUTEX_DEFINE(scope,mutex) \ + scope ast_mutex_t mutex = AST_MUTEX_INIT_VAULE #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ -static inline int __ast_pthread_mutex_lock(char *filename, int lineno, char *func, ast_mutex_t *t) + + +static inline int __ast_pthread_mutex_lock(char *filename, int lineno, char *func, + char* mutex_name, ast_mutex_t *t) { int res; -#ifdef AST_MUTEX_INIT_ON_FIRST_USE - if(*t->mutex == (ast_mutex_t)AST_MUTEX_KIND) - ast_mutex_init(t->mutex); +#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE) + if((t->mutex) == ((pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER)) { +#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS + fprintf(stderr, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n", + filename, lineno, func, mutex_name); #endif - res = pthread_mutex_lock(&t->mutex); + ast_mutex_init(t); + } +#endif /* definded(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE) */ +#ifdef DETECT_DEADLOCKS + { + time_t seconds seconds = time(NULL); + do { + res = pthread_mutex_trylock(&t->mutex); + if(res == EBUSY) { + if((time(NULL) - seconds) % 5) { + fprintf(stderr, "%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n", + filename, lineno, func, (time(NULL) - seconds), mutex_name); + fprintf(stderr, "%s line %d (%s): '%s' was locked here.\n", + t->file, t->lineno, t->func, mutex_name); + } + usleep(200); + } + } while (res == EBUSY); + } +#else + res = pthread_mutex_lock(&t->mutex); +#endif /* DETECT_DEADLOCKS */ if (!res) { t->file = filename; t->lineno = lineno; @@ -130,14 +224,21 @@ return res; } -#define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a) +#define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a) -static inline int __ast_pthread_mutex_trylock(char *filename, int lineno, char *func, ast_mutex_t *t) { +static inline int __ast_pthread_mutex_trylock(char *filename, int lineno, char *func, + char* mutex_name, ast_mutex_t *t) +{ int res; -#ifdef AST_MUTEX_INIT_ON_FIRST_USE - if(*t->mutex == (ast_mutex_t)AST_MUTEX_KIND) - ast_mutex_init(t->mutex); +#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE) + if((t->mutex) == ((pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER)) { +#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS + fprintf(stderr, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n", + filename, lineno, func, mutex_name); #endif + ast_mutex_init(t); + } +#endif /* definded(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE) */ res = pthread_mutex_trylock(&t->mutex); if (!res) { t->file = filename; @@ -148,10 +249,17 @@ return res; } -#define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a) +#define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a) -static inline int __ast_pthread_mutex_unlock(char *filename, int lineno, char *func, ast_mutex_t *t) { +static inline int __ast_pthread_mutex_unlock(char *filename, int lineno, char *func, + char* mutex_name, ast_mutex_t *t) { int res; +#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS + if((t->mutex) == ((pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER)) { + fprintf(stderr, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n", + filename, lineno, func, mutex_name); + } +#endif /* Assumes lock is actually held */ t->file = NULL; t->lineno = 0; @@ -168,23 +276,7 @@ return res; } -#define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a) - -static inline int __ast_pthread_mutex_destroy(char *filename, int lineno, char *func, ast_mutex_t *t) -{ - int res; - t->file = NULL; - t->lineno = 0; - t->func = NULL; - t->thread = 0; - res = pthread_mutex_destroy(&t->mutex); - if (res) - fprintf(stderr, "%s line %d (%s): Error destroying mutex: %s\n", - filename, lineno, func, strerror(res)); - return res; -} - -#define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, a) +#define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a) #define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t #define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock @@ -195,15 +287,9 @@ #else /* DEBUG_THREADS */ -/* From now on, Asterisk REQUIRES Recursive (not error checking) mutexes - and will not run without them. */ -#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP -#define AST_MUTEX_INIT_VAULE PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP -#define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE_NP -#else -#define AST_MUTEX_INIT_VAULE PTHREAD_MUTEX_INITIALIZER -#define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE -#endif /* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */ + +#define AST_MUTEX_INIT_VAULE PTHREAD_MUTEX_INIT_VAULE + typedef pthread_mutex_t ast_mutex_t; @@ -220,7 +306,7 @@ #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) /* if AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope - constrictors/destructors to create/destroy mutexes. */ + constrictors/destructors to create/destroy mutexes. */ #define __AST_MUTEX_DEFINE(scope,mutex) \ scope ast_mutex_t mutex = AST_MUTEX_INIT_VAULE; \ static void __attribute__ ((constructor)) init_##mutex(void) \ @@ -268,7 +354,6 @@ #define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static,mutex) #define AST_MUTEX_DEFINE_EXPORTED(mutex) __AST_MUTEX_DEFINE(/**/,mutex) - #define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__ #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__ Index: include/asterisk/utils.h =================================================================== RCS file: /usr/cvsroot/asterisk/include/asterisk/utils.h,v retrieving revision 1.2 diff -u -u -r1.2 utils.h --- include/asterisk/utils.h 9 May 2004 08:22:15 -0000 1.2 +++ include/asterisk/utils.h 15 Jun 2004 02:40:32 -0000 @@ -26,4 +26,6 @@ extern struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp); +extern int test_for_thread_safety(void); + #endif