]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re-core/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_init.c
Update
[l4.git] / l4 / pkg / l4re-core / uclibc / lib / contrib / uclibc / libpthread / nptl / pthread_mutex_init.c
1 /* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
2    Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <http://www.gnu.org/licenses/>.  */
19
20 #include <assert.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <bits/kernel-features.h>
24 #include "pthreadP.h"
25
26 static const struct pthread_mutexattr default_attr =
27   {
28     /* Default is a normal mutex, not shared between processes.  */
29     .mutexkind = PTHREAD_MUTEX_NORMAL
30   };
31
32
33 #ifndef __ASSUME_FUTEX_LOCK_PI
34 static int tpi_supported;
35 #endif
36
37
38 int
39 attribute_protected
40 __pthread_mutex_init (
41      pthread_mutex_t *mutex,
42      const pthread_mutexattr_t *mutexattr)
43 {
44   const struct pthread_mutexattr *imutexattr;
45
46   assert (sizeof (pthread_mutex_t) <= __SIZEOF_PTHREAD_MUTEX_T);
47
48   imutexattr = (const struct pthread_mutexattr *) mutexattr ?: &default_attr;
49
50   /* Sanity checks.  */
51   switch (__builtin_expect (imutexattr->mutexkind
52                             & PTHREAD_MUTEXATTR_PROTOCOL_MASK,
53                             PTHREAD_PRIO_NONE
54                             << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT))
55     {
56     case PTHREAD_PRIO_NONE << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
57       break;
58
59     case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
60 #ifndef __ASSUME_FUTEX_LOCK_PI
61       if (__builtin_expect (tpi_supported == 0, 0))
62         {
63           int lock = 0;
64           INTERNAL_SYSCALL_DECL (err);
65           int ret = INTERNAL_SYSCALL (futex, err, 4, &lock, FUTEX_UNLOCK_PI,
66                                       0, 0);
67           assert (INTERNAL_SYSCALL_ERROR_P (ret, err));
68           tpi_supported = INTERNAL_SYSCALL_ERRNO (ret, err) == ENOSYS ? -1 : 1;
69         }
70       if (__builtin_expect (tpi_supported < 0, 0))
71         return ENOTSUP;
72 #endif
73       break;
74
75     default:
76       /* XXX: For now we don't support robust priority protected mutexes.  */
77       if (imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST)
78         return ENOTSUP;
79       break;
80     }
81
82   /* Clear the whole variable.  */
83   memset (mutex, '\0', __SIZEOF_PTHREAD_MUTEX_T);
84
85   /* Copy the values from the attribute.  */
86   mutex->__data.__kind = imutexattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS;
87
88   if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0)
89     {
90 #ifndef __ASSUME_SET_ROBUST_LIST
91       if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_PSHARED) != 0
92           && __set_robust_list_avail < 0)
93         return ENOTSUP;
94 #endif
95
96       mutex->__data.__kind |= PTHREAD_MUTEX_ROBUST_NORMAL_NP;
97     }
98
99   switch (imutexattr->mutexkind & PTHREAD_MUTEXATTR_PROTOCOL_MASK)
100     {
101     case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
102       mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_INHERIT_NP;
103       break;
104
105     case PTHREAD_PRIO_PROTECT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
106       mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP;
107
108       int ceiling = (imutexattr->mutexkind
109                      & PTHREAD_MUTEXATTR_PRIO_CEILING_MASK)
110                     >> PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT;
111       if (! ceiling)
112         {
113           if (__sched_fifo_min_prio == -1)
114             __init_sched_fifo_prio ();
115           if (ceiling < __sched_fifo_min_prio)
116             ceiling = __sched_fifo_min_prio;
117         }
118       mutex->__data.__lock = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
119       break;
120
121     default:
122       break;
123     }
124
125   /* The kernel when waking robust mutexes on exit never uses
126      FUTEX_PRIVATE_FLAG FUTEX_WAKE.  */
127   if ((imutexattr->mutexkind & (PTHREAD_MUTEXATTR_FLAG_PSHARED
128                                 | PTHREAD_MUTEXATTR_FLAG_ROBUST)) != 0)
129     mutex->__data.__kind |= PTHREAD_MUTEX_PSHARED_BIT;
130
131   /* Default values: mutex not used yet.  */
132   // mutex->__count = 0;        already done by memset
133   // mutex->__owner = 0;        already done by memset
134   // mutex->__nusers = 0;       already done by memset
135   // mutex->__spins = 0;        already done by memset
136   // mutex->__next = NULL;      already done by memset
137
138   return 0;
139 }
140 strong_alias (__pthread_mutex_init, pthread_mutex_init)
141 INTDEF(__pthread_mutex_init)