/src/common/list.c

https://code.google.com/ · C · 838 lines · 632 code · 134 blank · 72 comment · 155 complexity · 773918d6c103aa9688c417098abf584e MD5 · raw file

  1. /*****************************************************************************
  2. * $Id$
  3. *****************************************************************************
  4. * $LSDId: list.c,v 1.28 2003/05/20 23:53:22 dun Exp $
  5. *****************************************************************************
  6. * Copyright (C) 2001-2006 The Regents of the University of California.
  7. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  8. * Written by Chris Dunlap <cdunlap@llnl.gov>.
  9. *
  10. * This file is from LSD-Tools, the LLNL Software Development Toolbox.
  11. *
  12. * LSD-Tools is free software; you can redistribute it and/or modify it under
  13. * the terms of the GNU General Public License as published by the Free
  14. * Software Foundation; either version 2 of the License, or (at your option)
  15. * any later version.
  16. *
  17. * LSD-Tools is distributed in the hope that it will be useful, but WITHOUT
  18. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  19. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  20. * more details.
  21. *
  22. * You should have received a copy of the GNU General Public License along
  23. * with LSD-Tools; if not, write to the Free Software Foundation, Inc.,
  24. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  25. *****************************************************************************
  26. * Refer to "list.h" for documentation on public functions.
  27. *****************************************************************************/
  28. #ifdef HAVE_CONFIG_H
  29. # include "config.h"
  30. #endif /* HAVE_CONFIG_H */
  31. #ifdef WITH_PTHREADS
  32. # include <pthread.h>
  33. #endif /* WITH_PTHREADS */
  34. #include <assert.h>
  35. #include <errno.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include "list.h"
  39. /*********************
  40. * lsd_fatal_error *
  41. *********************/
  42. #ifdef WITH_LSD_FATAL_ERROR_FUNC
  43. # undef lsd_fatal_error
  44. extern void lsd_fatal_error(char *file, int line, char *mesg);
  45. #else /* !WITH_LSD_FATAL_ERROR_FUNC */
  46. # ifndef lsd_fatal_error
  47. # include <errno.h>
  48. # include <stdio.h>
  49. # include <string.h>
  50. # define lsd_fatal_error(file, line, mesg) \
  51. do { \
  52. fprintf(stderr, "ERROR: [%s:%d] %s: %s\n", \
  53. file, line, mesg, strerror(errno)); \
  54. } while (0)
  55. # endif /* !lsd_fatal_error */
  56. #endif /* !WITH_LSD_FATAL_ERROR_FUNC */
  57. /*********************
  58. * lsd_nomem_error *
  59. *********************/
  60. #ifdef WITH_LSD_NOMEM_ERROR_FUNC
  61. # undef lsd_nomem_error
  62. extern void * lsd_nomem_error(char *file, int line, char *mesg);
  63. #else /* !WITH_LSD_NOMEM_ERROR_FUNC */
  64. # ifndef lsd_nomem_error
  65. # define lsd_nomem_error(file, line, mesg) (NULL)
  66. # endif /* !lsd_nomem_error */
  67. #endif /* !WITH_LSD_NOMEM_ERROR_FUNC */
  68. /***************
  69. * Constants *
  70. ***************/
  71. #define LIST_ALLOC 32
  72. #define LIST_MAGIC 0xDEADBEEF
  73. /****************
  74. * Data Types *
  75. ****************/
  76. struct listNode {
  77. void *data; /* node's data */
  78. struct listNode *next; /* next node in list */
  79. };
  80. struct listIterator {
  81. struct list *list; /* the list being iterated */
  82. struct listNode *pos; /* the next node to be iterated */
  83. struct listNode **prev; /* addr of 'next' ptr to prv It node */
  84. struct listIterator *iNext; /* iterator chain for list_destroy() */
  85. #ifndef NDEBUG
  86. unsigned int magic; /* sentinel for asserting validity */
  87. #endif /* !NDEBUG */
  88. };
  89. struct list {
  90. struct listNode *head; /* head of the list */
  91. struct listNode **tail; /* addr of last node's 'next' ptr */
  92. struct listIterator *iNext; /* iterator chain for list_destroy() */
  93. ListDelF fDel; /* function to delete node data */
  94. int count; /* number of nodes in list */
  95. #ifdef WITH_PTHREADS
  96. pthread_mutex_t mutex; /* mutex to protect access to list */
  97. #endif /* WITH_PTHREADS */
  98. #ifndef NDEBUG
  99. unsigned int magic; /* sentinel for asserting validity */
  100. #endif /* !NDEBUG */
  101. };
  102. typedef struct listNode * ListNode;
  103. /****************
  104. * Prototypes *
  105. ****************/
  106. static void * list_node_create (List l, ListNode *pp, void *x);
  107. static void * list_node_destroy (List l, ListNode *pp);
  108. static List list_alloc (void);
  109. static void list_free (List l);
  110. static ListNode list_node_alloc (void);
  111. static void list_node_free (ListNode p);
  112. static ListIterator list_iterator_alloc (void);
  113. static void list_iterator_free (ListIterator i);
  114. static void * list_alloc_aux (int size, void *pfreelist);
  115. static void list_free_aux (void *x, void *pfreelist);
  116. /***************
  117. * Variables *
  118. ***************/
  119. static List list_free_lists = NULL;
  120. static ListNode list_free_nodes = NULL;
  121. static ListIterator list_free_iterators = NULL;
  122. #ifdef WITH_PTHREADS
  123. static pthread_mutex_t list_free_lock = PTHREAD_MUTEX_INITIALIZER;
  124. #endif /* WITH_PTHREADS */
  125. /************
  126. * Macros *
  127. ************/
  128. #ifdef WITH_PTHREADS
  129. # define list_mutex_init(mutex) \
  130. do { \
  131. int e = pthread_mutex_init(mutex, NULL); \
  132. if (e != 0) { \
  133. errno = e; \
  134. lsd_fatal_error(__FILE__, __LINE__, "list mutex init"); \
  135. abort(); \
  136. } \
  137. } while (0)
  138. # define list_mutex_lock(mutex) \
  139. do { \
  140. int e = pthread_mutex_lock(mutex); \
  141. if (e != 0) { \
  142. errno = e; \
  143. lsd_fatal_error(__FILE__, __LINE__, "list mutex lock"); \
  144. abort(); \
  145. } \
  146. } while (0)
  147. # define list_mutex_unlock(mutex) \
  148. do { \
  149. int e = pthread_mutex_unlock(mutex); \
  150. if (e != 0) { \
  151. errno = e; \
  152. lsd_fatal_error(__FILE__, __LINE__, "list mutex unlock"); \
  153. abort(); \
  154. } \
  155. } while (0)
  156. # define list_mutex_destroy(mutex) \
  157. do { \
  158. int e = pthread_mutex_destroy(mutex); \
  159. if (e != 0) { \
  160. errno = e; \
  161. lsd_fatal_error(__FILE__, __LINE__, "list mutex destroy"); \
  162. abort(); \
  163. } \
  164. } while (0)
  165. # ifndef NDEBUG
  166. static int list_mutex_is_locked (pthread_mutex_t *mutex);
  167. # endif /* !NDEBUG */
  168. #else /* !WITH_PTHREADS */
  169. # define list_mutex_init(mutex)
  170. # define list_mutex_lock(mutex)
  171. # define list_mutex_unlock(mutex)
  172. # define list_mutex_destroy(mutex)
  173. # define list_mutex_is_locked(mutex) (1)
  174. #endif /* !WITH_PTHREADS */
  175. /***************
  176. * Functions *
  177. ***************/
  178. List
  179. list_create (ListDelF f)
  180. {
  181. List l;
  182. if (!(l = list_alloc()))
  183. return(lsd_nomem_error(__FILE__, __LINE__, "list create"));
  184. l->head = NULL;
  185. l->tail = &l->head;
  186. l->iNext = NULL;
  187. l->fDel = f;
  188. l->count = 0;
  189. list_mutex_init(&l->mutex);
  190. assert(l->magic = LIST_MAGIC); /* set magic via assert abuse */
  191. return(l);
  192. }
  193. void
  194. list_destroy (List l)
  195. {
  196. ListIterator i, iTmp;
  197. ListNode p, pTmp;
  198. assert(l != NULL);
  199. list_mutex_lock(&l->mutex);
  200. assert(l->magic == LIST_MAGIC);
  201. i = l->iNext;
  202. while (i) {
  203. assert(i->magic == LIST_MAGIC);
  204. iTmp = i->iNext;
  205. assert(i->magic = ~LIST_MAGIC); /* clear magic via assert abuse */
  206. list_iterator_free(i);
  207. i = iTmp;
  208. }
  209. p = l->head;
  210. while (p) {
  211. pTmp = p->next;
  212. if (p->data && l->fDel)
  213. l->fDel(p->data);
  214. list_node_free(p);
  215. p = pTmp;
  216. }
  217. assert(l->magic = ~LIST_MAGIC); /* clear magic via assert abuse */
  218. list_mutex_unlock(&l->mutex);
  219. list_mutex_destroy(&l->mutex);
  220. list_free(l);
  221. return;
  222. }
  223. int
  224. list_is_empty (List l)
  225. {
  226. int n;
  227. assert(l != NULL);
  228. list_mutex_lock(&l->mutex);
  229. assert(l->magic == LIST_MAGIC);
  230. n = l->count;
  231. list_mutex_unlock(&l->mutex);
  232. return(n == 0);
  233. }
  234. int
  235. list_count (List l)
  236. {
  237. int n;
  238. assert(l != NULL);
  239. list_mutex_lock(&l->mutex);
  240. assert(l->magic == LIST_MAGIC);
  241. n = l->count;
  242. list_mutex_unlock(&l->mutex);
  243. return(n);
  244. }
  245. void *
  246. list_append (List l, void *x)
  247. {
  248. void *v;
  249. assert(l != NULL);
  250. assert(x != NULL);
  251. list_mutex_lock(&l->mutex);
  252. assert(l->magic == LIST_MAGIC);
  253. v = list_node_create(l, l->tail, x);
  254. list_mutex_unlock(&l->mutex);
  255. return(v);
  256. }
  257. void *
  258. list_prepend (List l, void *x)
  259. {
  260. void *v;
  261. assert(l != NULL);
  262. assert(x != NULL);
  263. list_mutex_lock(&l->mutex);
  264. assert(l->magic == LIST_MAGIC);
  265. v = list_node_create(l, &l->head, x);
  266. list_mutex_unlock(&l->mutex);
  267. return(v);
  268. }
  269. void *
  270. list_find_first (List l, ListFindF f, void *key)
  271. {
  272. ListNode p;
  273. void *v = NULL;
  274. assert(l != NULL);
  275. assert(f != NULL);
  276. assert(key != NULL);
  277. list_mutex_lock(&l->mutex);
  278. assert(l->magic == LIST_MAGIC);
  279. for (p=l->head; p; p=p->next) {
  280. if (f(p->data, key)) {
  281. v = p->data;
  282. break;
  283. }
  284. }
  285. list_mutex_unlock(&l->mutex);
  286. return(v);
  287. }
  288. int
  289. list_delete_all (List l, ListFindF f, void *key)
  290. {
  291. ListNode *pp;
  292. void *v;
  293. int n = 0;
  294. assert(l != NULL);
  295. assert(f != NULL);
  296. assert(key != NULL);
  297. list_mutex_lock(&l->mutex);
  298. assert(l->magic == LIST_MAGIC);
  299. pp = &l->head;
  300. while (*pp) {
  301. if (f((*pp)->data, key)) {
  302. if ((v = list_node_destroy(l, pp))) {
  303. if (l->fDel)
  304. l->fDel(v);
  305. n++;
  306. }
  307. }
  308. else {
  309. pp = &(*pp)->next;
  310. }
  311. }
  312. list_mutex_unlock(&l->mutex);
  313. return(n);
  314. }
  315. int
  316. list_for_each (List l, ListForF f, void *arg)
  317. {
  318. ListNode p;
  319. int n = 0;
  320. assert(l != NULL);
  321. assert(f != NULL);
  322. list_mutex_lock(&l->mutex);
  323. assert(l->magic == LIST_MAGIC);
  324. for (p=l->head; p; p=p->next) {
  325. n++;
  326. if (f(p->data, arg) < 0) {
  327. n = -n;
  328. break;
  329. }
  330. }
  331. list_mutex_unlock(&l->mutex);
  332. return(n);
  333. }
  334. void
  335. list_sort (List l, ListCmpF f)
  336. {
  337. /* Note: Time complexity O(n^2).
  338. */
  339. ListNode *pp, *ppPrev, *ppPos, pTmp;
  340. ListIterator i;
  341. assert(l != NULL);
  342. assert(f != NULL);
  343. list_mutex_lock(&l->mutex);
  344. assert(l->magic == LIST_MAGIC);
  345. if (l->count > 1) {
  346. ppPrev = &l->head;
  347. pp = &(*ppPrev)->next;
  348. while (*pp) {
  349. if (f((*pp)->data, (*ppPrev)->data) < 0) {
  350. ppPos = &l->head;
  351. while (f((*pp)->data, (*ppPos)->data) >= 0)
  352. ppPos = &(*ppPos)->next;
  353. pTmp = (*pp)->next;
  354. (*pp)->next = *ppPos;
  355. *ppPos = *pp;
  356. *pp = pTmp;
  357. if (ppPrev == ppPos)
  358. ppPrev = &(*ppPrev)->next;
  359. }
  360. else {
  361. ppPrev = pp;
  362. pp = &(*pp)->next;
  363. }
  364. }
  365. l->tail = pp;
  366. for (i=l->iNext; i; i=i->iNext) {
  367. assert(i->magic == LIST_MAGIC);
  368. i->pos = i->list->head;
  369. i->prev = &i->list->head;
  370. }
  371. }
  372. list_mutex_unlock(&l->mutex);
  373. return;
  374. }
  375. void *
  376. list_push (List l, void *x)
  377. {
  378. void *v;
  379. assert(l != NULL);
  380. assert(x != NULL);
  381. list_mutex_lock(&l->mutex);
  382. assert(l->magic == LIST_MAGIC);
  383. v = list_node_create(l, &l->head, x);
  384. list_mutex_unlock(&l->mutex);
  385. return(v);
  386. }
  387. void *
  388. list_pop (List l)
  389. {
  390. void *v;
  391. assert(l != NULL);
  392. list_mutex_lock(&l->mutex);
  393. assert(l->magic == LIST_MAGIC);
  394. v = list_node_destroy(l, &l->head);
  395. list_mutex_unlock(&l->mutex);
  396. return(v);
  397. }
  398. void *
  399. list_peek (List l)
  400. {
  401. void *v;
  402. assert(l != NULL);
  403. list_mutex_lock(&l->mutex);
  404. assert(l->magic == LIST_MAGIC);
  405. v = (l->head) ? l->head->data : NULL;
  406. list_mutex_unlock(&l->mutex);
  407. return(v);
  408. }
  409. void *
  410. list_enqueue (List l, void *x)
  411. {
  412. void *v;
  413. assert(l != NULL);
  414. assert(x != NULL);
  415. list_mutex_lock(&l->mutex);
  416. assert(l->magic == LIST_MAGIC);
  417. v = list_node_create(l, l->tail, x);
  418. list_mutex_unlock(&l->mutex);
  419. return(v);
  420. }
  421. void *
  422. list_dequeue (List l)
  423. {
  424. void *v;
  425. assert(l != NULL);
  426. list_mutex_lock(&l->mutex);
  427. assert(l->magic == LIST_MAGIC);
  428. v = list_node_destroy(l, &l->head);
  429. list_mutex_unlock(&l->mutex);
  430. return(v);
  431. }
  432. ListIterator
  433. list_iterator_create (List l)
  434. {
  435. ListIterator i;
  436. assert(l != NULL);
  437. if (!(i = list_iterator_alloc()))
  438. return(lsd_nomem_error(__FILE__, __LINE__, "list iterator create"));
  439. i->list = l;
  440. list_mutex_lock(&l->mutex);
  441. assert(l->magic == LIST_MAGIC);
  442. i->pos = l->head;
  443. i->prev = &l->head;
  444. i->iNext = l->iNext;
  445. l->iNext = i;
  446. assert(i->magic = LIST_MAGIC); /* set magic via assert abuse */
  447. list_mutex_unlock(&l->mutex);
  448. return(i);
  449. }
  450. void
  451. list_iterator_reset (ListIterator i)
  452. {
  453. assert(i != NULL);
  454. assert(i->magic == LIST_MAGIC);
  455. list_mutex_lock(&i->list->mutex);
  456. assert(i->list->magic == LIST_MAGIC);
  457. i->pos = i->list->head;
  458. i->prev = &i->list->head;
  459. list_mutex_unlock(&i->list->mutex);
  460. return;
  461. }
  462. void
  463. list_iterator_destroy (ListIterator i)
  464. {
  465. ListIterator *pi;
  466. assert(i != NULL);
  467. assert(i->magic == LIST_MAGIC);
  468. list_mutex_lock(&i->list->mutex);
  469. assert(i->list->magic == LIST_MAGIC);
  470. for (pi=&i->list->iNext; *pi; pi=&(*pi)->iNext) {
  471. assert((*pi)->magic == LIST_MAGIC);
  472. if (*pi == i) {
  473. *pi = (*pi)->iNext;
  474. break;
  475. }
  476. }
  477. list_mutex_unlock(&i->list->mutex);
  478. assert(i->magic = ~LIST_MAGIC); /* clear magic via assert abuse */
  479. list_iterator_free(i);
  480. return;
  481. }
  482. void *
  483. list_next (ListIterator i)
  484. {
  485. ListNode p;
  486. assert(i != NULL);
  487. assert(i->magic == LIST_MAGIC);
  488. list_mutex_lock(&i->list->mutex);
  489. assert(i->list->magic == LIST_MAGIC);
  490. if ((p = i->pos))
  491. i->pos = p->next;
  492. if (*i->prev != p)
  493. i->prev = &(*i->prev)->next;
  494. list_mutex_unlock(&i->list->mutex);
  495. return(p ? p->data : NULL);
  496. }
  497. void *
  498. list_insert (ListIterator i, void *x)
  499. {
  500. void *v;
  501. assert(i != NULL);
  502. assert(x != NULL);
  503. assert(i->magic == LIST_MAGIC);
  504. list_mutex_lock(&i->list->mutex);
  505. assert(i->list->magic == LIST_MAGIC);
  506. v = list_node_create(i->list, i->prev, x);
  507. list_mutex_unlock(&i->list->mutex);
  508. return(v);
  509. }
  510. void *
  511. list_find (ListIterator i, ListFindF f, void *key)
  512. {
  513. void *v;
  514. assert(i != NULL);
  515. assert(f != NULL);
  516. assert(key != NULL);
  517. assert(i->magic == LIST_MAGIC);
  518. while ((v=list_next(i)) && !f(v,key)) {;}
  519. return(v);
  520. }
  521. void *
  522. list_remove (ListIterator i)
  523. {
  524. void *v = NULL;
  525. assert(i != NULL);
  526. assert(i->magic == LIST_MAGIC);
  527. list_mutex_lock(&i->list->mutex);
  528. assert(i->list->magic == LIST_MAGIC);
  529. if (*i->prev != i->pos)
  530. v = list_node_destroy(i->list, i->prev);
  531. list_mutex_unlock(&i->list->mutex);
  532. return(v);
  533. }
  534. int
  535. list_delete (ListIterator i)
  536. {
  537. void *v;
  538. assert(i != NULL);
  539. assert(i->magic == LIST_MAGIC);
  540. if ((v = list_remove(i))) {
  541. if (i->list->fDel)
  542. i->list->fDel(v);
  543. return(1);
  544. }
  545. return(0);
  546. }
  547. static void *
  548. list_node_create (List l, ListNode *pp, void *x)
  549. {
  550. /* Inserts data pointed to by [x] into list [l] after [pp],
  551. * the address of the previous node's "next" ptr.
  552. * Returns a ptr to data [x], or NULL if insertion fails.
  553. * This routine assumes the list is already locked upon entry.
  554. */
  555. ListNode p;
  556. ListIterator i;
  557. assert(l != NULL);
  558. assert(l->magic == LIST_MAGIC);
  559. assert(list_mutex_is_locked(&l->mutex));
  560. assert(pp != NULL);
  561. assert(x != NULL);
  562. if (!(p = list_node_alloc()))
  563. return(lsd_nomem_error(__FILE__, __LINE__, "list node create"));
  564. p->data = x;
  565. if (!(p->next = *pp))
  566. l->tail = &p->next;
  567. *pp = p;
  568. l->count++;
  569. for (i=l->iNext; i; i=i->iNext) {
  570. assert(i->magic == LIST_MAGIC);
  571. if (i->prev == pp)
  572. i->prev = &p->next;
  573. else if (i->pos == p->next)
  574. i->pos = p;
  575. assert((i->pos == *i->prev) || (i->pos == (*i->prev)->next));
  576. }
  577. return(x);
  578. }
  579. static void *
  580. list_node_destroy (List l, ListNode *pp)
  581. {
  582. /* Removes the node pointed to by [*pp] from from list [l],
  583. * where [pp] is the address of the previous node's "next" ptr.
  584. * Returns the data ptr associated with list item being removed,
  585. * or NULL if [*pp] points to the NULL element.
  586. * This routine assumes the list is already locked upon entry.
  587. */
  588. void *v;
  589. ListNode p;
  590. ListIterator i;
  591. assert(l != NULL);
  592. assert(l->magic == LIST_MAGIC);
  593. assert(list_mutex_is_locked(&l->mutex));
  594. assert(pp != NULL);
  595. if (!(p = *pp))
  596. return(NULL);
  597. v = p->data;
  598. if (!(*pp = p->next))
  599. l->tail = pp;
  600. l->count--;
  601. for (i=l->iNext; i; i=i->iNext) {
  602. assert(i->magic == LIST_MAGIC);
  603. if (i->pos == p)
  604. i->pos = p->next, i->prev = pp;
  605. else if (i->prev == &p->next)
  606. i->prev = pp;
  607. assert((i->pos == *i->prev) || (i->pos == (*i->prev)->next));
  608. }
  609. list_node_free(p);
  610. return(v);
  611. }
  612. static List
  613. list_alloc (void)
  614. {
  615. return(list_alloc_aux(sizeof(struct list), &list_free_lists));
  616. }
  617. static void
  618. list_free (List l)
  619. {
  620. list_free_aux(l, &list_free_lists);
  621. return;
  622. }
  623. static ListNode
  624. list_node_alloc (void)
  625. {
  626. return(list_alloc_aux(sizeof(struct listNode), &list_free_nodes));
  627. }
  628. static void
  629. list_node_free (ListNode p)
  630. {
  631. list_free_aux(p, &list_free_nodes);
  632. return;
  633. }
  634. static ListIterator
  635. list_iterator_alloc (void)
  636. {
  637. return(list_alloc_aux(sizeof(struct listIterator), &list_free_iterators));
  638. }
  639. static void
  640. list_iterator_free (ListIterator i)
  641. {
  642. list_free_aux(i, &list_free_iterators);
  643. return;
  644. }
  645. static void *
  646. list_alloc_aux (int size, void *pfreelist)
  647. {
  648. /* Allocates an object of [size] bytes from the freelist [*pfreelist].
  649. * Memory is added to the freelist in chunks of size LIST_ALLOC.
  650. * Returns a ptr to the object, or NULL if the memory request fails.
  651. */
  652. void **px;
  653. void **pfree = pfreelist;
  654. void **plast;
  655. assert(sizeof(char) == 1);
  656. assert(size >= sizeof(void *));
  657. assert(pfreelist != NULL);
  658. assert(LIST_ALLOC > 0);
  659. list_mutex_lock(&list_free_lock);
  660. if (!*pfree) {
  661. if ((*pfree = malloc(LIST_ALLOC * size))) {
  662. px = *pfree;
  663. plast = (void **) ((char *) *pfree + ((LIST_ALLOC - 1) * size));
  664. while (px < plast)
  665. *px = (char *) px + size, px = *px;
  666. *plast = NULL;
  667. }
  668. }
  669. if ((px = *pfree))
  670. *pfree = *px;
  671. else
  672. errno = ENOMEM;
  673. list_mutex_unlock(&list_free_lock);
  674. return(px);
  675. }
  676. static void
  677. list_free_aux (void *x, void *pfreelist)
  678. {
  679. /* Frees the object [x], returning it to the freelist [*pfreelist].
  680. */
  681. void **px = x;
  682. void **pfree = pfreelist;
  683. assert(x != NULL);
  684. assert(pfreelist != NULL);
  685. list_mutex_lock(&list_free_lock);
  686. *px = *pfree;
  687. *pfree = px;
  688. list_mutex_unlock(&list_free_lock);
  689. return;
  690. }
  691. #ifndef NDEBUG
  692. #ifdef WITH_PTHREADS
  693. static int
  694. list_mutex_is_locked (pthread_mutex_t *mutex)
  695. {
  696. /* Returns true if the mutex is locked; o/w, returns false.
  697. */
  698. int rc;
  699. assert(mutex != NULL);
  700. rc = pthread_mutex_trylock(mutex);
  701. return(rc == EBUSY ? 1 : 0);
  702. }
  703. #endif /* WITH_PTHREADS */
  704. #endif /* !NDEBUG */