1 /* Copyright (C) 2002-2022 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3 
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8 
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
17 
18 #include <errno.h>
19 #include <semaphore.h>
20 #include <shlib-compat.h>
21 #include "semaphoreP.h"
22 #include <kernel-features.h>
23 #include <futex-internal.h>
24 
25 
26 int
__new_sem_init(sem_t * sem,int pshared,unsigned int value)27 __new_sem_init (sem_t *sem, int pshared, unsigned int value)
28 {
29   ASSERT_PTHREAD_INTERNAL_SIZE (sem_t, struct new_sem);
30 
31   /* Parameter sanity check.  */
32   if (__glibc_unlikely (value > SEM_VALUE_MAX))
33     {
34       __set_errno (EINVAL);
35       return -1;
36     }
37   pshared = pshared != 0 ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE;
38   int err = futex_supports_pshared (pshared);
39   if (err != 0)
40     {
41       __set_errno (err);
42       return -1;
43     }
44 
45   /* Map to the internal type.  */
46   struct new_sem *isem = (struct new_sem *) sem;
47 
48   /* Use the values the caller provided.  */
49 #if __HAVE_64B_ATOMICS
50   isem->data = value;
51 #else
52   isem->value = value << SEM_VALUE_SHIFT;
53   /* pad is used as a mutex on pre-v9 sparc and ignored otherwise.  */
54   isem->pad = 0;
55   isem->nwaiters = 0;
56 #endif
57 
58   isem->private = (pshared == PTHREAD_PROCESS_PRIVATE
59 		   ? FUTEX_PRIVATE : FUTEX_SHARED);
60 
61   return 0;
62 }
63 versioned_symbol (libc, __new_sem_init, sem_init, GLIBC_2_34);
64 
65 #if OTHER_SHLIB_COMPAT(libpthread, GLIBC_2_1, GLIBC_2_34)
66 compat_symbol (libpthread, __new_sem_init, sem_init, GLIBC_2_1);
67 #endif
68 
69 #if OTHER_SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
70 int
71 attribute_compat_text_section
__old_sem_init(sem_t * sem,int pshared,unsigned int value)72 __old_sem_init (sem_t *sem, int pshared, unsigned int value)
73 {
74   ASSERT_PTHREAD_INTERNAL_SIZE (sem_t, struct new_sem);
75 
76   /* Parameter sanity check.  */
77   if (__glibc_unlikely (value > SEM_VALUE_MAX))
78     {
79       __set_errno (EINVAL);
80       return -1;
81     }
82 
83   /* Map to the internal type.  */
84   struct old_sem *isem = (struct old_sem *) sem;
85 
86   /* Use the value the user provided.  */
87   isem->value = value;
88 
89   /* We cannot store the PSHARED attribute.  So we always use the
90      operations needed for shared semaphores.  */
91 
92   return 0;
93 }
94 compat_symbol (libpthread, __old_sem_init, sem_init, GLIBC_2_0);
95 #endif
96