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. */
62 if (!mthread_mutex_valid(mutex
))
64 else if ((*mutex
)->mm_owner
!= NO_THREAD
)
67 /* Check if this mutex is not associated with a condition */
68 for (t
= (mthread_thread_t
) 0; t
< no_threads
; t
++) {
69 tcb
= mthread_find_tcb(t
);
70 if (tcb
->m_state
== MS_CONDITION
) {
71 if (tcb
->m_cond
!= NULL
&& tcb
->m_cond
->mc_mutex
== *mutex
)
76 /* Not in use; invalidate it */
77 mthread_mutex_remove(mutex
);
85 /*===========================================================================*
86 * mthread_mutex_init *
87 *===========================================================================*/
88 int mthread_mutex_init(mutex
, mattr
)
89 mthread_mutex_t
*mutex
; /* Mutex that is to be initialized */
90 mthread_mutexattr_t
*mattr
; /* Mutex attribute */
92 /* Initialize the mutex to a known state. Attributes are not supported */
94 struct __mthread_mutex
*m
;
98 else if (mattr
!= NULL
)
100 #ifdef MTHREAD_STRICT
101 else if (mthread_mutex_valid(mutex
))
104 else if ((m
= malloc(sizeof(struct __mthread_mutex
))) == NULL
)
107 mthread_queue_init(&m
->mm_queue
);
108 m
->mm_owner
= NO_THREAD
;
109 *mutex
= (mthread_mutex_t
) m
;
110 mthread_mutex_add(mutex
); /* Validate mutex; mutex now in use */
115 /*===========================================================================*
116 * mthread_mutex_lock *
117 *===========================================================================*/
118 int mthread_mutex_lock(mutex
)
119 mthread_mutex_t
*mutex
; /* Mutex that is to be locked */
121 /* Try to lock this mutex. If already locked, append the current thread to
122 * FIFO queue associated with this mutex and suspend the thread. */
124 struct __mthread_mutex
*m
;
129 m
= (struct __mthread_mutex
*) *mutex
;
130 if (!mthread_mutex_valid(&m
))
132 else if (m
->mm_owner
== NO_THREAD
) { /* Not locked */
133 m
->mm_owner
= current_thread
;
134 } else if (m
->mm_owner
== current_thread
) {
137 mthread_queue_add(&m
->mm_queue
, current_thread
);
138 mthread_suspend(MS_MUTEX
);
141 /* When we get here we acquired the lock. */
146 /*===========================================================================*
147 * mthread_mutex_remove *
148 *===========================================================================*/
149 #ifdef MTHREAD_STRICT
150 static void mthread_mutex_remove(m
)
153 /* Remove mutex from list of valid, initialized mutexes */
155 if ((*m
)->mm_prev
== NULL
)
156 vm_front
= (*m
)->mm_next
;
158 (*m
)->mm_prev
->mm_next
= (*m
)->mm_next
;
160 if ((*m
)->mm_next
== NULL
)
161 vm_rear
= (*m
)->mm_prev
;
163 (*m
)->mm_next
->mm_prev
= (*m
)->mm_prev
;
167 /*===========================================================================*
168 * mthread_mutex_trylock *
169 *===========================================================================*/
170 int mthread_mutex_trylock(mutex
)
171 mthread_mutex_t
*mutex
; /* Mutex that is to be locked */
173 /* Try to lock this mutex and return OK. If already locked, return error. */
175 struct __mthread_mutex
*m
;
180 m
= (struct __mthread_mutex
*) *mutex
;
181 if (!mthread_mutex_valid(&m
))
183 else if (m
->mm_owner
== current_thread
)
185 else if (m
->mm_owner
== NO_THREAD
) {
186 m
->mm_owner
= current_thread
;
194 /*===========================================================================*
195 * mthread_mutex_unlock *
196 *===========================================================================*/
197 int mthread_mutex_unlock(mutex
)
198 mthread_mutex_t
*mutex
; /* Mutex that is to be unlocked */
200 /* Unlock a previously locked mutex. If there is a pending lock for this mutex
201 * by another thread, mark that thread runnable. */
203 struct __mthread_mutex
*m
;
208 m
= (struct __mthread_mutex
*) *mutex
;
209 if (!mthread_mutex_valid(&m
))
211 else if (m
->mm_owner
!= current_thread
)
212 return(EPERM
); /* Can't unlock a mutex locked by another thread. */
214 m
->mm_owner
= mthread_queue_remove(&m
->mm_queue
);
215 if (m
->mm_owner
!= NO_THREAD
) mthread_unsuspend(m
->mm_owner
);
220 /*===========================================================================*
221 * mthread_mutex_valid *
222 *===========================================================================*/
223 #ifdef MTHREAD_STRICT
224 int mthread_mutex_valid(m
)
227 /* Check to see if mutex is on the list of valid mutexes */
228 struct __mthread_mutex
*loopitem
;
232 while (loopitem
!= NULL
) {
236 loopitem
= loopitem
->mm_next
;
243 /*===========================================================================*
244 * mthread_mutex_verify *
245 *===========================================================================*/
247 int mthread_mutex_verify(void)
249 /* Return true when no mutexes are in use */
251 struct __mthread_mutex
*loopitem
;
253 #ifdef MTHREAD_STRICT
256 while (loopitem
!= NULL
) {
257 printf("mutex corruption: owner: %d\n", loopitem
->mm_owner
);
258 loopitem
= loopitem
->mm_next
;