__aeabi_ldivmod: fix sign logic
[minix.git] / lib / libmthread / mutex.c
blob06009b88c1b7a2f5d9b19a11f35975056b8c8ec2
1 #include <minix/mthread.h>
2 #include "global.h"
3 #include "proto.h"
5 #ifdef MTHREAD_STRICT
6 static struct __mthread_mutex *vm_front, *vm_rear;
7 static void mthread_mutex_add(mthread_mutex_t *m);
8 static void mthread_mutex_remove(mthread_mutex_t *m);
9 #else
10 # define mthread_mutex_add(m) ((*m)->mm_magic = MTHREAD_INIT_MAGIC)
11 # define mthread_mutex_remove(m) ((*m)->mm_magic = MTHREAD_NOT_INUSE)
12 #endif
14 /*===========================================================================*
15 * mthread_init_valid_mutexes *
16 *===========================================================================*/
17 void mthread_init_valid_mutexes(void)
19 #ifdef MTHREAD_STRICT
20 /* Initialize list of valid mutexes */
21 vm_front = vm_rear = NULL;
22 #endif
26 /*===========================================================================*
27 * mthread_mutex_add *
28 *===========================================================================*/
29 #ifdef MTHREAD_STRICT
30 static void mthread_mutex_add(m)
31 mthread_mutex_t *m;
33 /* Add mutex to list of valid, initialized mutexes */
35 if (vm_front == NULL) { /* Empty list */
36 vm_front = *m;
37 (*m)->mm_prev = NULL;
38 } else {
39 vm_rear->mm_next = *m;
40 (*m)->mm_prev = vm_rear;
43 (*m)->mm_next = NULL;
44 vm_rear = *m;
46 #endif
48 /*===========================================================================*
49 * mthread_mutex_destroy *
50 *===========================================================================*/
51 int mthread_mutex_destroy(mutex)
52 mthread_mutex_t *mutex;
54 /* Invalidate mutex and deallocate resources. */
56 mthread_thread_t t;
57 mthread_tcb_t *tcb;
59 MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */
61 if (mutex == NULL)
62 return(EINVAL);
64 if (!mthread_mutex_valid(mutex))
65 return(EINVAL);
66 else if ((*mutex)->mm_owner != NO_THREAD)
67 return(EBUSY);
69 /* Check if this mutex is not associated with a condition */
70 for (t = (mthread_thread_t) 0; t < no_threads; t++) {
71 tcb = mthread_find_tcb(t);
72 if (tcb->m_state == MS_CONDITION) {
73 if (tcb->m_cond != NULL && tcb->m_cond->mc_mutex == *mutex)
74 return(EBUSY);
78 /* Not in use; invalidate it */
79 mthread_mutex_remove(mutex);
80 free(*mutex);
81 *mutex = NULL;
83 return(0);
87 /*===========================================================================*
88 * mthread_mutex_init *
89 *===========================================================================*/
90 int mthread_mutex_init(mutex, mattr)
91 mthread_mutex_t *mutex; /* Mutex that is to be initialized */
92 mthread_mutexattr_t *mattr; /* Mutex attribute */
94 /* Initialize the mutex to a known state. Attributes are not supported */
96 struct __mthread_mutex *m;
98 MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */
100 if (mutex == NULL)
101 return(EAGAIN);
102 else if (mattr != NULL)
103 return(ENOSYS);
104 #ifdef MTHREAD_STRICT
105 else if (mthread_mutex_valid(mutex))
106 return(EBUSY);
107 #endif
108 else if ((m = malloc(sizeof(struct __mthread_mutex))) == NULL)
109 return(ENOMEM);
111 mthread_queue_init(&m->mm_queue);
112 m->mm_owner = NO_THREAD;
113 *mutex = (mthread_mutex_t) m;
114 mthread_mutex_add(mutex); /* Validate mutex; mutex now in use */
116 return(0);
119 /*===========================================================================*
120 * mthread_mutex_lock *
121 *===========================================================================*/
122 int mthread_mutex_lock(mutex)
123 mthread_mutex_t *mutex; /* Mutex that is to be locked */
125 /* Try to lock this mutex. If already locked, append the current thread to
126 * FIFO queue associated with this mutex and suspend the thread. */
128 struct __mthread_mutex *m;
130 MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */
132 if (mutex == NULL)
133 return(EINVAL);
135 m = (struct __mthread_mutex *) *mutex;
136 if (!mthread_mutex_valid(&m))
137 return(EINVAL);
138 else if (m->mm_owner == NO_THREAD) { /* Not locked */
139 m->mm_owner = current_thread;
140 } else if (m->mm_owner == current_thread) {
141 return(EDEADLK);
142 } else {
143 mthread_queue_add(&m->mm_queue, current_thread);
144 mthread_suspend(MS_MUTEX);
147 /* When we get here we acquired the lock. */
148 return(0);
152 /*===========================================================================*
153 * mthread_mutex_remove *
154 *===========================================================================*/
155 #ifdef MTHREAD_STRICT
156 static void mthread_mutex_remove(m)
157 mthread_mutex_t *m;
159 /* Remove mutex from list of valid, initialized mutexes */
161 if ((*m)->mm_prev == NULL)
162 vm_front = (*m)->mm_next;
163 else
164 (*m)->mm_prev->mm_next = (*m)->mm_next;
166 if ((*m)->mm_next == NULL)
167 vm_rear = (*m)->mm_prev;
168 else
169 (*m)->mm_next->mm_prev = (*m)->mm_prev;
171 #endif
173 /*===========================================================================*
174 * mthread_mutex_trylock *
175 *===========================================================================*/
176 int mthread_mutex_trylock(mutex)
177 mthread_mutex_t *mutex; /* Mutex that is to be locked */
179 /* Try to lock this mutex and return OK. If already locked, return error. */
181 struct __mthread_mutex *m;
183 MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */
185 if (mutex == NULL)
186 return(EINVAL);
188 m = (struct __mthread_mutex *) *mutex;
189 if (!mthread_mutex_valid(&m))
190 return(EINVAL);
191 else if (m->mm_owner == current_thread)
192 return(EDEADLK);
193 else if (m->mm_owner == NO_THREAD) {
194 m->mm_owner = current_thread;
195 return(0);
198 return(EBUSY);
202 /*===========================================================================*
203 * mthread_mutex_unlock *
204 *===========================================================================*/
205 int mthread_mutex_unlock(mutex)
206 mthread_mutex_t *mutex; /* Mutex that is to be unlocked */
208 /* Unlock a previously locked mutex. If there is a pending lock for this mutex
209 * by another thread, mark that thread runnable. */
211 struct __mthread_mutex *m;
213 MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */
215 if (mutex == NULL)
216 return(EINVAL);
218 m = (struct __mthread_mutex *) *mutex;
219 if (!mthread_mutex_valid(&m))
220 return(EINVAL);
221 else if (m->mm_owner != current_thread)
222 return(EPERM); /* Can't unlock a mutex locked by another thread. */
224 m->mm_owner = mthread_queue_remove(&m->mm_queue);
225 if (m->mm_owner != NO_THREAD) mthread_unsuspend(m->mm_owner);
226 return(0);
230 /*===========================================================================*
231 * mthread_mutex_valid *
232 *===========================================================================*/
233 #ifdef MTHREAD_STRICT
234 int mthread_mutex_valid(m)
235 mthread_mutex_t *m;
237 /* Check to see if mutex is on the list of valid mutexes */
238 struct __mthread_mutex *loopitem;
240 MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */
242 loopitem = vm_front;
244 while (loopitem != NULL) {
245 if (loopitem == *m)
246 return(1);
248 loopitem = loopitem->mm_next;
251 return(0);
253 #endif
255 /*===========================================================================*
256 * mthread_mutex_verify *
257 *===========================================================================*/
258 #ifdef MDEBUG
259 int mthread_mutex_verify(void)
261 /* Return true when no mutexes are in use */
262 int r = 1;
263 struct __mthread_mutex *loopitem;
265 MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */
267 #ifdef MTHREAD_STRICT
268 loopitem = vm_front;
270 while (loopitem != NULL) {
271 printf("mutex corruption: owner: %d\n", loopitem->mm_owner);
272 loopitem = loopitem->mm_next;
273 r = 0;
275 #endif
277 return(r);
279 #endif