lock.c 36 KB

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