]> git.ipfire.org Git - thirdparty/glibc.git/blame - nptl/pthread_getattr_np.c
sparc (64bit): Regenerate ulps
[thirdparty/glibc.git] / nptl / pthread_getattr_np.c
CommitLineData
6d7e8eda 1/* Copyright (C) 2002-2023 Free Software Foundation, Inc.
76a50749 2 This file is part of the GNU C Library.
76a50749
UD
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
59ba27a6 15 License along with the GNU C Library; if not, see
5a82c748 16 <https://www.gnu.org/licenses/>. */
76a50749 17
92ce4676
UD
18#include <assert.h>
19#include <errno.h>
20#include <inttypes.h>
21#include <stdio.h>
22#include <stdio_ext.h>
23#include <stdlib.h>
76a50749 24#include <string.h>
92ce4676 25#include <sys/resource.h>
76a50749
UD
26#include "pthreadP.h"
27#include <lowlevellock.h>
6bae8725 28#include <ldsodefs.h>
76a50749
UD
29
30
31int
07a73d52 32__pthread_getattr_np (pthread_t thread_id, pthread_attr_t *attr)
76a50749
UD
33{
34 struct pthread *thread = (struct pthread *) thread_id;
86ed0774
FW
35
36 /* Prepare the new thread attribute. */
37 int ret = __pthread_attr_init (attr);
38 if (ret != 0)
39 return ret;
40
76a50749
UD
41 struct pthread_attr *iattr = (struct pthread_attr *) attr;
42
e51deae7 43 lll_lock (thread->lock, LLL_PRIVATE);
76a50749
UD
44
45 /* The thread library is responsible for keeping the values in the
46 thread desriptor up-to-date in case the user changes them. */
47 memcpy (&iattr->schedparam, &thread->schedparam,
48 sizeof (struct sched_param));
49 iattr->schedpolicy = thread->schedpolicy;
50
51 /* Clear the flags work. */
52 iattr->flags = thread->flags;
53
54 /* The thread might be detached by now. */
55 if (IS_DETACHED (thread))
56 iattr->flags |= ATTR_FLAG_DETACHSTATE;
57
58 /* This is the guardsize after adjusting it. */
5adac0e4 59 iattr->guardsize = thread->reported_guardsize;
76a50749
UD
60
61 /* The sizes are subject to alignment. */
a1ffb40e 62 if (__glibc_likely (thread->stackblock != NULL))
92ce4676 63 {
630f4cc3
SN
64 /* The stack size reported to the user should not include the
65 guard size. */
66 iattr->stacksize = thread->stackblock_size - thread->guardsize;
d615a473 67#if _STACK_GROWS_DOWN
630f4cc3
SN
68 iattr->stackaddr = (char *) thread->stackblock
69 + thread->stackblock_size;
d615a473
CD
70#else
71 iattr->stackaddr = (char *) thread->stackblock;
72#endif
92ce4676
UD
73 }
74 else
75 {
76 /* No stack information available. This must be for the initial
77 thread. Get the info in some magical way. */
92ce4676 78
92ce4676
UD
79 /* Stack size limit. */
80 struct rlimit rl;
81
82 /* The safest way to get the top of the stack is to read
83 /proc/self/maps and locate the line into which
84 __libc_stack_end falls. */
312be3f9 85 FILE *fp = fopen ("/proc/self/maps", "rce");
92ce4676
UD
86 if (fp == NULL)
87 ret = errno;
88 /* We need the limit of the stack in any case. */
92ce4676
UD
89 else
90 {
07a73d52 91 if (__getrlimit (RLIMIT_STACK, &rl) != 0)
0292b0dd
UD
92 ret = errno;
93 else
94 {
9c6ea9fa
SP
95 /* We consider the main process stack to have ended with
96 the page containing __libc_stack_end. There is stuff below
97 it in the stack too, like the program arguments, environment
98 variables and auxv info, but we ignore those pages when
99 returning size so that the output is consistent when the
100 stack is marked executable due to a loaded DSO requiring
101 it. */
102 void *stack_end = (void *) ((uintptr_t) __libc_stack_end
103 & -(uintptr_t) GLRO(dl_pagesize));
104#if _STACK_GROWS_DOWN
105 stack_end += GLRO(dl_pagesize);
106#endif
0292b0dd
UD
107 /* We need no locking. */
108 __fsetlocking (fp, FSETLOCKING_BYCALLER);
92ce4676 109
0292b0dd
UD
110 /* Until we found an entry (which should always be the case)
111 mark the result as a failure. */
112 ret = ENOENT;
92ce4676 113
0292b0dd
UD
114 char *line = NULL;
115 size_t linelen = 0;
d615a473 116#if _STACK_GROWS_DOWN
0292b0dd 117 uintptr_t last_to = 0;
d615a473 118#endif
92ce4676 119
0292b0dd 120 while (! feof_unlocked (fp))
92ce4676 121 {
07a73d52 122 if (__getline (&line, &linelen, fp) <= 0)
0292b0dd
UD
123 break;
124
125 uintptr_t from;
126 uintptr_t to;
127 if (sscanf (line, "%" SCNxPTR "-%" SCNxPTR, &from, &to) != 2)
128 continue;
129 if (from <= (uintptr_t) __libc_stack_end
130 && (uintptr_t) __libc_stack_end < to)
131 {
132 /* Found the entry. Now we have the info we need. */
9c6ea9fa 133 iattr->stackaddr = stack_end;
18b5e737
SP
134 iattr->stacksize =
135 rl.rlim_cur - (size_t) (to - (uintptr_t) stack_end);
136
137 /* Cut it down to align it to page size since otherwise we
138 risk going beyond rlimit when the kernel rounds up the
139 stack extension request. */
140 iattr->stacksize = (iattr->stacksize
141 & -(intptr_t) GLRO(dl_pagesize));
d615a473 142#if _STACK_GROWS_DOWN
0292b0dd
UD
143 /* The limit might be too high. */
144 if ((size_t) iattr->stacksize
145 > (size_t) iattr->stackaddr - last_to)
146 iattr->stacksize = (size_t) iattr->stackaddr - last_to;
d615a473
CD
147#else
148 /* The limit might be too high. */
149 if ((size_t) iattr->stacksize
150 > to - (size_t) iattr->stackaddr)
151 iattr->stacksize = to - (size_t) iattr->stackaddr;
152#endif
0292b0dd
UD
153 /* We succeed and no need to look further. */
154 ret = 0;
155 break;
156 }
d615a473 157#if _STACK_GROWS_DOWN
0292b0dd 158 last_to = to;
d615a473 159#endif
92ce4676 160 }
0292b0dd
UD
161
162 free (line);
92ce4676
UD
163 }
164
165 fclose (fp);
92ce4676
UD
166 }
167 }
168
76a50749
UD
169 iattr->flags |= ATTR_FLAG_STACKADDR;
170
06f6ca90
UD
171 if (ret == 0)
172 {
61645263 173 size_t size = 16;
439ff07b
UD
174 cpu_set_t *cpuset = NULL;
175
176 do
06f6ca90 177 {
61645263
UD
178 size <<= 1;
179
439ff07b
UD
180 void *newp = realloc (cpuset, size);
181 if (newp == NULL)
06f6ca90 182 {
439ff07b 183 ret = ENOMEM;
61645263 184 break;
06f6ca90 185 }
439ff07b
UD
186 cpuset = (cpu_set_t *) newp;
187
188 ret = __pthread_getaffinity_np (thread_id, size, cpuset);
189 }
190 /* Pick some ridiculous upper limit. Is 8 million CPUs enough? */
191 while (ret == EINVAL && size < 1024 * 1024);
192
193 if (ret == 0)
86ed0774
FW
194 ret = __pthread_attr_setaffinity_np (attr, size, cpuset);
195 else if (ret == ENOSYS)
196 /* There is no such functionality. */
197 ret = 0;
198 free (cpuset);
06f6ca90
UD
199 }
200
e51deae7 201 lll_unlock (thread->lock, LLL_PRIVATE);
76a50749 202
86ed0774
FW
203 if (ret != 0)
204 __pthread_attr_destroy (attr);
205
92ce4676 206 return ret;
76a50749 207}
07a73d52
FW
208versioned_symbol (libc, __pthread_getattr_np, pthread_getattr_np, GLIBC_2_32);
209
210#if SHLIB_COMPAT (libc, GLIBC_2_2_3, GLIBC_2_32)
211strong_alias (__pthread_getattr_np, __pthread_getattr_np_alias)
212compat_symbol (libc, __pthread_getattr_np_alias,
213 pthread_getattr_np, GLIBC_2_2_3);
214#endif