lock.c 40 KB

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