1 #include <minix/mthread.h>
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
);
10 # define mthread_mutex_add(m) ((*m)->mm_magic = MTHREAD_INIT_MAGIC)
11 # define mthread_mutex_remove(m) ((*m)->mm_magic = MTHREAD_NOT_INUSE)
14 /*===========================================================================*
15 * mthread_init_valid_mutexes *
16 *===========================================================================*/
17 void mthread_init_valid_mutexes(void)
20 /* Initialize list of valid mutexes */
21 vm_front
= vm_rear
= NULL
;
26 /*===========================================================================*
28 *===========================================================================*/
30 static void mthread_mutex_add(m
)
33 /* Add mutex to list of valid, initialized mutexes */
35 if (vm_front
== NULL
) { /* Empty list */
39 vm_rear
->mm_next
= *m
;
40 (*m
)->mm_prev
= vm_rear
;
48 /*===========================================================================*
49 * mthread_mutex_destroy *
50 *===========================================================================*/
51 int mthread_mutex_destroy(mutex
)
52 mthread_mutex_t
*mutex
;
54 /* Invalidate mutex and deallocate resources. */
59 MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */
64 if (!mthread_mutex_valid(mutex
))
66 else if ((*mutex
)->mm_owner
!= NO_THREAD
)
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
)
78 /* Not in use; invalidate it */
79 mthread_mutex_remove(mutex
);
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 */
102 else if (mattr
!= NULL
)
104 #ifdef MTHREAD_STRICT
105 else if (mthread_mutex_valid(mutex
))
108 else if ((m
= malloc(sizeof(struct __mthread_mutex
))) == NULL
)
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 */
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 */
135 m
= (struct __mthread_mutex
*) *mutex
;
136 if (!mthread_mutex_valid(&m
))
138 else if (m
->mm_owner
== NO_THREAD
) { /* Not locked */
139 m
->mm_owner
= current_thread
;
140 } else if (m
->mm_owner
== current_thread
) {
143 mthread_queue_add(&m
->mm_queue
, current_thread
);
144 mthread_suspend(MS_MUTEX
);
147 /* When we get here we acquired the lock. */
152 /*===========================================================================*
153 * mthread_mutex_remove *
154 *===========================================================================*/
155 #ifdef MTHREAD_STRICT
156 static void mthread_mutex_remove(m
)
159 /* Remove mutex from list of valid, initialized mutexes */
161 if ((*m
)->mm_prev
== NULL
)
162 vm_front
= (*m
)->mm_next
;
164 (*m
)->mm_prev
->mm_next
= (*m
)->mm_next
;
166 if ((*m
)->mm_next
== NULL
)
167 vm_rear
= (*m
)->mm_prev
;
169 (*m
)->mm_next
->mm_prev
= (*m
)->mm_prev
;
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 */
188 m
= (struct __mthread_mutex
*) *mutex
;
189 if (!mthread_mutex_valid(&m
))
191 else if (m
->mm_owner
== current_thread
)
193 else if (m
->mm_owner
== NO_THREAD
) {
194 m
->mm_owner
= current_thread
;
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 */
218 m
= (struct __mthread_mutex
*) *mutex
;
219 if (!mthread_mutex_valid(&m
))
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
);
230 /*===========================================================================*
231 * mthread_mutex_valid *
232 *===========================================================================*/
233 #ifdef MTHREAD_STRICT
234 int mthread_mutex_valid(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 */
244 while (loopitem
!= NULL
) {
248 loopitem
= loopitem
->mm_next
;
255 /*===========================================================================*
256 * mthread_mutex_verify *
257 *===========================================================================*/
259 int mthread_mutex_verify(void)
261 /* Return true when no mutexes are in use */
263 struct __mthread_mutex
*loopitem
;
265 MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */
267 #ifdef MTHREAD_STRICT
270 while (loopitem
!= NULL
) {
271 printf("mutex corruption: owner: %d\n", loopitem
->mm_owner
);
272 loopitem
= loopitem
->mm_next
;