Add clockid to _thr_umtx_wait, so that clockid attribute of condition
[dragonfly.git] / lib / libthread_xu / thread / thr_mutex.c
1 /*
2  * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by John Birrell.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $FreeBSD: src/lib/libpthread/thread/thr_mutex.c,v 1.46 2004/10/31 05:03:50 green Exp $
33  * $DragonFly: src/lib/libthread_xu/thread/thr_mutex.c,v 1.2 2005/03/15 11:24:23 davidxu Exp $
34  */
35 #include <stdlib.h>
36 #include <errno.h>
37 #include <string.h>
38 #include <sys/param.h>
39 #include <sys/queue.h>
40 #include <pthread.h>
41 #include "thr_private.h"
42
43 #if defined(_PTHREADS_INVARIANTS)
44 #define MUTEX_INIT_LINK(m)              do {            \
45         (m)->m_qe.tqe_prev = NULL;                      \
46         (m)->m_qe.tqe_next = NULL;                      \
47 } while (0)
48 #define MUTEX_ASSERT_IS_OWNED(m)        do {            \
49         if ((m)->m_qe.tqe_prev == NULL)                 \
50                 PANIC("mutex is not on list");          \
51 } while (0)
52 #define MUTEX_ASSERT_NOT_OWNED(m)       do {            \
53         if (((m)->m_qe.tqe_prev != NULL) ||             \
54             ((m)->m_qe.tqe_next != NULL))               \
55                 PANIC("mutex is on list");              \
56 } while (0)
57 #define THR_ASSERT_NOT_IN_SYNCQ(thr)    do {            \
58         THR_ASSERT(((thr)->sflags & THR_FLAGS_IN_SYNCQ) == 0, \
59             "thread in syncq when it shouldn't be.");   \
60 } while (0);
61 #else
62 #define MUTEX_INIT_LINK(m)
63 #define MUTEX_ASSERT_IS_OWNED(m)
64 #define MUTEX_ASSERT_NOT_OWNED(m)
65 #define THR_ASSERT_NOT_IN_SYNCQ(thr)
66 #endif
67
68 #define THR_IN_MUTEXQ(thr)      (((thr)->sflags & THR_FLAGS_IN_SYNCQ) != 0)
69 #define MUTEX_DESTROY(m) do {           \
70         free(m);                        \
71 } while (0)
72
73
74 /*
75  * Prototypes
76  */
77 static long             mutex_handoff(struct pthread *, struct pthread_mutex *);
78 static int              mutex_self_trylock(struct pthread *, pthread_mutex_t);
79 static int              mutex_self_lock(struct pthread *, pthread_mutex_t,
80                                 const struct timespec *abstime);
81 static int              mutex_unlock_common(pthread_mutex_t *, int);
82 static void             mutex_priority_adjust(struct pthread *, pthread_mutex_t);
83 static void             mutex_rescan_owned (struct pthread *, struct pthread *,
84                             struct pthread_mutex *);
85 #if 0
86 static pthread_t        mutex_queue_deq(pthread_mutex_t);
87 #endif
88 static void             mutex_queue_remove(pthread_mutex_t, pthread_t);
89 static void             mutex_queue_enq(pthread_mutex_t, pthread_t);
90
91 __weak_reference(__pthread_mutex_init, pthread_mutex_init);
92 __weak_reference(__pthread_mutex_lock, pthread_mutex_lock);
93 __weak_reference(__pthread_mutex_timedlock, pthread_mutex_timedlock);
94 __weak_reference(__pthread_mutex_trylock, pthread_mutex_trylock);
95
96 /* Single underscore versions provided for libc internal usage: */
97 /* No difference between libc and application usage of these: */
98 __weak_reference(_pthread_mutex_destroy, pthread_mutex_destroy);
99 __weak_reference(_pthread_mutex_unlock, pthread_mutex_unlock);
100
101 static int
102 mutex_init(pthread_mutex_t *mutex,
103     const pthread_mutexattr_t *mutex_attr, int private)
104 {
105         struct pthread_mutex *pmutex;
106         enum pthread_mutextype type;
107         int             protocol;
108         int             ceiling;
109         int             flags;
110         int             ret = 0;
111
112         /* Check if default mutex attributes: */
113         if (mutex_attr == NULL || *mutex_attr == NULL) {
114                 /* Default to a (error checking) POSIX mutex: */
115                 type = PTHREAD_MUTEX_ERRORCHECK;
116                 protocol = PTHREAD_PRIO_NONE;
117                 ceiling = THR_MAX_PRIORITY;
118                 flags = 0;
119         }
120
121         /* Check mutex type: */
122         else if (((*mutex_attr)->m_type < PTHREAD_MUTEX_ERRORCHECK) ||
123             ((*mutex_attr)->m_type >= MUTEX_TYPE_MAX))
124                 /* Return an invalid argument error: */
125                 ret = EINVAL;
126
127         /* Check mutex protocol: */
128         else if (((*mutex_attr)->m_protocol < PTHREAD_PRIO_NONE) ||
129             ((*mutex_attr)->m_protocol > PTHREAD_PRIO_PROTECT))
130                 /* Return an invalid argument error: */
131                 ret = EINVAL;
132
133         else {
134                 /* Use the requested mutex type and protocol: */
135                 type = (*mutex_attr)->m_type;
136                 protocol = (*mutex_attr)->m_protocol;
137                 ceiling = (*mutex_attr)->m_ceiling;
138                 flags = (*mutex_attr)->m_flags;
139         }
140
141         /* Check no errors so far: */
142         if (ret == 0) {
143                 if ((pmutex = (pthread_mutex_t)
144                     malloc(sizeof(struct pthread_mutex))) == NULL) {
145                         ret = ENOMEM;
146                 } else {
147                         _thr_umtx_init(&pmutex->m_lock);
148                         /* Set the mutex flags: */
149                         pmutex->m_flags = flags;
150
151                         /* Process according to mutex type: */
152                         switch (type) {
153                         /* case PTHREAD_MUTEX_DEFAULT: */
154                         case PTHREAD_MUTEX_ERRORCHECK:
155                         case PTHREAD_MUTEX_NORMAL:
156                                 /* Nothing to do here. */
157                                 break;
158
159                         /* Single UNIX Spec 2 recursive mutex: */
160                         case PTHREAD_MUTEX_RECURSIVE:
161                                 /* Reset the mutex count: */
162                                 pmutex->m_count = 0;
163                                 break;
164
165                         /* Trap invalid mutex types: */
166                         default:
167                                 /* Return an invalid argument error: */
168                                 ret = EINVAL;
169                                 break;
170                         }
171                         if (ret == 0) {
172                                 /* Initialise the rest of the mutex: */
173                                 TAILQ_INIT(&pmutex->m_queue);
174                                 pmutex->m_flags |= MUTEX_FLAGS_INITED;
175                                 if (private)
176                                         pmutex->m_flags |= MUTEX_FLAGS_PRIVATE;
177                                 pmutex->m_owner = NULL;
178                                 pmutex->m_type = type;
179                                 pmutex->m_protocol = protocol;
180                                 pmutex->m_refcount = 0;
181                                 if (protocol == PTHREAD_PRIO_PROTECT)
182                                         pmutex->m_prio = ceiling;
183                                 else
184                                         pmutex->m_prio = -1;
185                                 pmutex->m_saved_prio = 0;
186                                 MUTEX_INIT_LINK(pmutex);
187                                 *mutex = pmutex;
188                         } else {
189                                 /* Free the mutex lock structure: */
190                                 MUTEX_DESTROY(pmutex);
191                                 *mutex = NULL;
192                         }
193                 }
194         }
195         /* Return the completion status: */
196         return (ret);
197 }
198
199 static int
200 init_static(struct pthread *thread, pthread_mutex_t *mutex)
201 {
202         int ret;
203
204         THR_LOCK_ACQUIRE(thread, &_mutex_static_lock);
205
206         if (*mutex == NULL)
207                 ret = mutex_init(mutex, NULL, 0);
208         else
209                 ret = 0;
210
211         THR_LOCK_RELEASE(thread, &_mutex_static_lock);
212
213         return (ret);
214 }
215
216 static int
217 init_static_private(struct pthread *thread, pthread_mutex_t *mutex)
218 {
219         int ret;
220
221         THR_LOCK_ACQUIRE(thread, &_mutex_static_lock);
222
223         if (*mutex == NULL)
224                 ret = mutex_init(mutex, NULL, 1);
225         else
226                 ret = 0;
227
228         THR_LOCK_RELEASE(thread, &_mutex_static_lock);
229
230         return (ret);
231 }
232
233 int
234 _pthread_mutex_init(pthread_mutex_t *mutex,
235     const pthread_mutexattr_t *mutex_attr)
236 {
237         return mutex_init(mutex, mutex_attr, 1);
238 }
239
240 int
241 __pthread_mutex_init(pthread_mutex_t *mutex,
242     const pthread_mutexattr_t *mutex_attr)
243 {
244         return mutex_init(mutex, mutex_attr, 0);
245 }
246
247 int
248 _mutex_reinit(pthread_mutex_t *mutex)
249 {
250         _thr_umtx_init(&(*mutex)->m_lock);
251         TAILQ_INIT(&(*mutex)->m_queue);
252         MUTEX_INIT_LINK(*mutex);
253         (*mutex)->m_owner = NULL;
254         (*mutex)->m_count = 0;
255         (*mutex)->m_refcount = 0;
256         (*mutex)->m_prio = 0;
257         (*mutex)->m_saved_prio = 0;
258         return (0);
259 }
260
261 void
262 _mutex_fork(struct pthread *curthread)
263 {
264         struct pthread_mutex *m;
265
266         TAILQ_FOREACH(m, &curthread->mutexq, m_qe)
267                 m->m_lock = UMTX_LOCKED;
268
269         /* Clear contender for priority mutexes */
270         TAILQ_FOREACH(m, &curthread->pri_mutexq, m_qe) {
271                 /* clear another thread locked us */
272                 _thr_umtx_init(&m->m_lock);
273                 TAILQ_INIT(&m->m_queue);
274         }
275 }
276
277 int
278 _pthread_mutex_destroy(pthread_mutex_t *mutex)
279 {
280         struct pthread *curthread = _get_curthread();
281         pthread_mutex_t m;
282         int ret = 0;
283
284         if (mutex == NULL || *mutex == NULL)
285                 ret = EINVAL;
286         else {
287                 /*
288                  * Try to lock the mutex structure, we only need to
289                  * try once, if failed, the mutex is in used.
290                  */
291                 ret = THR_UMTX_TRYLOCK(curthread, &(*mutex)->m_lock);
292                 if (ret)
293                         return (ret);
294
295                 /*
296                  * Check mutex other fields to see if this mutex is
297                  * in use. Mostly for prority mutex types, or there
298                  * are condition variables referencing it.
299                  */
300                 if (((*mutex)->m_owner != NULL) ||
301                     (TAILQ_FIRST(&(*mutex)->m_queue) != NULL) ||
302                     ((*mutex)->m_refcount != 0)) {
303                         THR_UMTX_UNLOCK(curthread, &(*mutex)->m_lock);
304                         ret = EBUSY;
305                 } else {
306                         /*
307                          * Save a pointer to the mutex so it can be free'd
308                          * and set the caller's pointer to NULL:
309                          */
310                         m = *mutex;
311                         *mutex = NULL;
312
313                         /* Unlock the mutex structure: */
314                         _thr_umtx_unlock(&m->m_lock, curthread->tid);
315
316                         /*
317                          * Free the memory allocated for the mutex
318                          * structure:
319                          */
320                         MUTEX_ASSERT_NOT_OWNED(m);
321                         MUTEX_DESTROY(m);
322                 }
323         }
324
325         /* Return the completion status: */
326         return (ret);
327 }
328
329 static int
330 mutex_trylock_common(struct pthread *curthread, pthread_mutex_t *mutex)
331 {
332         int ret = 0;
333
334         THR_ASSERT((mutex != NULL) && (*mutex != NULL),
335             "Uninitialized mutex in mutex_trylock_common");
336
337         /* Short cut for simple mutex. */
338         if ((*mutex)->m_protocol == PTHREAD_PRIO_NONE) {
339                 ret = THR_UMTX_TRYLOCK(curthread, &(*mutex)->m_lock);
340                 if (ret == 0) {
341                         (*mutex)->m_owner = curthread;
342                         /* Add to the list of owned mutexes: */
343                         MUTEX_ASSERT_NOT_OWNED(*mutex);
344                         TAILQ_INSERT_TAIL(&curthread->mutexq,
345                             (*mutex), m_qe);
346                 } else if ((*mutex)->m_owner == curthread) {
347                         ret = mutex_self_trylock(curthread, *mutex);
348                 } /* else {} */
349
350                 return (ret);
351         }
352
353         /* Code for priority mutex */
354
355         /* Lock the mutex structure: */
356         THR_LOCK_ACQUIRE(curthread, &(*mutex)->m_lock);
357
358         /*
359          * If the mutex was statically allocated, properly
360          * initialize the tail queue.
361          */
362         if (((*mutex)->m_flags & MUTEX_FLAGS_INITED) == 0) {
363                 TAILQ_INIT(&(*mutex)->m_queue);
364                 MUTEX_INIT_LINK(*mutex);
365                 (*mutex)->m_flags |= MUTEX_FLAGS_INITED;
366         }
367
368         /* Process according to mutex type: */
369         switch ((*mutex)->m_protocol) {
370         /* POSIX priority inheritence mutex: */
371         case PTHREAD_PRIO_INHERIT:
372                 /* Check if this mutex is not locked: */
373                 if ((*mutex)->m_owner == NULL) {
374                         /* Lock the mutex for the running thread: */
375                         (*mutex)->m_owner = curthread;
376
377                         THR_LOCK(curthread);
378                         /* Track number of priority mutexes owned: */
379                         curthread->priority_mutex_count++;
380
381                         /*
382                          * The mutex takes on the attributes of the
383                          * running thread when there are no waiters.
384                          */
385                         (*mutex)->m_prio = curthread->active_priority;
386                         (*mutex)->m_saved_prio =
387                             curthread->inherited_priority;
388                         curthread->inherited_priority = (*mutex)->m_prio;
389                         THR_UNLOCK(curthread);
390
391                         /* Add to the list of owned mutexes: */
392                         MUTEX_ASSERT_NOT_OWNED(*mutex);
393                         TAILQ_INSERT_TAIL(&curthread->pri_mutexq,
394                             (*mutex), m_qe);
395                 } else if ((*mutex)->m_owner == curthread)
396                         ret = mutex_self_trylock(curthread, *mutex);
397                 else
398                         /* Return a busy error: */
399                         ret = EBUSY;
400                 break;
401
402         /* POSIX priority protection mutex: */
403         case PTHREAD_PRIO_PROTECT:
404                 /* Check for a priority ceiling violation: */
405                 if (curthread->active_priority > (*mutex)->m_prio)
406                         ret = EINVAL;
407
408                 /* Check if this mutex is not locked: */
409                 else if ((*mutex)->m_owner == NULL) {
410                         /* Lock the mutex for the running thread: */
411                         (*mutex)->m_owner = curthread;
412
413                         THR_LOCK(curthread);
414                         /* Track number of priority mutexes owned: */
415                         curthread->priority_mutex_count++;
416
417                         /*
418                          * The running thread inherits the ceiling
419                          * priority of the mutex and executes at that
420                          * priority.
421                          */
422                         curthread->active_priority = (*mutex)->m_prio;
423                         (*mutex)->m_saved_prio =
424                             curthread->inherited_priority;
425                         curthread->inherited_priority =
426                             (*mutex)->m_prio;
427                         THR_UNLOCK(curthread);
428                         /* Add to the list of owned mutexes: */
429                         MUTEX_ASSERT_NOT_OWNED(*mutex);
430                         TAILQ_INSERT_TAIL(&curthread->pri_mutexq,
431                             (*mutex), m_qe);
432                 } else if ((*mutex)->m_owner == curthread)
433                         ret = mutex_self_trylock(curthread, *mutex);
434                 else
435                         /* Return a busy error: */
436                         ret = EBUSY;
437                 break;
438
439         /* Trap invalid mutex types: */
440         default:
441                 /* Return an invalid argument error: */
442                 ret = EINVAL;
443                 break;
444         }
445
446         /* Unlock the mutex structure: */
447         THR_LOCK_RELEASE(curthread, &(*mutex)->m_lock);
448
449         /* Return the completion status: */
450         return (ret);
451 }
452
453 int
454 __pthread_mutex_trylock(pthread_mutex_t *mutex)
455 {
456         struct pthread *curthread = _get_curthread();
457         int ret = 0;
458
459         /*
460          * If the mutex is statically initialized, perform the dynamic
461          * initialization:
462          */
463         if ((*mutex != NULL) ||
464             ((ret = init_static(curthread, mutex)) == 0))
465                 ret = mutex_trylock_common(curthread, mutex);
466
467         return (ret);
468 }
469
470 int
471 _pthread_mutex_trylock(pthread_mutex_t *mutex)
472 {
473         struct pthread  *curthread = _get_curthread();
474         int     ret = 0;
475
476         /*
477          * If the mutex is statically initialized, perform the dynamic
478          * initialization marking the mutex private (delete safe):
479          */
480         if ((*mutex != NULL) ||
481             ((ret = init_static_private(curthread, mutex)) == 0))
482                 ret = mutex_trylock_common(curthread, mutex);
483
484         return (ret);
485 }
486
487 static int
488 mutex_lock_common(struct pthread *curthread, pthread_mutex_t *m,
489         const struct timespec * abstime)
490 {
491         struct  timespec ts, ts2;
492         long    cycle;
493         int     ret = 0;
494
495         THR_ASSERT((m != NULL) && (*m != NULL),
496             "Uninitialized mutex in mutex_lock_common");
497
498         if (abstime != NULL && (abstime->tv_sec < 0 || abstime->tv_nsec < 0 ||
499             abstime->tv_nsec >= 1000000000))
500                 return (EINVAL);
501
502         /* Short cut for simple mutex. */
503
504         if ((*m)->m_protocol == PTHREAD_PRIO_NONE) {
505                 /* Default POSIX mutex: */
506                 ret = THR_UMTX_TRYLOCK(curthread, &(*m)->m_lock);
507                 if (ret == 0) {
508                         (*m)->m_owner = curthread;
509                         /* Add to the list of owned mutexes: */
510                         MUTEX_ASSERT_NOT_OWNED(*m);
511                         TAILQ_INSERT_TAIL(&curthread->mutexq,
512                             (*m), m_qe);
513                 } else if ((*m)->m_owner == curthread) {
514                         ret = mutex_self_lock(curthread, *m, abstime);
515                 } else {
516                         if (abstime == NULL) {
517                                 THR_UMTX_LOCK(curthread, &(*m)->m_lock);
518                                 ret = 0;
519                         } else {
520                                 clock_gettime(CLOCK_REALTIME, &ts);
521                                 TIMESPEC_SUB(&ts2, abstime, &ts);
522                                 ret = THR_UMTX_TIMEDLOCK(curthread,
523                                         &(*m)->m_lock, &ts2);
524                                 /*
525                                  * Timed out wait is not restarted if
526                                  * it was interrupted, not worth to do it.
527                                  */
528                                 if (ret == EINTR)
529                                         ret = ETIMEDOUT;
530                         }
531                         if (ret == 0) {
532                                 (*m)->m_owner = curthread;
533                                 /* Add to the list of owned mutexes: */
534                                 MUTEX_ASSERT_NOT_OWNED(*m);
535                                 TAILQ_INSERT_TAIL(&curthread->mutexq,
536                                     (*m), m_qe);
537                         }
538                 }
539                 return (ret);
540         }
541
542         /* Code for priority mutex */
543
544         /*
545          * Enter a loop waiting to become the mutex owner.  We need a
546          * loop in case the waiting thread is interrupted by a signal
547          * to execute a signal handler.  It is not (currently) possible
548          * to remain in the waiting queue while running a handler.
549          * Instead, the thread is interrupted and backed out of the
550          * waiting queue prior to executing the signal handler.
551          */
552         do {
553                 /* Lock the mutex structure: */
554                 THR_LOCK_ACQUIRE(curthread, &(*m)->m_lock);
555
556                 /*
557                  * If the mutex was statically allocated, properly
558                  * initialize the tail queue.
559                  */
560                 if (((*m)->m_flags & MUTEX_FLAGS_INITED) == 0) {
561                         TAILQ_INIT(&(*m)->m_queue);
562                         (*m)->m_flags |= MUTEX_FLAGS_INITED;
563                         MUTEX_INIT_LINK(*m);
564                 }
565
566                 /* Process according to mutex type: */
567                 switch ((*m)->m_protocol) {
568                 /* POSIX priority inheritence mutex: */
569                 case PTHREAD_PRIO_INHERIT:
570                         /* Check if this mutex is not locked: */
571                         if ((*m)->m_owner == NULL) {
572                                 /* Lock the mutex for this thread: */
573                                 (*m)->m_owner = curthread;
574
575                                 THR_LOCK(curthread);
576                                 /* Track number of priority mutexes owned: */
577                                 curthread->priority_mutex_count++;
578
579                                 /*
580                                  * The mutex takes on attributes of the
581                                  * running thread when there are no waiters.
582                                  * Make sure the thread's scheduling lock is
583                                  * held while priorities are adjusted.
584                                  */
585                                 (*m)->m_prio = curthread->active_priority;
586                                 (*m)->m_saved_prio =
587                                     curthread->inherited_priority;
588                                 curthread->inherited_priority = (*m)->m_prio;
589                                 THR_UNLOCK(curthread);
590
591                                 /* Add to the list of owned mutexes: */
592                                 MUTEX_ASSERT_NOT_OWNED(*m);
593                                 TAILQ_INSERT_TAIL(&curthread->pri_mutexq,
594                                     (*m), m_qe);
595
596                                 /* Unlock the mutex structure: */
597                                 THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
598                         } else if ((*m)->m_owner == curthread) {
599                                 ret = mutex_self_lock(curthread, *m, abstime);
600
601                                 /* Unlock the mutex structure: */
602                                 THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
603                         } else {
604                                 /*
605                                  * Join the queue of threads waiting to lock
606                                  * the mutex and save a pointer to the mutex.
607                                  */
608                                 mutex_queue_enq(*m, curthread);
609                                 curthread->data.mutex = *m;
610
611                                 if (curthread->active_priority > (*m)->m_prio)
612                                         /* Adjust priorities: */
613                                         mutex_priority_adjust(curthread, *m);
614
615                                 THR_LOCK(curthread);
616                                 cycle = curthread->cycle;
617                                 THR_UNLOCK(curthread);
618
619                                 /* Unlock the mutex structure: */
620                                 THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
621
622                                 clock_gettime(CLOCK_REALTIME, &ts);
623                                 TIMESPEC_SUB(&ts2, abstime, &ts);
624                                 ret = _thr_umtx_wait(&curthread->cycle, cycle,
625                                          &ts2, CLOCK_REALTIME);
626                                 if (ret == EINTR)
627                                         ret = 0;
628
629                                 if (THR_IN_MUTEXQ(curthread)) {
630                                         THR_LOCK_ACQUIRE(curthread, &(*m)->m_lock);
631                                         mutex_queue_remove(*m, curthread);
632                                         THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
633                                 }
634                                 /*
635                                  * Only clear these after assuring the
636                                  * thread is dequeued.
637                                  */
638                                 curthread->data.mutex = NULL;
639                         }
640                         break;
641
642                 /* POSIX priority protection mutex: */
643                 case PTHREAD_PRIO_PROTECT:
644                         /* Check for a priority ceiling violation: */
645                         if (curthread->active_priority > (*m)->m_prio) {
646                                 /* Unlock the mutex structure: */
647                                 THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
648                                 ret = EINVAL;
649                         }
650                         /* Check if this mutex is not locked: */
651                         else if ((*m)->m_owner == NULL) {
652                                 /*
653                                  * Lock the mutex for the running
654                                  * thread:
655                                  */
656                                 (*m)->m_owner = curthread;
657
658                                 THR_LOCK(curthread);
659                                 /* Track number of priority mutexes owned: */
660                                 curthread->priority_mutex_count++;
661
662                                 /*
663                                  * The running thread inherits the ceiling
664                                  * priority of the mutex and executes at that
665                                  * priority.  Make sure the thread's
666                                  * scheduling lock is held while priorities
667                                  * are adjusted.
668                                  */
669                                 curthread->active_priority = (*m)->m_prio;
670                                 (*m)->m_saved_prio =
671                                     curthread->inherited_priority;
672                                 curthread->inherited_priority = (*m)->m_prio;
673                                 THR_UNLOCK(curthread);
674
675                                 /* Add to the list of owned mutexes: */
676                                 MUTEX_ASSERT_NOT_OWNED(*m);
677                                 TAILQ_INSERT_TAIL(&curthread->pri_mutexq,
678                                     (*m), m_qe);
679
680                                 /* Unlock the mutex structure: */
681                                 THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
682                         } else if ((*m)->m_owner == curthread) {
683                                 ret = mutex_self_lock(curthread, *m, abstime);
684
685                                 /* Unlock the mutex structure: */
686                                 THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
687                         } else {
688                                 /*
689                                  * Join the queue of threads waiting to lock
690                                  * the mutex and save a pointer to the mutex.
691                                  */
692                                 mutex_queue_enq(*m, curthread);
693                                 curthread->data.mutex = *m;
694
695                                 /* Clear any previous error: */
696                                 curthread->error = 0;
697
698                                 THR_LOCK(curthread);
699                                 cycle = curthread->cycle;
700                                 THR_UNLOCK(curthread);
701
702                                 /* Unlock the mutex structure: */
703                                 THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
704
705                                 clock_gettime(CLOCK_REALTIME, &ts);
706                                 TIMESPEC_SUB(&ts2, abstime, &ts);
707                                 ret = _thr_umtx_wait(&curthread->cycle, cycle,
708                                         &ts2, CLOCK_REALTIME);
709                                 if (ret == EINTR)
710                                         ret = 0;
711
712                                 curthread->data.mutex = NULL;
713                                 if (THR_IN_MUTEXQ(curthread)) {
714                                         THR_LOCK_ACQUIRE(curthread, &(*m)->m_lock);
715                                         mutex_queue_remove(*m, curthread);
716                                         THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
717                                 }
718                                 /*
719                                  * Only clear these after assuring the
720                                  * thread is dequeued.
721                                  */
722                                 curthread->data.mutex = NULL;
723
724                                 /*
725                                  * The threads priority may have changed while
726                                  * waiting for the mutex causing a ceiling
727                                  * violation.
728                                  */
729                                 ret = curthread->error;
730                                 curthread->error = 0;
731                         }
732                         break;
733
734                 /* Trap invalid mutex types: */
735                 default:
736                         /* Unlock the mutex structure: */
737                         THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
738
739                         /* Return an invalid argument error: */
740                         ret = EINVAL;
741                         break;
742                 }
743
744         } while (((*m)->m_owner != curthread) && (ret == 0));
745
746         /* Return the completion status: */
747         return (ret);
748 }
749
750 int
751 __pthread_mutex_lock(pthread_mutex_t *m)
752 {
753         struct pthread *curthread;
754         int     ret = 0;
755
756         _thr_check_init();
757
758         curthread = _get_curthread();
759
760         /*
761          * If the mutex is statically initialized, perform the dynamic
762          * initialization:
763          */
764         if ((*m != NULL) || ((ret = init_static(curthread, m)) == 0))
765                 ret = mutex_lock_common(curthread, m, NULL);
766
767         return (ret);
768 }
769
770 __strong_reference(__pthread_mutex_lock, _thr_mutex_lock);
771
772 int
773 _pthread_mutex_lock(pthread_mutex_t *m)
774 {
775         struct pthread *curthread;
776         int     ret = 0;
777
778         _thr_check_init();
779
780         curthread = _get_curthread();
781
782         /*
783          * If the mutex is statically initialized, perform the dynamic
784          * initialization marking it private (delete safe):
785          */
786         if ((*m != NULL) ||
787             ((ret = init_static_private(curthread, m)) == 0))
788                 ret = mutex_lock_common(curthread, m, NULL);
789
790         return (ret);
791 }
792
793 int
794 __pthread_mutex_timedlock(pthread_mutex_t *m,
795         const struct timespec *abs_timeout)
796 {
797         struct pthread *curthread;
798         int     ret = 0;
799
800         _thr_check_init();
801
802         curthread = _get_curthread();
803
804         /*
805          * If the mutex is statically initialized, perform the dynamic
806          * initialization:
807          */
808         if ((*m != NULL) || ((ret = init_static(curthread, m)) == 0))
809                 ret = mutex_lock_common(curthread, m, abs_timeout);
810
811         return (ret);
812 }
813
814 int
815 _pthread_mutex_timedlock(pthread_mutex_t *m,
816         const struct timespec *abs_timeout)
817 {
818         struct pthread *curthread;
819         int     ret = 0;
820
821         _thr_check_init();
822
823         curthread = _get_curthread();
824
825         /*
826          * If the mutex is statically initialized, perform the dynamic
827          * initialization marking it private (delete safe):
828          */
829         if ((*m != NULL) ||
830             ((ret = init_static_private(curthread, m)) == 0))
831                 ret = mutex_lock_common(curthread, m, abs_timeout);
832
833         return (ret);
834 }
835
836 int
837 _pthread_mutex_unlock(pthread_mutex_t *m)
838 {
839         return (mutex_unlock_common(m, /* add reference */ 0));
840 }
841
842 __strong_reference(_pthread_mutex_unlock, _thr_mutex_unlock);
843
844 int
845 _mutex_cv_unlock(pthread_mutex_t *m)
846 {
847         return (mutex_unlock_common(m, /* add reference */ 1));
848 }
849
850 int
851 _mutex_cv_lock(pthread_mutex_t *m)
852 {
853         struct  pthread *curthread;
854         int     ret;
855
856         curthread = _get_curthread();
857         if ((ret = _pthread_mutex_lock(m)) == 0)
858                 (*m)->m_refcount--;
859         return (ret);
860 }
861
862 static int
863 mutex_self_trylock(struct pthread *curthread, pthread_mutex_t m)
864 {
865         int     ret;
866
867         switch (m->m_type) {
868         /* case PTHREAD_MUTEX_DEFAULT: */
869         case PTHREAD_MUTEX_ERRORCHECK:
870         case PTHREAD_MUTEX_NORMAL:
871                 ret = EBUSY; 
872                 break;
873
874         case PTHREAD_MUTEX_RECURSIVE:
875                 /* Increment the lock count: */
876                 if (m->m_count + 1 > 0) {
877                         m->m_count++;
878                         ret = 0;
879                 } else
880                         ret = EAGAIN;
881                 break;
882
883         default:
884                 /* Trap invalid mutex types; */
885                 ret = EINVAL;
886         }
887
888         return (ret);
889 }
890
891 static int
892 mutex_self_lock(struct pthread *curthread, pthread_mutex_t m,
893         const struct timespec *abstime)
894 {
895         struct timespec ts1, ts2;
896         int ret;
897
898         switch (m->m_type) {
899         /* case PTHREAD_MUTEX_DEFAULT: */
900         case PTHREAD_MUTEX_ERRORCHECK:
901                 if (abstime) {
902                         clock_gettime(CLOCK_REALTIME, &ts1);
903                         TIMESPEC_SUB(&ts2, abstime, &ts1);
904                         __sys_nanosleep(&ts2, NULL);
905                         ret = ETIMEDOUT;
906                 } else {
907                         /*
908                          * POSIX specifies that mutexes should return
909                          * EDEADLK if a recursive lock is detected.
910                          */
911                         ret = EDEADLK; 
912                 }
913                 break;
914
915         case PTHREAD_MUTEX_NORMAL:
916                 /*
917                  * What SS2 define as a 'normal' mutex.  Intentionally
918                  * deadlock on attempts to get a lock you already own.
919                  */
920                 ret = 0;
921                 if (m->m_protocol != PTHREAD_PRIO_NONE) {
922                         /* Unlock the mutex structure: */
923                         THR_LOCK_RELEASE(curthread, &m->m_lock);
924                 }
925                 if (abstime) {
926                         clock_gettime(CLOCK_REALTIME, &ts1);
927                         TIMESPEC_SUB(&ts2, abstime, &ts1);
928                         __sys_nanosleep(&ts2, NULL);
929                         ret = ETIMEDOUT;
930                 } else {
931                         ts1.tv_sec = 30;
932                         ts1.tv_nsec = 0;
933                         for (;;)
934                                 __sys_nanosleep(&ts1, NULL);
935                 }
936                 break;
937
938         case PTHREAD_MUTEX_RECURSIVE:
939                 /* Increment the lock count: */
940                 if (m->m_count + 1 > 0) {
941                         m->m_count++;
942                         ret = 0;
943                 } else
944                         ret = EAGAIN;
945                 break;
946
947         default:
948                 /* Trap invalid mutex types; */
949                 ret = EINVAL;
950         }
951
952         return (ret);
953 }
954
955 static int
956 mutex_unlock_common(pthread_mutex_t *m, int add_reference)
957 {
958         struct pthread *curthread = _get_curthread();
959         long tid = -1;
960         int ret = 0;
961
962         if (m == NULL || *m == NULL)
963                 ret = EINVAL;
964         else {
965                 /* Short cut for simple mutex. */
966
967                 if ((*m)->m_protocol == PTHREAD_PRIO_NONE) {
968                         /*
969                          * Check if the running thread is not the owner of the
970                          * mutex:
971                          */
972                         if (__predict_false((*m)->m_owner != curthread)) {
973                                 ret = EPERM;
974                         } else if (__predict_false(
975                                   (*m)->m_type == PTHREAD_MUTEX_RECURSIVE &&
976                                   (*m)->m_count > 0)) {
977                                 /* Decrement the count: */
978                                 (*m)->m_count--;
979                                 if (add_reference)
980                                         (*m)->m_refcount++;
981                         } else {
982                                 /*
983                                  * Clear the count in case this is a recursive
984                                  * mutex.
985                                  */
986                                 (*m)->m_count = 0;
987                                 (*m)->m_owner = NULL;
988                                 /* Remove the mutex from the threads queue. */
989                                 MUTEX_ASSERT_IS_OWNED(*m);
990                                 TAILQ_REMOVE(&curthread->mutexq, (*m), m_qe);
991                                 MUTEX_INIT_LINK(*m);
992                                 if (add_reference)
993                                         (*m)->m_refcount++;
994                                 /*
995                                  * Hand off the mutex to the next waiting
996                                  * thread.
997                                  */
998                                 _thr_umtx_unlock(&(*m)->m_lock, curthread->tid);
999                         }
1000                         return (ret);
1001                 }
1002
1003                 /* Code for priority mutex */
1004
1005                 /* Lock the mutex structure: */
1006                 THR_LOCK_ACQUIRE(curthread, &(*m)->m_lock);
1007
1008                 /* Process according to mutex type: */
1009                 switch ((*m)->m_protocol) {
1010                 /* POSIX priority inheritence mutex: */
1011                 case PTHREAD_PRIO_INHERIT:
1012                         /*
1013                          * Check if the running thread is not the owner of the
1014                          * mutex:
1015                          */
1016                         if ((*m)->m_owner != curthread)
1017                                 ret = EPERM;
1018                         else if (((*m)->m_type == PTHREAD_MUTEX_RECURSIVE) &&
1019                             ((*m)->m_count > 0))
1020                                 /* Decrement the count: */
1021                                 (*m)->m_count--;
1022                         else {
1023                                 /*
1024                                  * Clear the count in case this is recursive
1025                                  * mutex.
1026                                  */
1027                                 (*m)->m_count = 0;
1028
1029                                 /*
1030                                  * Restore the threads inherited priority and
1031                                  * recompute the active priority (being careful
1032                                  * not to override changes in the threads base
1033                                  * priority subsequent to locking the mutex).
1034                                  */
1035                                 THR_LOCK(curthread);
1036                                 curthread->inherited_priority =
1037                                         (*m)->m_saved_prio;
1038                                 curthread->active_priority =
1039                                     MAX(curthread->inherited_priority,
1040                                     curthread->base_priority);
1041
1042                                 /*
1043                                  * This thread now owns one less priority mutex.
1044                                  */
1045                                 curthread->priority_mutex_count--;
1046                                 THR_UNLOCK(curthread);
1047
1048                                 /* Remove the mutex from the threads queue. */
1049                                 MUTEX_ASSERT_IS_OWNED(*m);
1050                                 TAILQ_REMOVE(&(*m)->m_owner->pri_mutexq,
1051                                     (*m), m_qe);
1052                                 MUTEX_INIT_LINK(*m);
1053
1054                                 /*
1055                                  * Hand off the mutex to the next waiting
1056                                  * thread:
1057                                  */
1058                                 tid = mutex_handoff(curthread, *m);
1059                         }
1060                         break;
1061
1062                 /* POSIX priority ceiling mutex: */
1063                 case PTHREAD_PRIO_PROTECT:
1064                         /*
1065                          * Check if the running thread is not the owner of the
1066                          * mutex:
1067                          */
1068                         if ((*m)->m_owner != curthread)
1069                                 ret = EPERM;
1070                         else if (((*m)->m_type == PTHREAD_MUTEX_RECURSIVE) &&
1071                             ((*m)->m_count > 0))
1072                                 /* Decrement the count: */
1073                                 (*m)->m_count--;
1074                         else {
1075                                 /*
1076                                  * Clear the count in case this is a recursive
1077                                  * mutex.
1078                                  */
1079                                 (*m)->m_count = 0;
1080
1081                                 /*
1082                                  * Restore the threads inherited priority and
1083                                  * recompute the active priority (being careful
1084                                  * not to override changes in the threads base
1085                                  * priority subsequent to locking the mutex).
1086                                  */
1087                                 THR_LOCK(curthread);
1088                                 curthread->inherited_priority =
1089                                         (*m)->m_saved_prio;
1090                                 curthread->active_priority =
1091                                     MAX(curthread->inherited_priority,
1092                                     curthread->base_priority);
1093
1094                                 /*
1095                                  * This thread now owns one less priority mutex.
1096                                  */
1097                                 curthread->priority_mutex_count--;
1098                                 THR_UNLOCK(curthread);
1099
1100                                 /* Remove the mutex from the threads queue. */
1101                                 MUTEX_ASSERT_IS_OWNED(*m);
1102                                 TAILQ_REMOVE(&(*m)->m_owner->pri_mutexq,
1103                                     (*m), m_qe);
1104                                 MUTEX_INIT_LINK(*m);
1105
1106                                 /*
1107                                  * Hand off the mutex to the next waiting
1108                                  * thread:
1109                                  */
1110                                 tid = mutex_handoff(curthread, *m);
1111                         }
1112                         break;
1113
1114                 /* Trap invalid mutex types: */
1115                 default:
1116                         /* Return an invalid argument error: */
1117                         ret = EINVAL;
1118                         break;
1119                 }
1120
1121                 if ((ret == 0) && (add_reference != 0))
1122                         /* Increment the reference count: */
1123                         (*m)->m_refcount++;
1124
1125                 /* Unlock the mutex structure: */
1126                 THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
1127         }
1128
1129         /* Return the completion status: */
1130         return (ret);
1131 }
1132
1133
1134 /*
1135  * This function is called when a change in base priority occurs for
1136  * a thread that is holding or waiting for a priority protection or
1137  * inheritence mutex.  A change in a threads base priority can effect
1138  * changes to active priorities of other threads and to the ordering
1139  * of mutex locking by waiting threads.
1140  *
1141  * This must be called without the target thread's scheduling lock held.
1142  */
1143 void
1144 _mutex_notify_priochange(struct pthread *curthread, struct pthread *pthread,
1145     int propagate_prio)
1146 {
1147         struct pthread_mutex *m;
1148
1149         /* Adjust the priorites of any owned priority mutexes: */
1150         if (pthread->priority_mutex_count > 0) {
1151                 /*
1152                  * Rescan the mutexes owned by this thread and correct
1153                  * their priorities to account for this threads change
1154                  * in priority.  This has the side effect of changing
1155                  * the threads active priority.
1156                  *
1157                  * Be sure to lock the first mutex in the list of owned
1158                  * mutexes.  This acts as a barrier against another
1159                  * simultaneous call to change the threads priority
1160                  * and from the owning thread releasing the mutex.
1161                  */
1162                 m = TAILQ_FIRST(&pthread->pri_mutexq);
1163                 if (m != NULL) {
1164                         THR_LOCK_ACQUIRE(curthread, &m->m_lock);
1165                         /*
1166                          * Make sure the thread still owns the lock.
1167                          */
1168                         if (m == TAILQ_FIRST(&pthread->pri_mutexq))
1169                                 mutex_rescan_owned(curthread, pthread,
1170                                     /* rescan all owned */ NULL);
1171                         THR_LOCK_RELEASE(curthread, &m->m_lock);
1172                 }
1173         }
1174
1175         /*
1176          * If this thread is waiting on a priority inheritence mutex,
1177          * check for priority adjustments.  A change in priority can
1178          * also cause a ceiling violation(*) for a thread waiting on
1179          * a priority protection mutex; we don't perform the check here
1180          * as it is done in pthread_mutex_unlock.
1181          *
1182          * (*) It should be noted that a priority change to a thread
1183          *     _after_ taking and owning a priority ceiling mutex
1184          *     does not affect ownership of that mutex; the ceiling
1185          *     priority is only checked before mutex ownership occurs.
1186          */
1187         if (propagate_prio != 0) {
1188                 /*
1189                  * Lock the thread's scheduling queue.  This is a bit
1190                  * convoluted; the "in synchronization queue flag" can
1191                  * only be cleared with both the thread's scheduling and
1192                  * mutex locks held.  The thread's pointer to the wanted
1193                  * mutex is guaranteed to be valid during this time.
1194                  */
1195                 THR_THREAD_LOCK(curthread, pthread);
1196
1197                 if (((pthread->sflags & THR_FLAGS_IN_SYNCQ) == 0) ||
1198                     ((m = pthread->data.mutex) == NULL))
1199                         THR_THREAD_UNLOCK(curthread, pthread);
1200                 else {
1201                         /*
1202                          * This thread is currently waiting on a mutex; unlock
1203                          * the scheduling queue lock and lock the mutex.  We
1204                          * can't hold both at the same time because the locking
1205                          * order could cause a deadlock.
1206                          */
1207                         THR_THREAD_UNLOCK(curthread, pthread);
1208                         THR_LOCK_ACQUIRE(curthread, &m->m_lock);
1209
1210                         /*
1211                          * Check to make sure this thread is still in the
1212                          * same state (the lock above can yield the CPU to
1213                          * another thread or the thread may be running on
1214                          * another CPU).
1215                          */
1216                         if (((pthread->sflags & THR_FLAGS_IN_SYNCQ) != 0) &&
1217                             (pthread->data.mutex == m)) {
1218                                 /*
1219                                  * Remove and reinsert this thread into
1220                                  * the list of waiting threads to preserve
1221                                  * decreasing priority order.
1222                                  */
1223                                 mutex_queue_remove(m, pthread);
1224                                 mutex_queue_enq(m, pthread);
1225
1226                                 if (m->m_protocol == PTHREAD_PRIO_INHERIT)
1227                                         /* Adjust priorities: */
1228                                         mutex_priority_adjust(curthread, m);
1229                         }
1230
1231                         /* Unlock the mutex structure: */
1232                         THR_LOCK_RELEASE(curthread, &m->m_lock);
1233                 }
1234         }
1235 }
1236
1237 /*
1238  * Called when a new thread is added to the mutex waiting queue or
1239  * when a threads priority changes that is already in the mutex
1240  * waiting queue.
1241  *
1242  * This must be called with the mutex locked by the current thread.
1243  */
1244 static void
1245 mutex_priority_adjust(struct pthread *curthread, pthread_mutex_t mutex)
1246 {
1247         pthread_mutex_t m = mutex;
1248         struct pthread  *pthread_next, *pthread = mutex->m_owner;
1249         int             done, temp_prio;
1250
1251         /*
1252          * Calculate the mutex priority as the maximum of the highest
1253          * active priority of any waiting threads and the owning threads
1254          * active priority(*).
1255          *
1256          * (*) Because the owning threads current active priority may
1257          *     reflect priority inherited from this mutex (and the mutex
1258          *     priority may have changed) we must recalculate the active
1259          *     priority based on the threads saved inherited priority
1260          *     and its base priority.
1261          */
1262         pthread_next = TAILQ_FIRST(&m->m_queue);  /* should never be NULL */
1263         temp_prio = MAX(pthread_next->active_priority,
1264             MAX(m->m_saved_prio, pthread->base_priority));
1265
1266         /* See if this mutex really needs adjusting: */
1267         if (temp_prio == m->m_prio)
1268                 /* No need to propagate the priority: */
1269                 return;
1270
1271         /* Set new priority of the mutex: */
1272         m->m_prio = temp_prio;
1273
1274         /*
1275          * Don't unlock the mutex passed in as an argument.  It is
1276          * expected to be locked and unlocked by the caller.
1277          */
1278         done = 1;
1279         do {
1280                 /*
1281                  * Save the threads priority before rescanning the
1282                  * owned mutexes:
1283                  */
1284                 temp_prio = pthread->active_priority;
1285
1286                 /*
1287                  * Fix the priorities for all mutexes held by the owning
1288                  * thread since taking this mutex.  This also has a
1289                  * potential side-effect of changing the threads priority.
1290                  *
1291                  * At this point the mutex is locked by the current thread.
1292                  * The owning thread can't release the mutex until it is
1293                  * unlocked, so we should be able to safely walk its list
1294                  * of owned mutexes.
1295                  */
1296                 mutex_rescan_owned(curthread, pthread, m);
1297
1298                 /*
1299                  * If this isn't the first time through the loop,
1300                  * the current mutex needs to be unlocked.
1301                  */
1302                 if (done == 0)
1303                         THR_LOCK_RELEASE(curthread, &m->m_lock);
1304
1305                 /* Assume we're done unless told otherwise: */
1306                 done = 1;
1307
1308                 /*
1309                  * If the thread is currently waiting on a mutex, check
1310                  * to see if the threads new priority has affected the
1311                  * priority of the mutex.
1312                  */
1313                 if ((temp_prio != pthread->active_priority) &&
1314                     ((pthread->sflags & THR_FLAGS_IN_SYNCQ) != 0) &&
1315                     ((m = pthread->data.mutex) != NULL) &&
1316                     (m->m_protocol == PTHREAD_PRIO_INHERIT)) {
1317                         /* Lock the mutex structure: */
1318                         THR_LOCK_ACQUIRE(curthread, &m->m_lock);
1319
1320                         /*
1321                          * Make sure the thread is still waiting on the
1322                          * mutex:
1323                          */
1324                         if (((pthread->sflags & THR_FLAGS_IN_SYNCQ) != 0) &&
1325                             (m == pthread->data.mutex)) {
1326                                 /*
1327                                  * The priority for this thread has changed.
1328                                  * Remove and reinsert this thread into the
1329                                  * list of waiting threads to preserve
1330                                  * decreasing priority order.
1331                                  */
1332                                 mutex_queue_remove(m, pthread);
1333                                 mutex_queue_enq(m, pthread);
1334
1335                                 /*
1336                                  * Grab the waiting thread with highest
1337                                  * priority:
1338                                  */
1339                                 pthread_next = TAILQ_FIRST(&m->m_queue);
1340
1341                                 /*
1342                                  * Calculate the mutex priority as the maximum
1343                                  * of the highest active priority of any
1344                                  * waiting threads and the owning threads
1345                                  * active priority.
1346                                  */
1347                                 temp_prio = MAX(pthread_next->active_priority,
1348                                     MAX(m->m_saved_prio,
1349                                     m->m_owner->base_priority));
1350
1351                                 if (temp_prio != m->m_prio) {
1352                                         /*
1353                                          * The priority needs to be propagated
1354                                          * to the mutex this thread is waiting
1355                                          * on and up to the owner of that mutex.
1356                                          */
1357                                         m->m_prio = temp_prio;
1358                                         pthread = m->m_owner;
1359
1360                                         /* We're not done yet: */
1361                                         done = 0;
1362                                 }
1363                         }
1364                         /* Only release the mutex if we're done: */
1365                         if (done != 0)
1366                                 THR_LOCK_RELEASE(curthread, &m->m_lock);
1367                 }
1368         } while (done == 0);
1369 }
1370
1371 static void
1372 mutex_rescan_owned(struct pthread *curthread, struct pthread *pthread,
1373     struct pthread_mutex *mutex)
1374 {
1375         struct pthread_mutex    *m;
1376         struct pthread          *pthread_next;
1377         int                     active_prio, inherited_prio;
1378
1379         /*
1380          * Start walking the mutexes the thread has taken since
1381          * taking this mutex.
1382          */
1383         if (mutex == NULL) {
1384                 /*
1385                  * A null mutex means start at the beginning of the owned
1386                  * mutex list.
1387                  */
1388                 m = TAILQ_FIRST(&pthread->pri_mutexq);
1389
1390                 /* There is no inherited priority yet. */
1391                 inherited_prio = 0;
1392         } else {
1393                 /*
1394                  * The caller wants to start after a specific mutex.  It
1395                  * is assumed that this mutex is a priority inheritence
1396                  * mutex and that its priority has been correctly
1397                  * calculated.
1398                  */
1399                 m = TAILQ_NEXT(mutex, m_qe);
1400
1401                 /* Start inheriting priority from the specified mutex. */
1402                 inherited_prio = mutex->m_prio;
1403         }
1404         active_prio = MAX(inherited_prio, pthread->base_priority);
1405
1406         for (; m != NULL; m = TAILQ_NEXT(m, m_qe)) {
1407                 /*
1408                  * We only want to deal with priority inheritence
1409                  * mutexes.  This might be optimized by only placing
1410                  * priority inheritence mutexes into the owned mutex
1411                  * list, but it may prove to be useful having all
1412                  * owned mutexes in this list.  Consider a thread
1413                  * exiting while holding mutexes...
1414                  */
1415                 if (m->m_protocol == PTHREAD_PRIO_INHERIT) {
1416                         /*
1417                          * Fix the owners saved (inherited) priority to
1418                          * reflect the priority of the previous mutex.
1419                          */
1420                         m->m_saved_prio = inherited_prio;
1421
1422                         if ((pthread_next = TAILQ_FIRST(&m->m_queue)) != NULL)
1423                                 /* Recalculate the priority of the mutex: */
1424                                 m->m_prio = MAX(active_prio,
1425                                      pthread_next->active_priority);
1426                         else
1427                                 m->m_prio = active_prio;
1428
1429                         /* Recalculate new inherited and active priorities: */
1430                         inherited_prio = m->m_prio;
1431                         active_prio = MAX(m->m_prio, pthread->base_priority);
1432                 }
1433         }
1434
1435         /*
1436          * Fix the threads inherited priority and recalculate its
1437          * active priority.
1438          */
1439         pthread->inherited_priority = inherited_prio;
1440         active_prio = MAX(inherited_prio, pthread->base_priority);
1441
1442         if (active_prio != pthread->active_priority) {
1443                 /* Lock the thread's scheduling queue: */
1444                 THR_THREAD_LOCK(curthread, pthread);
1445
1446                 /* if ((pthread->flags & THR_FLAGS_IN_RUNQ) == 0) */
1447                 if (1) {
1448                         /*
1449                          * This thread is not in a run queue.  Just set
1450                          * its active priority.
1451                          */
1452                         pthread->active_priority = active_prio;
1453                 }
1454                 else {
1455                         /*
1456                          * This thread is in a run queue.  Remove it from
1457                          * the queue before changing its priority:
1458                          */
1459                         /* THR_RUNQ_REMOVE(pthread);*/
1460                         /*
1461                          * POSIX states that if the priority is being
1462                          * lowered, the thread must be inserted at the
1463                          * head of the queue for its priority if it owns
1464                          * any priority protection or inheritence mutexes.
1465                          */
1466                         if ((active_prio < pthread->active_priority) &&
1467                             (pthread->priority_mutex_count > 0)) {
1468                                 /* Set the new active priority. */
1469                                 pthread->active_priority = active_prio;
1470                                 /* THR_RUNQ_INSERT_HEAD(pthread); */
1471                         } else {
1472                                 /* Set the new active priority. */
1473                                 pthread->active_priority = active_prio;
1474                                 /* THR_RUNQ_INSERT_TAIL(pthread);*/
1475                         }
1476                 }
1477                 THR_THREAD_UNLOCK(curthread, pthread);
1478         }
1479 }
1480
1481 void
1482 _mutex_unlock_private(pthread_t pthread)
1483 {
1484         struct pthread_mutex    *m, *m_next;
1485
1486         for (m = TAILQ_FIRST(&pthread->pri_mutexq); m != NULL; m = m_next) {
1487                 m_next = TAILQ_NEXT(m, m_qe);
1488                 if ((m->m_flags & MUTEX_FLAGS_PRIVATE) != 0)
1489                         pthread_mutex_unlock(&m);
1490         }
1491 }
1492
1493 /*
1494  * Dequeue a waiting thread from the head of a mutex queue in descending
1495  * priority order.
1496  *
1497  * In order to properly dequeue a thread from the mutex queue and
1498  * make it runnable without the possibility of errant wakeups, it
1499  * is necessary to lock the thread's scheduling queue while also
1500  * holding the mutex lock.
1501  */
1502 static long
1503 mutex_handoff(struct pthread *curthread, struct pthread_mutex *mutex)
1504 {
1505         struct pthread *pthread;
1506         long tid = -1;
1507
1508         /* Keep dequeueing until we find a valid thread: */
1509         mutex->m_owner = NULL;
1510         pthread = TAILQ_FIRST(&mutex->m_queue);
1511         while (pthread != NULL) {
1512                 /* Take the thread's scheduling lock: */
1513                 THR_THREAD_LOCK(curthread, pthread);
1514
1515                 /* Remove the thread from the mutex queue: */
1516                 TAILQ_REMOVE(&mutex->m_queue, pthread, sqe);
1517                 pthread->sflags &= ~THR_FLAGS_IN_SYNCQ;
1518
1519                 /*
1520                  * Only exit the loop if the thread hasn't been
1521                  * cancelled.
1522                  */
1523                 switch (mutex->m_protocol) {
1524                 case PTHREAD_PRIO_NONE:
1525                         /*
1526                          * Assign the new owner and add the mutex to the
1527                          * thread's list of owned mutexes.
1528                          */
1529                         mutex->m_owner = pthread;
1530                         TAILQ_INSERT_TAIL(&pthread->pri_mutexq, mutex, m_qe);
1531                         break;
1532
1533                 case PTHREAD_PRIO_INHERIT:
1534                         /*
1535                          * Assign the new owner and add the mutex to the
1536                          * thread's list of owned mutexes.
1537                          */
1538                         mutex->m_owner = pthread;
1539                         TAILQ_INSERT_TAIL(&pthread->pri_mutexq, mutex, m_qe);
1540
1541                         /* Track number of priority mutexes owned: */
1542                         pthread->priority_mutex_count++;
1543
1544                         /*
1545                          * Set the priority of the mutex.  Since our waiting
1546                          * threads are in descending priority order, the
1547                          * priority of the mutex becomes the active priority
1548                          * of the thread we just dequeued.
1549                          */
1550                         mutex->m_prio = pthread->active_priority;
1551
1552                         /* Save the owning threads inherited priority: */
1553                         mutex->m_saved_prio = pthread->inherited_priority;
1554
1555                         /*
1556                          * The owning threads inherited priority now becomes
1557                          * his active priority (the priority of the mutex).
1558                          */
1559                         pthread->inherited_priority = mutex->m_prio;
1560                         break;
1561
1562                 case PTHREAD_PRIO_PROTECT:
1563                         if (pthread->active_priority > mutex->m_prio) {
1564                                 /*
1565                                  * Either the mutex ceiling priority has
1566                                  * been lowered and/or this threads priority
1567                                  * has been raised subsequent to the thread
1568                                  * being queued on the waiting list.
1569                                  */
1570                                 pthread->error = EINVAL;
1571                         }
1572                         else {
1573                                 /*
1574                                  * Assign the new owner and add the mutex
1575                                  * to the thread's list of owned mutexes.
1576                                  */
1577                                 mutex->m_owner = pthread;
1578                                 TAILQ_INSERT_TAIL(&pthread->pri_mutexq,
1579                                     mutex, m_qe);
1580
1581                                 /* Track number of priority mutexes owned: */
1582                                 pthread->priority_mutex_count++;
1583
1584                                 /*
1585                                  * Save the owning threads inherited
1586                                  * priority:
1587                                  */
1588                                 mutex->m_saved_prio =
1589                                     pthread->inherited_priority;
1590
1591                                 /*
1592                                  * The owning thread inherits the ceiling
1593                                  * priority of the mutex and executes at
1594                                  * that priority:
1595                                  */
1596                                 pthread->inherited_priority = mutex->m_prio;
1597                                 pthread->active_priority = mutex->m_prio;
1598
1599                         }
1600                         break;
1601                 }
1602
1603                 /* Make the thread runnable and unlock the scheduling queue: */
1604                 pthread->cycle++;
1605                 _thr_umtx_wake(&pthread->cycle, 1);
1606
1607                 THR_THREAD_UNLOCK(curthread, pthread);
1608                 if (mutex->m_owner == pthread)
1609                         /* We're done; a valid owner was found. */
1610                         break;
1611                 else
1612                         /* Get the next thread from the waiting queue: */
1613                         pthread = TAILQ_NEXT(pthread, sqe);
1614         }
1615
1616         if ((pthread == NULL) && (mutex->m_protocol == PTHREAD_PRIO_INHERIT))
1617                 /* This mutex has no priority: */
1618                 mutex->m_prio = 0;
1619         return (tid);
1620 }
1621
1622 #if 0
1623 /*
1624  * Dequeue a waiting thread from the head of a mutex queue in descending
1625  * priority order.
1626  */
1627 static pthread_t
1628 mutex_queue_deq(struct pthread_mutex *mutex)
1629 {
1630         pthread_t pthread;
1631
1632         while ((pthread = TAILQ_FIRST(&mutex->m_queue)) != NULL) {
1633                 TAILQ_REMOVE(&mutex->m_queue, pthread, sqe);
1634                 pthread->sflags &= ~THR_FLAGS_IN_SYNCQ;
1635         }
1636
1637         return (pthread);
1638 }
1639 #endif
1640
1641 /*
1642  * Remove a waiting thread from a mutex queue in descending priority order.
1643  */
1644 static void
1645 mutex_queue_remove(pthread_mutex_t mutex, pthread_t pthread)
1646 {
1647         if ((pthread->sflags & THR_FLAGS_IN_SYNCQ) != 0) {
1648                 TAILQ_REMOVE(&mutex->m_queue, pthread, sqe);
1649                 pthread->sflags &= ~THR_FLAGS_IN_SYNCQ;
1650         }
1651 }
1652
1653 /*
1654  * Enqueue a waiting thread to a queue in descending priority order.
1655  */
1656 static void
1657 mutex_queue_enq(pthread_mutex_t mutex, pthread_t pthread)
1658 {
1659         pthread_t tid = TAILQ_LAST(&mutex->m_queue, mutex_head);
1660
1661         THR_ASSERT_NOT_IN_SYNCQ(pthread);
1662         /*
1663          * For the common case of all threads having equal priority,
1664          * we perform a quick check against the priority of the thread
1665          * at the tail of the queue.
1666          */
1667         if ((tid == NULL) || (pthread->active_priority <= tid->active_priority))
1668                 TAILQ_INSERT_TAIL(&mutex->m_queue, pthread, sqe);
1669         else {
1670                 tid = TAILQ_FIRST(&mutex->m_queue);
1671                 while (pthread->active_priority <= tid->active_priority)
1672                         tid = TAILQ_NEXT(tid, sqe);
1673                 TAILQ_INSERT_BEFORE(tid, pthread, sqe);
1674         }
1675         pthread->sflags |= THR_FLAGS_IN_SYNCQ;
1676 }