lock.c 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 1999 - 2010, Digium, Inc.
  5. *
  6. * Mark Spencer <markster@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*! \file
  19. *
  20. * \brief General Asterisk locking.
  21. */
  22. /*** MODULEINFO
  23. <support_level>core</support_level>
  24. ***/
  25. #include "asterisk.h"
  26. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  27. #include "asterisk/utils.h"
  28. #include "asterisk/lock.h"
  29. /* Allow direct use of pthread_mutex_* / pthread_cond_* */
  30. #undef pthread_mutex_init
  31. #undef pthread_mutex_destroy
  32. #undef pthread_mutex_lock
  33. #undef pthread_mutex_trylock
  34. #undef pthread_mutex_t
  35. #undef pthread_mutex_unlock
  36. #undef pthread_cond_init
  37. #undef pthread_cond_signal
  38. #undef pthread_cond_broadcast
  39. #undef pthread_cond_destroy
  40. #undef pthread_cond_wait
  41. #undef pthread_cond_timedwait
  42. #if defined(DEBUG_THREADS)
  43. #define log_mutex_error(canlog, ...) \
  44. do { \
  45. if (canlog) { \
  46. ast_log(LOG_ERROR, __VA_ARGS__); \
  47. } else { \
  48. fprintf(stderr, __VA_ARGS__); \
  49. } \
  50. } while (0)
  51. #endif
  52. #if defined(DEBUG_THREADS) && defined(HAVE_BKTR)
  53. static void __dump_backtrace(struct ast_bt *bt, int canlog)
  54. {
  55. char **strings;
  56. ssize_t i;
  57. strings = backtrace_symbols(bt->addresses, bt->num_frames);
  58. for (i = 0; i < bt->num_frames; i++) {
  59. log_mutex_error(canlog, "%s\n", strings[i]);
  60. }
  61. ast_std_free(strings);
  62. }
  63. #endif /* defined(DEBUG_THREADS) && defined(HAVE_BKTR) */
  64. #ifdef DEBUG_THREADS
  65. AST_MUTEX_DEFINE_STATIC(reentrancy_lock);
  66. static inline struct ast_lock_track *ast_get_reentrancy(struct ast_lock_track **plt,
  67. struct ast_lock_track_flags *flags, int no_setup)
  68. {
  69. pthread_mutexattr_t reentr_attr;
  70. struct ast_lock_track *lt;
  71. if (!flags->tracking || flags->setup) {
  72. return *plt;
  73. }
  74. pthread_mutex_lock(&reentrancy_lock.mutex);
  75. if (*plt) {
  76. pthread_mutex_unlock(&reentrancy_lock.mutex);
  77. return *plt;
  78. }
  79. if (no_setup) {
  80. pthread_mutex_unlock(&reentrancy_lock.mutex);
  81. return NULL;
  82. }
  83. lt = *plt = ast_std_calloc(1, sizeof(*lt));
  84. if (!lt) {
  85. fprintf(stderr, "%s: Failed to allocate lock tracking\n", __func__);
  86. #if defined(DO_CRASH) || defined(THREAD_CRASH)
  87. abort();
  88. #else
  89. pthread_mutex_unlock(&reentrancy_lock.mutex);
  90. return NULL;
  91. #endif
  92. }
  93. pthread_mutexattr_init(&reentr_attr);
  94. pthread_mutexattr_settype(&reentr_attr, AST_MUTEX_KIND);
  95. pthread_mutex_init(&lt->reentr_mutex, &reentr_attr);
  96. pthread_mutexattr_destroy(&reentr_attr);
  97. flags->setup = 1;
  98. pthread_mutex_unlock(&reentrancy_lock.mutex);
  99. return lt;
  100. }
  101. static inline void delete_reentrancy_cs(struct ast_lock_track **plt)
  102. {
  103. struct ast_lock_track *lt;
  104. if (*plt) {
  105. lt = *plt;
  106. *plt = NULL;
  107. pthread_mutex_destroy(&lt->reentr_mutex);
  108. ast_std_free(lt);
  109. }
  110. }
  111. #endif /* DEBUG_THREADS */
  112. int __ast_pthread_mutex_init(int tracking, const char *filename, int lineno, const char *func,
  113. const char *mutex_name, ast_mutex_t *t)
  114. {
  115. int res;
  116. pthread_mutexattr_t attr;
  117. #ifdef DEBUG_THREADS
  118. #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
  119. if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
  120. int canlog = tracking && strcmp(filename, "logger.c");
  121. log_mutex_error(canlog, "%s line %d (%s): NOTICE: mutex '%s' is already initialized.\n",
  122. filename, lineno, func, mutex_name);
  123. DO_THREAD_CRASH;
  124. return EBUSY;
  125. }
  126. #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
  127. t->track = NULL;
  128. t->flags.tracking = tracking;
  129. t->flags.setup = 0;
  130. #endif /* DEBUG_THREADS */
  131. pthread_mutexattr_init(&attr);
  132. pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
  133. res = pthread_mutex_init(&t->mutex, &attr);
  134. pthread_mutexattr_destroy(&attr);
  135. return res;
  136. }
  137. int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func,
  138. const char *mutex_name, ast_mutex_t *t)
  139. {
  140. int res;
  141. #ifdef DEBUG_THREADS
  142. struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 1);
  143. int canlog = t->flags.tracking && strcmp(filename, "logger.c");
  144. #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
  145. if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
  146. /* Don't try to uninitialize an uninitialized mutex
  147. * This may have no effect on linux
  148. * but it always generates a core on *BSD when
  149. * linked with libpthread.
  150. * This is not an error condition if the mutex is created on the fly.
  151. */
  152. log_mutex_error(canlog, "%s line %d (%s): NOTICE: mutex '%s' is uninitialized.\n",
  153. filename, lineno, func, mutex_name);
  154. DO_THREAD_CRASH;
  155. res = EINVAL;
  156. goto lt_cleanup;
  157. }
  158. #endif
  159. res = pthread_mutex_trylock(&t->mutex);
  160. switch (res) {
  161. case 0:
  162. pthread_mutex_unlock(&t->mutex);
  163. break;
  164. case EINVAL:
  165. log_mutex_error(canlog, "%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
  166. filename, lineno, func, mutex_name);
  167. break;
  168. case EBUSY:
  169. log_mutex_error(canlog, "%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
  170. filename, lineno, func, mutex_name);
  171. if (lt) {
  172. ast_reentrancy_lock(lt);
  173. log_mutex_error(canlog, "%s line %d (%s): Error: '%s' was locked here.\n",
  174. lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name);
  175. #ifdef HAVE_BKTR
  176. __dump_backtrace(&lt->backtrace[ROFFSET], canlog);
  177. #endif
  178. ast_reentrancy_unlock(lt);
  179. }
  180. break;
  181. }
  182. #endif /* DEBUG_THREADS */
  183. res = pthread_mutex_destroy(&t->mutex);
  184. #ifdef DEBUG_THREADS
  185. if (res) {
  186. log_mutex_error(canlog, "%s line %d (%s): Error destroying mutex %s: %s\n",
  187. filename, lineno, func, mutex_name, strerror(res));
  188. }
  189. #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
  190. lt_cleanup:
  191. #endif
  192. if (lt) {
  193. ast_reentrancy_lock(lt);
  194. lt->file[0] = filename;
  195. lt->lineno[0] = lineno;
  196. lt->func[0] = func;
  197. lt->reentrancy = 0;
  198. lt->thread_id[0] = 0;
  199. #ifdef HAVE_BKTR
  200. memset(&lt->backtrace[0], 0, sizeof(lt->backtrace[0]));
  201. #endif
  202. ast_reentrancy_unlock(lt);
  203. delete_reentrancy_cs(&t->track);
  204. }
  205. #endif /* DEBUG_THREADS */
  206. return res;
  207. }
  208. int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func,
  209. const char* mutex_name, ast_mutex_t *t)
  210. {
  211. int res;
  212. #ifdef DEBUG_THREADS
  213. struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0);
  214. int canlog = t->flags.tracking && strcmp(filename, "logger.c");
  215. #ifdef HAVE_BKTR
  216. struct ast_bt *bt = NULL;
  217. #endif
  218. if (lt) {
  219. #ifdef HAVE_BKTR
  220. struct ast_bt tmp;
  221. /* The implementation of backtrace() may have its own locks.
  222. * Capture the backtrace outside of the reentrancy lock to
  223. * avoid deadlocks. See ASTERISK-22455. */
  224. ast_bt_get_addresses(&tmp);
  225. ast_reentrancy_lock(lt);
  226. if (lt->reentrancy < AST_MAX_REENTRANCY) {
  227. lt->backtrace[lt->reentrancy] = tmp;
  228. bt = &lt->backtrace[lt->reentrancy];
  229. }
  230. ast_reentrancy_unlock(lt);
  231. ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
  232. #else
  233. ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t);
  234. #endif
  235. }
  236. #endif /* DEBUG_THREADS */
  237. #if defined(DETECT_DEADLOCKS) && defined(DEBUG_THREADS)
  238. {
  239. time_t seconds = time(NULL);
  240. time_t wait_time, reported_wait = 0;
  241. do {
  242. #ifdef HAVE_MTX_PROFILE
  243. ast_mark(mtx_prof, 1);
  244. #endif
  245. res = pthread_mutex_trylock(&t->mutex);
  246. #ifdef HAVE_MTX_PROFILE
  247. ast_mark(mtx_prof, 0);
  248. #endif
  249. if (res == EBUSY) {
  250. wait_time = time(NULL) - seconds;
  251. if (wait_time > reported_wait && (wait_time % 5) == 0) {
  252. log_mutex_error(canlog, "%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
  253. filename, lineno, func, (int) wait_time, mutex_name);
  254. if (lt) {
  255. ast_reentrancy_lock(lt);
  256. #ifdef HAVE_BKTR
  257. __dump_backtrace(&lt->backtrace[lt->reentrancy], canlog);
  258. #endif
  259. log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
  260. lt->file[ROFFSET], lt->lineno[ROFFSET],
  261. lt->func[ROFFSET], mutex_name);
  262. #ifdef HAVE_BKTR
  263. __dump_backtrace(&lt->backtrace[ROFFSET], canlog);
  264. #endif
  265. ast_reentrancy_unlock(lt);
  266. }
  267. reported_wait = wait_time;
  268. }
  269. usleep(200);
  270. }
  271. } while (res == EBUSY);
  272. }
  273. #else /* !DETECT_DEADLOCKS || !DEBUG_THREADS */
  274. #ifdef HAVE_MTX_PROFILE
  275. ast_mark(mtx_prof, 1);
  276. res = pthread_mutex_trylock(&t->mutex);
  277. ast_mark(mtx_prof, 0);
  278. if (res)
  279. #endif
  280. res = pthread_mutex_lock(&t->mutex);
  281. #endif /* !DETECT_DEADLOCKS || !DEBUG_THREADS */
  282. #ifdef DEBUG_THREADS
  283. if (lt && !res) {
  284. ast_reentrancy_lock(lt);
  285. if (lt->reentrancy < AST_MAX_REENTRANCY) {
  286. lt->file[lt->reentrancy] = filename;
  287. lt->lineno[lt->reentrancy] = lineno;
  288. lt->func[lt->reentrancy] = func;
  289. lt->thread_id[lt->reentrancy] = pthread_self();
  290. lt->reentrancy++;
  291. } else {
  292. log_mutex_error(canlog, "%s line %d (%s): '%s' really deep reentrancy!\n",
  293. filename, lineno, func, mutex_name);
  294. }
  295. ast_reentrancy_unlock(lt);
  296. ast_mark_lock_acquired(t);
  297. } else if (lt) {
  298. #ifdef HAVE_BKTR
  299. if (lt->reentrancy) {
  300. ast_reentrancy_lock(lt);
  301. bt = &lt->backtrace[lt->reentrancy-1];
  302. ast_reentrancy_unlock(lt);
  303. } else {
  304. bt = NULL;
  305. }
  306. ast_remove_lock_info(t, bt);
  307. #else
  308. ast_remove_lock_info(t);
  309. #endif
  310. }
  311. if (res) {
  312. log_mutex_error(canlog, "%s line %d (%s): Error obtaining mutex: %s\n",
  313. filename, lineno, func, strerror(res));
  314. DO_THREAD_CRASH;
  315. }
  316. #endif /* DEBUG_THREADS */
  317. return res;
  318. }
  319. int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func,
  320. const char* mutex_name, ast_mutex_t *t)
  321. {
  322. int res;
  323. #ifdef DEBUG_THREADS
  324. struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0);
  325. int canlog = t->flags.tracking && strcmp(filename, "logger.c");
  326. #ifdef HAVE_BKTR
  327. struct ast_bt *bt = NULL;
  328. #endif
  329. if (lt) {
  330. #ifdef HAVE_BKTR
  331. struct ast_bt tmp;
  332. /* The implementation of backtrace() may have its own locks.
  333. * Capture the backtrace outside of the reentrancy lock to
  334. * avoid deadlocks. See ASTERISK-22455. */
  335. ast_bt_get_addresses(&tmp);
  336. ast_reentrancy_lock(lt);
  337. if (lt->reentrancy < AST_MAX_REENTRANCY) {
  338. lt->backtrace[lt->reentrancy] = tmp;
  339. bt = &lt->backtrace[lt->reentrancy];
  340. }
  341. ast_reentrancy_unlock(lt);
  342. ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
  343. #else
  344. ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t);
  345. #endif
  346. }
  347. #endif /* DEBUG_THREADS */
  348. res = pthread_mutex_trylock(&t->mutex);
  349. #ifdef DEBUG_THREADS
  350. if (lt && !res) {
  351. ast_reentrancy_lock(lt);
  352. if (lt->reentrancy < AST_MAX_REENTRANCY) {
  353. lt->file[lt->reentrancy] = filename;
  354. lt->lineno[lt->reentrancy] = lineno;
  355. lt->func[lt->reentrancy] = func;
  356. lt->thread_id[lt->reentrancy] = pthread_self();
  357. lt->reentrancy++;
  358. } else {
  359. log_mutex_error(canlog, "%s line %d (%s): '%s' really deep reentrancy!\n",
  360. filename, lineno, func, mutex_name);
  361. }
  362. ast_reentrancy_unlock(lt);
  363. ast_mark_lock_acquired(t);
  364. } else if (lt) {
  365. ast_mark_lock_failed(t);
  366. }
  367. #endif /* DEBUG_THREADS */
  368. return res;
  369. }
  370. int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func,
  371. const char *mutex_name, ast_mutex_t *t)
  372. {
  373. int res;
  374. #ifdef DEBUG_THREADS
  375. struct ast_lock_track *lt = NULL;
  376. int canlog = t->flags.tracking && strcmp(filename, "logger.c");
  377. #ifdef HAVE_BKTR
  378. struct ast_bt *bt = NULL;
  379. #endif
  380. #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
  381. if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
  382. log_mutex_error(canlog, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
  383. filename, lineno, func, mutex_name);
  384. DO_THREAD_CRASH;
  385. return EINVAL;
  386. }
  387. #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
  388. lt = ast_get_reentrancy(&t->track, &t->flags, 0);
  389. if (lt) {
  390. ast_reentrancy_lock(lt);
  391. if (lt->reentrancy && (lt->thread_id[ROFFSET] != pthread_self())) {
  392. log_mutex_error(canlog, "%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
  393. filename, lineno, func, mutex_name);
  394. log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
  395. lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name);
  396. #ifdef HAVE_BKTR
  397. __dump_backtrace(&lt->backtrace[ROFFSET], canlog);
  398. #endif
  399. DO_THREAD_CRASH;
  400. }
  401. if (--lt->reentrancy < 0) {
  402. log_mutex_error(canlog, "%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
  403. filename, lineno, func, mutex_name);
  404. lt->reentrancy = 0;
  405. }
  406. if (lt->reentrancy < AST_MAX_REENTRANCY) {
  407. lt->file[lt->reentrancy] = NULL;
  408. lt->lineno[lt->reentrancy] = 0;
  409. lt->func[lt->reentrancy] = NULL;
  410. lt->thread_id[lt->reentrancy] = 0;
  411. }
  412. #ifdef HAVE_BKTR
  413. if (lt->reentrancy) {
  414. bt = &lt->backtrace[lt->reentrancy - 1];
  415. }
  416. #endif
  417. ast_reentrancy_unlock(lt);
  418. #ifdef HAVE_BKTR
  419. ast_remove_lock_info(t, bt);
  420. #else
  421. ast_remove_lock_info(t);
  422. #endif
  423. }
  424. #endif /* DEBUG_THREADS */
  425. res = pthread_mutex_unlock(&t->mutex);
  426. #ifdef DEBUG_THREADS
  427. if (res) {
  428. log_mutex_error(canlog, "%s line %d (%s): Error releasing mutex: %s\n",
  429. filename, lineno, func, strerror(res));
  430. DO_THREAD_CRASH;
  431. }
  432. #endif /* DEBUG_THREADS */
  433. return res;
  434. }
  435. int __ast_cond_init(const char *filename, int lineno, const char *func,
  436. const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr)
  437. {
  438. return pthread_cond_init(cond, cond_attr);
  439. }
  440. int __ast_cond_signal(const char *filename, int lineno, const char *func,
  441. const char *cond_name, ast_cond_t *cond)
  442. {
  443. return pthread_cond_signal(cond);
  444. }
  445. int __ast_cond_broadcast(const char *filename, int lineno, const char *func,
  446. const char *cond_name, ast_cond_t *cond)
  447. {
  448. return pthread_cond_broadcast(cond);
  449. }
  450. int __ast_cond_destroy(const char *filename, int lineno, const char *func,
  451. const char *cond_name, ast_cond_t *cond)
  452. {
  453. return pthread_cond_destroy(cond);
  454. }
  455. #ifdef DEBUG_THREADS
  456. static void restore_lock_tracking(struct ast_lock_track *lt, struct ast_lock_track *lt_saved)
  457. {
  458. ast_reentrancy_lock(lt);
  459. /*
  460. * The following code must match the struct ast_lock_track
  461. * definition with the explicit exception of the reentr_mutex
  462. * member.
  463. */
  464. memcpy(lt->file, lt_saved->file, sizeof(lt->file));
  465. memcpy(lt->lineno, lt_saved->lineno, sizeof(lt->lineno));
  466. lt->reentrancy = lt_saved->reentrancy;
  467. memcpy(lt->func, lt_saved->func, sizeof(lt->func));
  468. memcpy(lt->thread_id, lt_saved->thread_id, sizeof(lt->thread_id));
  469. #ifdef HAVE_BKTR
  470. memcpy(lt->backtrace, lt_saved->backtrace, sizeof(lt->backtrace));
  471. #endif
  472. ast_reentrancy_unlock(lt);
  473. }
  474. #endif /* DEBUG_THREADS */
  475. int __ast_cond_wait(const char *filename, int lineno, const char *func,
  476. const char *cond_name, const char *mutex_name,
  477. ast_cond_t *cond, ast_mutex_t *t)
  478. {
  479. int res;
  480. #ifdef DEBUG_THREADS
  481. struct ast_lock_track *lt = NULL;
  482. struct ast_lock_track lt_orig;
  483. int canlog = t->flags.tracking && strcmp(filename, "logger.c");
  484. #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
  485. if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
  486. log_mutex_error(canlog, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
  487. filename, lineno, func, mutex_name);
  488. DO_THREAD_CRASH;
  489. return EINVAL;
  490. }
  491. #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
  492. lt = ast_get_reentrancy(&t->track, &t->flags, 0);
  493. if (lt) {
  494. ast_reentrancy_lock(lt);
  495. if (lt->reentrancy && (lt->thread_id[ROFFSET] != pthread_self())) {
  496. log_mutex_error(canlog, "%s line %d (%s): attempted wait using mutex '%s' without owning it!\n",
  497. filename, lineno, func, mutex_name);
  498. log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
  499. lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name);
  500. #ifdef HAVE_BKTR
  501. __dump_backtrace(&lt->backtrace[ROFFSET], canlog);
  502. #endif
  503. DO_THREAD_CRASH;
  504. } else if (lt->reentrancy <= 0) {
  505. log_mutex_error(canlog, "%s line %d (%s): attempted wait using an unlocked mutex '%s'\n",
  506. filename, lineno, func, mutex_name);
  507. DO_THREAD_CRASH;
  508. }
  509. /* Waiting on a condition completely suspends a recursive mutex,
  510. * even if it's been recursively locked multiple times. Make a
  511. * copy of the lock tracking, and reset reentrancy to zero */
  512. lt_orig = *lt;
  513. lt->reentrancy = 0;
  514. ast_reentrancy_unlock(lt);
  515. ast_suspend_lock_info(t);
  516. }
  517. #endif /* DEBUG_THREADS */
  518. res = pthread_cond_wait(cond, &t->mutex);
  519. #ifdef DEBUG_THREADS
  520. if (res) {
  521. log_mutex_error(canlog, "%s line %d (%s): Error waiting on condition mutex '%s'\n",
  522. filename, lineno, func, strerror(res));
  523. DO_THREAD_CRASH;
  524. } else if (lt) {
  525. restore_lock_tracking(lt, &lt_orig);
  526. ast_restore_lock_info(t);
  527. }
  528. #endif /* DEBUG_THREADS */
  529. return res;
  530. }
  531. int __ast_cond_timedwait(const char *filename, int lineno, const char *func,
  532. const char *cond_name, const char *mutex_name, ast_cond_t *cond,
  533. ast_mutex_t *t, const struct timespec *abstime)
  534. {
  535. int res;
  536. #ifdef DEBUG_THREADS
  537. struct ast_lock_track *lt = NULL;
  538. struct ast_lock_track lt_orig;
  539. int canlog = t->flags.tracking && strcmp(filename, "logger.c");
  540. #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
  541. if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
  542. log_mutex_error(canlog, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
  543. filename, lineno, func, mutex_name);
  544. DO_THREAD_CRASH;
  545. return EINVAL;
  546. }
  547. #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
  548. lt = ast_get_reentrancy(&t->track, &t->flags, 0);
  549. if (lt) {
  550. ast_reentrancy_lock(lt);
  551. if (lt->reentrancy && (lt->thread_id[ROFFSET] != pthread_self())) {
  552. log_mutex_error(canlog, "%s line %d (%s): attempted wait using mutex '%s' without owning it!\n",
  553. filename, lineno, func, mutex_name);
  554. log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
  555. lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name);
  556. #ifdef HAVE_BKTR
  557. __dump_backtrace(&lt->backtrace[ROFFSET], canlog);
  558. #endif
  559. DO_THREAD_CRASH;
  560. } else if (lt->reentrancy <= 0) {
  561. log_mutex_error(canlog, "%s line %d (%s): attempted wait using an unlocked mutex '%s'\n",
  562. filename, lineno, func, mutex_name);
  563. DO_THREAD_CRASH;
  564. }
  565. /* Waiting on a condition completely suspends a recursive mutex,
  566. * even if it's been recursively locked multiple times. Make a
  567. * copy of the lock tracking, and reset reentrancy to zero */
  568. lt_orig = *lt;
  569. lt->reentrancy = 0;
  570. ast_reentrancy_unlock(lt);
  571. ast_suspend_lock_info(t);
  572. }
  573. #endif /* DEBUG_THREADS */
  574. res = pthread_cond_timedwait(cond, &t->mutex, abstime);
  575. #ifdef DEBUG_THREADS
  576. if (res && (res != ETIMEDOUT)) {
  577. log_mutex_error(canlog, "%s line %d (%s): Error waiting on condition mutex '%s'\n",
  578. filename, lineno, func, strerror(res));
  579. DO_THREAD_CRASH;
  580. } else if (lt) {
  581. restore_lock_tracking(lt, &lt_orig);
  582. ast_restore_lock_info(t);
  583. }
  584. #endif /* DEBUG_THREADS */
  585. return res;
  586. }
  587. int __ast_rwlock_init(int tracking, const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t)
  588. {
  589. int res;
  590. pthread_rwlockattr_t attr;
  591. #ifdef DEBUG_THREADS
  592. #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
  593. if (t->lock != ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
  594. int canlog = tracking && strcmp(filename, "logger.c");
  595. log_mutex_error(canlog, "%s line %d (%s): Warning: rwlock '%s' is already initialized.\n",
  596. filename, lineno, func, rwlock_name);
  597. DO_THREAD_CRASH;
  598. return EBUSY;
  599. }
  600. #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
  601. t->track = NULL;
  602. t->flags.tracking = tracking;
  603. t->flags.setup = 0;
  604. #endif /* DEBUG_THREADS */
  605. pthread_rwlockattr_init(&attr);
  606. #ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
  607. pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
  608. #endif
  609. res = pthread_rwlock_init(&t->lock, &attr);
  610. pthread_rwlockattr_destroy(&attr);
  611. return res;
  612. }
  613. int __ast_rwlock_destroy(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t)
  614. {
  615. int res;
  616. #ifdef DEBUG_THREADS
  617. struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 1);
  618. int canlog = t->flags.tracking && strcmp(filename, "logger.c");
  619. #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
  620. if (t->lock == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
  621. log_mutex_error(canlog, "%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
  622. filename, lineno, func, rwlock_name);
  623. DO_THREAD_CRASH;
  624. res = EINVAL;
  625. goto lt_cleanup;
  626. }
  627. #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
  628. #endif /* DEBUG_THREADS */
  629. res = pthread_rwlock_destroy(&t->lock);
  630. #ifdef DEBUG_THREADS
  631. if (res) {
  632. log_mutex_error(canlog, "%s line %d (%s): Error destroying rwlock %s: %s\n",
  633. filename, lineno, func, rwlock_name, strerror(res));
  634. }
  635. #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
  636. lt_cleanup:
  637. #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
  638. if (lt) {
  639. ast_reentrancy_lock(lt);
  640. lt->file[0] = filename;
  641. lt->lineno[0] = lineno;
  642. lt->func[0] = func;
  643. lt->reentrancy = 0;
  644. lt->thread_id[0] = 0;
  645. #ifdef HAVE_BKTR
  646. memset(&lt->backtrace[0], 0, sizeof(lt->backtrace[0]));
  647. #endif
  648. ast_reentrancy_unlock(lt);
  649. delete_reentrancy_cs(&t->track);
  650. }
  651. #endif /* DEBUG_THREADS */
  652. return res;
  653. }
  654. int __ast_rwlock_unlock(const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name)
  655. {
  656. int res;
  657. #ifdef DEBUG_THREADS
  658. struct ast_lock_track *lt = NULL;
  659. int canlog = t->flags.tracking && strcmp(filename, "logger.c");
  660. #ifdef HAVE_BKTR
  661. struct ast_bt *bt = NULL;
  662. #endif
  663. int lock_found = 0;
  664. #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
  665. if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
  666. log_mutex_error(canlog, "%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
  667. filename, line, func, name);
  668. DO_THREAD_CRASH;
  669. return EINVAL;
  670. }
  671. #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
  672. lt = ast_get_reentrancy(&t->track, &t->flags, 0);
  673. if (lt) {
  674. ast_reentrancy_lock(lt);
  675. if (lt->reentrancy) {
  676. int i;
  677. pthread_t self = pthread_self();
  678. for (i = lt->reentrancy - 1; i >= 0; --i) {
  679. if (lt->thread_id[i] == self) {
  680. lock_found = 1;
  681. if (i != lt->reentrancy - 1) {
  682. lt->file[i] = lt->file[lt->reentrancy - 1];
  683. lt->lineno[i] = lt->lineno[lt->reentrancy - 1];
  684. lt->func[i] = lt->func[lt->reentrancy - 1];
  685. lt->thread_id[i] = lt->thread_id[lt->reentrancy - 1];
  686. }
  687. #ifdef HAVE_BKTR
  688. bt = &lt->backtrace[i];
  689. #endif
  690. lt->file[lt->reentrancy - 1] = NULL;
  691. lt->lineno[lt->reentrancy - 1] = 0;
  692. lt->func[lt->reentrancy - 1] = NULL;
  693. lt->thread_id[lt->reentrancy - 1] = AST_PTHREADT_NULL;
  694. break;
  695. }
  696. }
  697. }
  698. if (lock_found && --lt->reentrancy < 0) {
  699. log_mutex_error(canlog, "%s line %d (%s): rwlock '%s' freed more times than we've locked!\n",
  700. filename, line, func, name);
  701. lt->reentrancy = 0;
  702. }
  703. ast_reentrancy_unlock(lt);
  704. #ifdef HAVE_BKTR
  705. ast_remove_lock_info(t, bt);
  706. #else
  707. ast_remove_lock_info(t);
  708. #endif
  709. }
  710. #endif /* DEBUG_THREADS */
  711. res = pthread_rwlock_unlock(&t->lock);
  712. #ifdef DEBUG_THREADS
  713. if (res) {
  714. log_mutex_error(canlog, "%s line %d (%s): Error releasing rwlock: %s\n",
  715. filename, line, func, strerror(res));
  716. DO_THREAD_CRASH;
  717. }
  718. #endif /* DEBUG_THREADS */
  719. return res;
  720. }
  721. int __ast_rwlock_rdlock(const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name)
  722. {
  723. int res;
  724. #ifdef DEBUG_THREADS
  725. struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0);
  726. int canlog = t->flags.tracking && strcmp(filename, "logger.c");
  727. #ifdef HAVE_BKTR
  728. struct ast_bt *bt = NULL;
  729. #endif
  730. if (lt) {
  731. #ifdef HAVE_BKTR
  732. struct ast_bt tmp;
  733. /* The implementation of backtrace() may have its own locks.
  734. * Capture the backtrace outside of the reentrancy lock to
  735. * avoid deadlocks. See ASTERISK-22455. */
  736. ast_bt_get_addresses(&tmp);
  737. ast_reentrancy_lock(lt);
  738. if (lt->reentrancy < AST_MAX_REENTRANCY) {
  739. lt->backtrace[lt->reentrancy] = tmp;
  740. bt = &lt->backtrace[lt->reentrancy];
  741. }
  742. ast_reentrancy_unlock(lt);
  743. ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t, bt);
  744. #else
  745. ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t);
  746. #endif
  747. }
  748. #endif /* DEBUG_THREADS */
  749. #if defined(DETECT_DEADLOCKS) && defined(DEBUG_THREADS)
  750. {
  751. time_t seconds = time(NULL);
  752. time_t wait_time, reported_wait = 0;
  753. do {
  754. res = pthread_rwlock_tryrdlock(&t->lock);
  755. if (res == EBUSY) {
  756. wait_time = time(NULL) - seconds;
  757. if (wait_time > reported_wait && (wait_time % 5) == 0) {
  758. log_mutex_error(canlog, "%s line %d (%s): Deadlock? waited %d sec for readlock '%s'?\n",
  759. filename, line, func, (int)wait_time, name);
  760. if (lt) {
  761. ast_reentrancy_lock(lt);
  762. #ifdef HAVE_BKTR
  763. __dump_backtrace(&lt->backtrace[lt->reentrancy], canlog);
  764. #endif
  765. log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
  766. lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1],
  767. lt->func[lt->reentrancy-1], name);
  768. #ifdef HAVE_BKTR
  769. __dump_backtrace(&lt->backtrace[lt->reentrancy-1], canlog);
  770. #endif
  771. ast_reentrancy_unlock(lt);
  772. }
  773. reported_wait = wait_time;
  774. }
  775. usleep(200);
  776. }
  777. } while (res == EBUSY);
  778. }
  779. #else /* !DETECT_DEADLOCKS || !DEBUG_THREADS */
  780. res = pthread_rwlock_rdlock(&t->lock);
  781. #endif /* !DETECT_DEADLOCKS || !DEBUG_THREADS */
  782. #ifdef DEBUG_THREADS
  783. if (!res && lt) {
  784. ast_reentrancy_lock(lt);
  785. if (lt->reentrancy < AST_MAX_REENTRANCY) {
  786. lt->file[lt->reentrancy] = filename;
  787. lt->lineno[lt->reentrancy] = line;
  788. lt->func[lt->reentrancy] = func;
  789. lt->thread_id[lt->reentrancy] = pthread_self();
  790. lt->reentrancy++;
  791. }
  792. ast_reentrancy_unlock(lt);
  793. ast_mark_lock_acquired(t);
  794. } else if (lt) {
  795. #ifdef HAVE_BKTR
  796. if (lt->reentrancy) {
  797. ast_reentrancy_lock(lt);
  798. bt = &lt->backtrace[lt->reentrancy-1];
  799. ast_reentrancy_unlock(lt);
  800. } else {
  801. bt = NULL;
  802. }
  803. ast_remove_lock_info(t, bt);
  804. #else
  805. ast_remove_lock_info(t);
  806. #endif
  807. }
  808. if (res) {
  809. log_mutex_error(canlog, "%s line %d (%s): Error obtaining read lock: %s\n",
  810. filename, line, func, strerror(res));
  811. DO_THREAD_CRASH;
  812. }
  813. #endif /* DEBUG_THREADS */
  814. return res;
  815. }
  816. int __ast_rwlock_wrlock(const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name)
  817. {
  818. int res;
  819. #ifdef DEBUG_THREADS
  820. struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0);
  821. int canlog = t->flags.tracking && strcmp(filename, "logger.c");
  822. #ifdef HAVE_BKTR
  823. struct ast_bt *bt = NULL;
  824. #endif
  825. if (lt) {
  826. #ifdef HAVE_BKTR
  827. struct ast_bt tmp;
  828. /* The implementation of backtrace() may have its own locks.
  829. * Capture the backtrace outside of the reentrancy lock to
  830. * avoid deadlocks. See ASTERISK-22455. */
  831. ast_bt_get_addresses(&tmp);
  832. ast_reentrancy_lock(lt);
  833. if (lt->reentrancy < AST_MAX_REENTRANCY) {
  834. lt->backtrace[lt->reentrancy] = tmp;
  835. bt = &lt->backtrace[lt->reentrancy];
  836. }
  837. ast_reentrancy_unlock(lt);
  838. ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
  839. #else
  840. ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
  841. #endif
  842. }
  843. #endif /* DEBUG_THREADS */
  844. #if defined(DETECT_DEADLOCKS) && defined(DEBUG_THREADS)
  845. {
  846. time_t seconds = time(NULL);
  847. time_t wait_time, reported_wait = 0;
  848. do {
  849. res = pthread_rwlock_trywrlock(&t->lock);
  850. if (res == EBUSY) {
  851. wait_time = time(NULL) - seconds;
  852. if (wait_time > reported_wait && (wait_time % 5) == 0) {
  853. log_mutex_error(canlog, "%s line %d (%s): Deadlock? waited %d sec for writelock '%s'?\n",
  854. filename, line, func, (int)wait_time, name);
  855. if (lt) {
  856. ast_reentrancy_lock(lt);
  857. #ifdef HAVE_BKTR
  858. __dump_backtrace(&lt->backtrace[lt->reentrancy], canlog);
  859. #endif
  860. log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
  861. lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1],
  862. lt->func[lt->reentrancy-1], name);
  863. #ifdef HAVE_BKTR
  864. __dump_backtrace(&lt->backtrace[lt->reentrancy-1], canlog);
  865. #endif
  866. ast_reentrancy_unlock(lt);
  867. }
  868. reported_wait = wait_time;
  869. }
  870. usleep(200);
  871. }
  872. } while (res == EBUSY);
  873. }
  874. #else /* !DETECT_DEADLOCKS || !DEBUG_THREADS */
  875. res = pthread_rwlock_wrlock(&t->lock);
  876. #endif /* !DETECT_DEADLOCKS || !DEBUG_THREADS */
  877. #ifdef DEBUG_THREADS
  878. if (!res && lt) {
  879. ast_reentrancy_lock(lt);
  880. if (lt->reentrancy < AST_MAX_REENTRANCY) {
  881. lt->file[lt->reentrancy] = filename;
  882. lt->lineno[lt->reentrancy] = line;
  883. lt->func[lt->reentrancy] = func;
  884. lt->thread_id[lt->reentrancy] = pthread_self();
  885. lt->reentrancy++;
  886. }
  887. ast_reentrancy_unlock(lt);
  888. ast_mark_lock_acquired(t);
  889. } else if (lt) {
  890. #ifdef HAVE_BKTR
  891. if (lt->reentrancy) {
  892. ast_reentrancy_lock(lt);
  893. bt = &lt->backtrace[lt->reentrancy-1];
  894. ast_reentrancy_unlock(lt);
  895. } else {
  896. bt = NULL;
  897. }
  898. ast_remove_lock_info(t, bt);
  899. #else
  900. ast_remove_lock_info(t);
  901. #endif
  902. }
  903. if (res) {
  904. log_mutex_error(canlog, "%s line %d (%s): Error obtaining write lock: %s\n",
  905. filename, line, func, strerror(res));
  906. DO_THREAD_CRASH;
  907. }
  908. #endif /* DEBUG_THREADS */
  909. return res;
  910. }
  911. int __ast_rwlock_timedrdlock(const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name,
  912. const struct timespec *abs_timeout)
  913. {
  914. int res;
  915. #ifdef DEBUG_THREADS
  916. struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0);
  917. int canlog = t->flags.tracking && strcmp(filename, "logger.c");
  918. #ifdef HAVE_BKTR
  919. struct ast_bt *bt = NULL;
  920. #endif
  921. if (lt) {
  922. #ifdef HAVE_BKTR
  923. struct ast_bt tmp;
  924. /* The implementation of backtrace() may have its own locks.
  925. * Capture the backtrace outside of the reentrancy lock to
  926. * avoid deadlocks. See ASTERISK-22455. */
  927. ast_bt_get_addresses(&tmp);
  928. ast_reentrancy_lock(lt);
  929. if (lt->reentrancy < AST_MAX_REENTRANCY) {
  930. lt->backtrace[lt->reentrancy] = tmp;
  931. bt = &lt->backtrace[lt->reentrancy];
  932. }
  933. ast_reentrancy_unlock(lt);
  934. ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
  935. #else
  936. ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
  937. #endif
  938. }
  939. #endif /* DEBUG_THREADS */
  940. #ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
  941. res = pthread_rwlock_timedrdlock(&t->lock, abs_timeout);
  942. #else
  943. do {
  944. struct timeval _now;
  945. for (;;) {
  946. if (!(res = pthread_rwlock_tryrdlock(&t->lock))) {
  947. break;
  948. }
  949. _now = ast_tvnow();
  950. if (_now.tv_sec > abs_timeout->tv_sec || (_now.tv_sec == abs_timeout->tv_sec && _now.tv_usec * 1000 > abs_timeout->tv_nsec)) {
  951. break;
  952. }
  953. usleep(1);
  954. }
  955. } while (0);
  956. #endif
  957. #ifdef DEBUG_THREADS
  958. if (!res && lt) {
  959. ast_reentrancy_lock(lt);
  960. if (lt->reentrancy < AST_MAX_REENTRANCY) {
  961. lt->file[lt->reentrancy] = filename;
  962. lt->lineno[lt->reentrancy] = line;
  963. lt->func[lt->reentrancy] = func;
  964. lt->thread_id[lt->reentrancy] = pthread_self();
  965. lt->reentrancy++;
  966. }
  967. ast_reentrancy_unlock(lt);
  968. ast_mark_lock_acquired(t);
  969. } else if (lt) {
  970. #ifdef HAVE_BKTR
  971. if (lt->reentrancy) {
  972. ast_reentrancy_lock(lt);
  973. bt = &lt->backtrace[lt->reentrancy-1];
  974. ast_reentrancy_unlock(lt);
  975. } else {
  976. bt = NULL;
  977. }
  978. ast_remove_lock_info(t, bt);
  979. #else
  980. ast_remove_lock_info(t);
  981. #endif
  982. }
  983. if (res) {
  984. log_mutex_error(canlog, "%s line %d (%s): Error obtaining read lock: %s\n",
  985. filename, line, func, strerror(res));
  986. DO_THREAD_CRASH;
  987. }
  988. #endif /* DEBUG_THREADS */
  989. return res;
  990. }
  991. int __ast_rwlock_timedwrlock(const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name,
  992. const struct timespec *abs_timeout)
  993. {
  994. int res;
  995. #ifdef DEBUG_THREADS
  996. struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0);
  997. int canlog = t->flags.tracking && strcmp(filename, "logger.c");
  998. #ifdef HAVE_BKTR
  999. struct ast_bt *bt = NULL;
  1000. #endif
  1001. if (lt) {
  1002. #ifdef HAVE_BKTR
  1003. struct ast_bt tmp;
  1004. /* The implementation of backtrace() may have its own locks.
  1005. * Capture the backtrace outside of the reentrancy lock to
  1006. * avoid deadlocks. See ASTERISK-22455. */
  1007. ast_bt_get_addresses(&tmp);
  1008. ast_reentrancy_lock(lt);
  1009. if (lt->reentrancy < AST_MAX_REENTRANCY) {
  1010. lt->backtrace[lt->reentrancy] = tmp;
  1011. bt = &lt->backtrace[lt->reentrancy];
  1012. }
  1013. ast_reentrancy_unlock(lt);
  1014. ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
  1015. #else
  1016. ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
  1017. #endif
  1018. }
  1019. #endif /* DEBUG_THREADS */
  1020. #ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
  1021. res = pthread_rwlock_timedwrlock(&t->lock, abs_timeout);
  1022. #else
  1023. do {
  1024. struct timeval _now;
  1025. for (;;) {
  1026. if (!(res = pthread_rwlock_trywrlock(&t->lock))) {
  1027. break;
  1028. }
  1029. _now = ast_tvnow();
  1030. if (_now.tv_sec > abs_timeout->tv_sec || (_now.tv_sec == abs_timeout->tv_sec && _now.tv_usec * 1000 > abs_timeout->tv_nsec)) {
  1031. break;
  1032. }
  1033. usleep(1);
  1034. }
  1035. } while (0);
  1036. #endif
  1037. #ifdef DEBUG_THREADS
  1038. if (!res && lt) {
  1039. ast_reentrancy_lock(lt);
  1040. if (lt->reentrancy < AST_MAX_REENTRANCY) {
  1041. lt->file[lt->reentrancy] = filename;
  1042. lt->lineno[lt->reentrancy] = line;
  1043. lt->func[lt->reentrancy] = func;
  1044. lt->thread_id[lt->reentrancy] = pthread_self();
  1045. lt->reentrancy++;
  1046. }
  1047. ast_reentrancy_unlock(lt);
  1048. ast_mark_lock_acquired(t);
  1049. } else if (lt) {
  1050. #ifdef HAVE_BKTR
  1051. if (lt->reentrancy) {
  1052. ast_reentrancy_lock(lt);
  1053. bt = &lt->backtrace[lt->reentrancy-1];
  1054. ast_reentrancy_unlock(lt);
  1055. } else {
  1056. bt = NULL;
  1057. }
  1058. ast_remove_lock_info(t, bt);
  1059. #else
  1060. ast_remove_lock_info(t);
  1061. #endif
  1062. }
  1063. if (res) {
  1064. log_mutex_error(canlog, "%s line %d (%s): Error obtaining read lock: %s\n",
  1065. filename, line, func, strerror(res));
  1066. DO_THREAD_CRASH;
  1067. }
  1068. #endif /* DEBUG_THREADS */
  1069. return res;
  1070. }
  1071. int __ast_rwlock_tryrdlock(const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name)
  1072. {
  1073. int res;
  1074. #ifdef DEBUG_THREADS
  1075. struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0);
  1076. #ifdef HAVE_BKTR
  1077. struct ast_bt *bt = NULL;
  1078. #endif
  1079. if (lt) {
  1080. #ifdef HAVE_BKTR
  1081. struct ast_bt tmp;
  1082. /* The implementation of backtrace() may have its own locks.
  1083. * Capture the backtrace outside of the reentrancy lock to
  1084. * avoid deadlocks. See ASTERISK-22455. */
  1085. ast_bt_get_addresses(&tmp);
  1086. ast_reentrancy_lock(lt);
  1087. if (lt->reentrancy < AST_MAX_REENTRANCY) {
  1088. lt->backtrace[lt->reentrancy] = tmp;
  1089. bt = &lt->backtrace[lt->reentrancy];
  1090. }
  1091. ast_reentrancy_unlock(lt);
  1092. ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t, bt);
  1093. #else
  1094. ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t);
  1095. #endif
  1096. }
  1097. #endif /* DEBUG_THREADS */
  1098. res = pthread_rwlock_tryrdlock(&t->lock);
  1099. #ifdef DEBUG_THREADS
  1100. if (!res && lt) {
  1101. ast_reentrancy_lock(lt);
  1102. if (lt->reentrancy < AST_MAX_REENTRANCY) {
  1103. lt->file[lt->reentrancy] = filename;
  1104. lt->lineno[lt->reentrancy] = line;
  1105. lt->func[lt->reentrancy] = func;
  1106. lt->thread_id[lt->reentrancy] = pthread_self();
  1107. lt->reentrancy++;
  1108. }
  1109. ast_reentrancy_unlock(lt);
  1110. ast_mark_lock_acquired(t);
  1111. } else if (lt) {
  1112. ast_mark_lock_failed(t);
  1113. }
  1114. #endif /* DEBUG_THREADS */
  1115. return res;
  1116. }
  1117. int __ast_rwlock_trywrlock(const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name)
  1118. {
  1119. int res;
  1120. #ifdef DEBUG_THREADS
  1121. struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0);
  1122. #ifdef HAVE_BKTR
  1123. struct ast_bt *bt = NULL;
  1124. #endif
  1125. if (lt) {
  1126. #ifdef HAVE_BKTR
  1127. struct ast_bt tmp;
  1128. /* The implementation of backtrace() may have its own locks.
  1129. * Capture the backtrace outside of the reentrancy lock to
  1130. * avoid deadlocks. See ASTERISK-22455. */
  1131. ast_bt_get_addresses(&tmp);
  1132. ast_reentrancy_lock(lt);
  1133. if (lt->reentrancy < AST_MAX_REENTRANCY) {
  1134. lt->backtrace[lt->reentrancy] = tmp;
  1135. bt = &lt->backtrace[lt->reentrancy];
  1136. }
  1137. ast_reentrancy_unlock(lt);
  1138. ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
  1139. #else
  1140. ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
  1141. #endif
  1142. }
  1143. #endif /* DEBUG_THREADS */
  1144. res = pthread_rwlock_trywrlock(&t->lock);
  1145. #ifdef DEBUG_THREADS
  1146. if (!res && lt) {
  1147. ast_reentrancy_lock(lt);
  1148. if (lt->reentrancy < AST_MAX_REENTRANCY) {
  1149. lt->file[lt->reentrancy] = filename;
  1150. lt->lineno[lt->reentrancy] = line;
  1151. lt->func[lt->reentrancy] = func;
  1152. lt->thread_id[lt->reentrancy] = pthread_self();
  1153. lt->reentrancy++;
  1154. }
  1155. ast_reentrancy_unlock(lt);
  1156. ast_mark_lock_acquired(t);
  1157. } else if (lt) {
  1158. ast_mark_lock_failed(t);
  1159. }
  1160. #endif /* DEBUG_THREADS */
  1161. return res;
  1162. }