Back to index

glibc  2.9
pthread_mutex_init.c
Go to the documentation of this file.
00001 /* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
00002    Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include <assert.h>
00022 #include <errno.h>
00023 #include <string.h>
00024 #include <kernel-features.h>
00025 #include "pthreadP.h"
00026 
00027 static const struct pthread_mutexattr default_attr =
00028   {
00029     /* Default is a normal mutex, not shared between processes.  */
00030     .mutexkind = PTHREAD_MUTEX_NORMAL
00031   };
00032 
00033 
00034 #ifndef __ASSUME_FUTEX_LOCK_PI
00035 static int tpi_supported;
00036 #endif
00037 
00038 
00039 int
00040 __pthread_mutex_init (mutex, mutexattr)
00041      pthread_mutex_t *mutex;
00042      const pthread_mutexattr_t *mutexattr;
00043 {
00044   const struct pthread_mutexattr *imutexattr;
00045 
00046   assert (sizeof (pthread_mutex_t) <= __SIZEOF_PTHREAD_MUTEX_T);
00047 
00048   imutexattr = (const struct pthread_mutexattr *) mutexattr ?: &default_attr;
00049 
00050   /* Sanity checks.  */
00051   switch (__builtin_expect (imutexattr->mutexkind
00052                          & PTHREAD_MUTEXATTR_PROTOCOL_MASK,
00053                          PTHREAD_PRIO_NONE
00054                          << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT))
00055     {
00056     case PTHREAD_PRIO_NONE << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
00057       break;
00058 
00059     case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
00060 #ifndef __ASSUME_FUTEX_LOCK_PI
00061       if (__builtin_expect (tpi_supported == 0, 0))
00062        {
00063          int lock = 0;
00064          INTERNAL_SYSCALL_DECL (err);
00065          int ret = INTERNAL_SYSCALL (futex, err, 4, &lock, FUTEX_UNLOCK_PI,
00066                                   0, 0);
00067          assert (INTERNAL_SYSCALL_ERROR_P (ret, err));
00068          tpi_supported = INTERNAL_SYSCALL_ERRNO (ret, err) == ENOSYS ? -1 : 1;
00069        }
00070       if (__builtin_expect (tpi_supported < 0, 0))
00071        return ENOTSUP;
00072 #endif
00073       break;
00074 
00075     default:
00076       /* XXX: For now we don't support robust priority protected mutexes.  */
00077       if (imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST)
00078        return ENOTSUP;
00079       break;
00080     }
00081 
00082   /* Clear the whole variable.  */
00083   memset (mutex, '\0', __SIZEOF_PTHREAD_MUTEX_T);
00084 
00085   /* Copy the values from the attribute.  */
00086   mutex->__data.__kind = imutexattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS;
00087 
00088   if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0)
00089     {
00090 #ifndef __ASSUME_SET_ROBUST_LIST
00091       if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_PSHARED) != 0
00092          && __set_robust_list_avail < 0)
00093        return ENOTSUP;
00094 #endif
00095 
00096       mutex->__data.__kind |= PTHREAD_MUTEX_ROBUST_NORMAL_NP;
00097     }
00098 
00099   switch (imutexattr->mutexkind & PTHREAD_MUTEXATTR_PROTOCOL_MASK)
00100     {
00101     case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
00102       mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_INHERIT_NP;
00103       break;
00104 
00105     case PTHREAD_PRIO_PROTECT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
00106       mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP;
00107 
00108       int ceiling = (imutexattr->mutexkind
00109                    & PTHREAD_MUTEXATTR_PRIO_CEILING_MASK)
00110                   >> PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT;
00111       if (! ceiling)
00112        {
00113          if (__sched_fifo_min_prio == -1)
00114            __init_sched_fifo_prio ();
00115          if (ceiling < __sched_fifo_min_prio)
00116            ceiling = __sched_fifo_min_prio;
00117        }
00118       mutex->__data.__lock = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
00119       break;
00120 
00121     default:
00122       break;
00123     }
00124 
00125   /* The kernel when waking robust mutexes on exit never uses
00126      FUTEX_PRIVATE_FLAG FUTEX_WAKE.  */
00127   if ((imutexattr->mutexkind & (PTHREAD_MUTEXATTR_FLAG_PSHARED
00128                             | PTHREAD_MUTEXATTR_FLAG_ROBUST)) != 0)
00129     mutex->__data.__kind |= PTHREAD_MUTEX_PSHARED_BIT;
00130 
00131   /* Default values: mutex not used yet.  */
00132   // mutex->__count = 0;    already done by memset
00133   // mutex->__owner = 0;    already done by memset
00134   // mutex->__nusers = 0;   already done by memset
00135   // mutex->__spins = 0;    already done by memset
00136   // mutex->__next = NULL;  already done by memset
00137 
00138   return 0;
00139 }
00140 strong_alias (__pthread_mutex_init, pthread_mutex_init)
00141 INTDEF(__pthread_mutex_init)