2 * by Richard W.M. Jones <rich@annexia.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 * $Id: pthr_mutex.c,v 1.4 2003/02/02 18:05:31 rich Exp $
31 #include "pthr_pseudothread.h"
32 #include "pthr_wait_queue.h"
35 /* SunOS annoyingly defines a 'struct mutex' type, and even worse defines
36 * it as soon as you include <stdlib.h>.
40 typedef struct pool *pool;
41 extern pool new_subpool (pool);
42 extern void delete_pool (pool);
43 extern void *pmalloc (pool, unsigned n);
44 extern void pool_register_cleanup_fn (pool, void (*fn) (void *), void *);
46 #define PTHR_PSEUDOTHREAD_H
48 typedef struct pseudothread *pseudothread;
49 extern pseudothread current_pth;
50 extern pool pth_get_pool (pseudothread pth);
52 #define PTHR_WAIT_QUEUE_H
54 typedef struct wait_queue *wait_queue;
55 extern wait_queue new_wait_queue (pool);
56 extern void wq_wake_up (wait_queue);
57 extern void wq_wake_up_one (wait_queue);
58 extern void wq_sleep_on (wait_queue);
59 extern int wq_nr_sleepers (wait_queue);
62 #include "pthr_mutex.h"
64 static void _do_release (void *);
65 static void _delete_mutex (void *);
69 pseudothread pth; /* Pseudothread which is holding the lock, or null. */
70 wait_queue wq; /* Queue of threads waiting to enter. */
71 pool pool; /* Subpool of pth pool which holds the lock. If the
72 * thread exits without releasing the lock, then
73 * the subpool is deleted, which causes our callback
74 * to run, releasing the lock.
81 mutex m = pmalloc (p, sizeof *m);
85 m->wq = new_wait_queue (p);
87 /* The purpose of this cleanup is just to check that the mutex
88 * isn't released with threads in the critical section.
90 pool_register_cleanup_fn (p, _delete_mutex, m);
96 _delete_mutex (void *vm)
102 /* This function is identical to MUTEX_ENTER, except that it does not
103 * block if the lock is held by another thread. The function
104 * returns TRUE if the lock was successfully acquired, or FALSE
105 * if another thread is holding it.
108 mutex_try_enter (mutex m)
112 /* Create a subpool. If the thread exits early, then this subpool
113 * with be deleted implicitly. If, on the other hand, we release
114 * the lock in RWLOCK_LEAVE, then we will delete this pool
115 * explicitly. Either way, _DO_RELEASE will be called.
117 pool pool = new_subpool (pth_get_pool (current_pth));
119 /* Register _DO_RELEASE to run when the subpool is deleted. */
120 pool_register_cleanup_fn (pool, _do_release, m);
122 m->pth = current_pth;
130 /* Enter a critical section. This function blocks until the lock is
134 mutex_enter (mutex m)
136 while (mutex_try_enter (m) == 0)
140 /* Leave a critical section.
143 mutex_leave (mutex m)
145 assert (m->pth == current_pth);
147 /* Force _DO_RELEASE to run. */
148 delete_pool (m->pool);
152 _do_release (void *vm)
154 mutex m = (mutex) vm;
159 /* Anyone waiting to enter? */
160 if (wq_nr_sleepers (m->wq) > 0) wq_wake_up_one (m->wq);
164 mutex_nr_sleepers (mutex m)
166 return wq_nr_sleepers (m->wq);