]>
Commit | Line | Data |
---|---|---|
a1eaacb1 | 1 | '\" t |
4f37d29c MK |
2 | .\" Copyright (c) 2008 Linux Foundation, written by Michael Kerrisk |
3 | .\" <mtk.manpages@gmail.com> | |
4 | .\" | |
5fbde956 | 5 | .\" SPDX-License-Identifier: Linux-man-pages-copyleft |
4f37d29c | 6 | .\" |
4c1c5274 | 7 | .TH pthread_getattr_np 3 (date) "Linux man-pages (unreleased)" |
4f37d29c MK |
8 | .SH NAME |
9 | pthread_getattr_np \- get attributes of created thread | |
41295a69 AC |
10 | .SH LIBRARY |
11 | POSIX threads library | |
8fc3b2cf | 12 | .RI ( libpthread ", " \-lpthread ) |
4f37d29c MK |
13 | .SH SYNOPSIS |
14 | .nf | |
86b91fdf | 15 | .BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */" |
4f37d29c | 16 | .B #include <pthread.h> |
f90f031e | 17 | .PP |
4f37d29c | 18 | .BI "int pthread_getattr_np(pthread_t " thread ", pthread_attr_t *" attr ); |
6030f2d8 | 19 | .fi |
4f37d29c MK |
20 | .SH DESCRIPTION |
21 | The | |
22 | .BR pthread_getattr_np () | |
23 | function initializes the thread attributes object referred to by | |
24 | .I attr | |
25 | so that it contains actual attribute values describing the running thread | |
26 | .IR thread . | |
847e0d88 | 27 | .PP |
4f37d29c MK |
28 | The returned attribute values may differ from |
29 | the corresponding attribute values passed in the | |
30 | .I attr | |
31 | object that was used to create the thread using | |
32 | .BR pthread_create (3). | |
33 | In particular, the following attributes may differ: | |
22356d97 | 34 | .IP \(bu 3 |
4f37d29c MK |
35 | the detach state, since a joinable thread may have detached itself |
36 | after creation; | |
22356d97 | 37 | .IP \(bu |
4f37d29c MK |
38 | the stack size, |
39 | which the implementation may align to a suitable boundary. | |
22356d97 | 40 | .IP \(bu |
4f37d29c | 41 | and the guard size, |
5fab2e7c | 42 | which the implementation may round upward to a multiple of the page size, |
4f37d29c MK |
43 | or ignore (i.e., treat as 0), |
44 | if the application is allocating its own stack. | |
45 | .PP | |
46 | Furthermore, if the stack address attribute was not set | |
47 | in the thread attributes object used to create the thread, | |
48 | then the returned thread attributes object will report the actual | |
49 | stack address that the implementation selected for the thread. | |
847e0d88 | 50 | .PP |
4f37d29c MK |
51 | When the thread attributes object returned by |
52 | .BR pthread_getattr_np () | |
53 | is no longer required, it should be destroyed using | |
54 | .BR pthread_attr_destroy (3). | |
55 | .SH RETURN VALUE | |
56 | On success, this function returns 0; | |
c7094399 | 57 | on error, it returns a nonzero error number. |
4f37d29c MK |
58 | .SH ERRORS |
59 | .TP | |
60 | .B ENOMEM | |
61 | .\" Can happen (but unlikely) while trying to allocate memory for cpuset | |
62 | Insufficient memory. | |
63 | .PP | |
64 | In addition, if | |
65 | .I thread | |
66 | refers to the main thread, then | |
67 | .BR pthread_getattr_np () | |
222d90f4 | 68 | can fail because of errors from various underlying calls: |
4f37d29c MK |
69 | .BR fopen (3), |
70 | if | |
1ae6b2c7 | 71 | .I /proc/self/maps |
4f37d29c MK |
72 | can't be opened; |
73 | and | |
74 | .BR getrlimit (2), | |
75 | if the | |
1ae6b2c7 | 76 | .B RLIMIT_STACK |
4f37d29c MK |
77 | resource limit is not supported. |
78 | .SH VERSIONS | |
b324e17d | 79 | This function is available since glibc 2.2.3. |
5effafa2 ZL |
80 | .SH ATTRIBUTES |
81 | For an explanation of the terms used in this section, see | |
82 | .BR attributes (7). | |
74714ea8 | 83 | .ad l |
c466875e | 84 | .nh |
5effafa2 ZL |
85 | .TS |
86 | allbox; | |
c466875e | 87 | lbx lb lb |
5effafa2 ZL |
88 | l l l. |
89 | Interface Attribute Value | |
90 | T{ | |
91 | .BR pthread_getattr_np () | |
92 | T} Thread safety MT-Safe | |
93 | .TE | |
c466875e | 94 | .hy |
74714ea8 | 95 | .ad |
c466875e | 96 | .sp 1 |
3113c7f3 | 97 | .SH STANDARDS |
583dc9ac | 98 | This function is a nonstandard GNU extension; |
d603cc27 | 99 | hence the suffix "_np" (nonportable) in the name. |
a14af333 | 100 | .SH EXAMPLES |
4f37d29c MK |
101 | The program below demonstrates the use of |
102 | .BR pthread_getattr_np (). | |
103 | The program creates a thread that then uses | |
104 | .BR pthread_getattr_np () | |
105 | to retrieve and display its guard size, stack address, | |
106 | and stack size attributes. | |
107 | Command-line arguments can be used to set these attributes | |
108 | to values other than the default when creating the thread. | |
109 | The shell sessions below demonstrate the use of the program. | |
847e0d88 | 110 | .PP |
4f37d29c MK |
111 | In the first run, on an x86-32 system, |
112 | a thread is created using default attributes: | |
847e0d88 | 113 | .PP |
4f37d29c | 114 | .in +4n |
b8302363 | 115 | .EX |
ee8655b5 | 116 | .RB "$" " ulimit \-s" " # No stack limit ==> default stack size is 2 MB" |
4f37d29c | 117 | unlimited |
b43a3b30 | 118 | .RB "$" " ./a.out" |
4f37d29c MK |
119 | Attributes of created thread: |
120 | Guard size = 4096 bytes | |
121 | Stack address = 0x40196000 (EOS = 0x40397000) | |
122 | Stack size = 0x201000 (2101248) bytes | |
b8302363 | 123 | .EE |
4f37d29c | 124 | .in |
847e0d88 | 125 | .PP |
4f37d29c MK |
126 | In the following run, we see that if a guard size is specified, |
127 | it is rounded up to the next multiple of the system page size | |
128 | (4096 bytes on x86-32): | |
847e0d88 | 129 | .PP |
4f37d29c | 130 | .in +4n |
b8302363 | 131 | .EX |
b43a3b30 | 132 | .RB "$" " ./a.out \-g 4097" |
4f37d29c MK |
133 | Thread attributes object after initializations: |
134 | Guard size = 4097 bytes | |
135 | Stack address = (nil) | |
136 | Stack size = 0x0 (0) bytes | |
137 | ||
138 | Attributes of created thread: | |
139 | Guard size = 8192 bytes | |
140 | Stack address = 0x40196000 (EOS = 0x40397000) | |
141 | Stack size = 0x201000 (2101248) bytes | |
b8302363 | 142 | .EE |
4f37d29c MK |
143 | .in |
144 | .\".in +4n | |
145 | .\".nf | |
146 | .\"$ ./a.out \-s 0x8000 | |
147 | .\"Thread attributes object after initializations: | |
148 | .\" Guard size = 4096 bytes | |
149 | .\" Stack address = 0xffff8000 (EOS = (nil)) | |
150 | .\" Stack size = 0x8000 (32768) bytes | |
151 | .\" | |
152 | .\"Attributes of created thread: | |
153 | .\" Guard size = 4096 bytes | |
154 | .\" Stack address = 0x4001e000 (EOS = 0x40026000) | |
155 | .\" Stack size = 0x8000 (32768) bytes | |
156 | .\".fi | |
157 | .\".in | |
847e0d88 | 158 | .PP |
4f37d29c MK |
159 | In the last run, the program manually allocates a stack for the thread. |
160 | In this case, the guard size attribute is ignored. | |
847e0d88 | 161 | .PP |
4f37d29c | 162 | .in +4n |
b8302363 | 163 | .EX |
b43a3b30 | 164 | .RB "$" " ./a.out \-g 4096 \-s 0x8000 \-a" |
4f37d29c MK |
165 | Allocated thread stack at 0x804d000 |
166 | ||
167 | Thread attributes object after initializations: | |
168 | Guard size = 4096 bytes | |
169 | Stack address = 0x804d000 (EOS = 0x8055000) | |
170 | Stack size = 0x8000 (32768) bytes | |
171 | ||
172 | Attributes of created thread: | |
173 | Guard size = 0 bytes | |
174 | Stack address = 0x804d000 (EOS = 0x8055000) | |
175 | Stack size = 0x8000 (32768) bytes | |
b8302363 | 176 | .EE |
4f37d29c | 177 | .in |
9c330504 | 178 | .SS Program source |
d84d0300 | 179 | \& |
b0b6ab4e | 180 | .\" SRC BEGIN (pthread_getattr_np.c) |
e7d0bb47 | 181 | .EX |
4f37d29c | 182 | #define _GNU_SOURCE /* To get pthread_getattr_np() declaration */ |
5a5208c1 | 183 | #include <err.h> |
ad3868f0 | 184 | #include <errno.h> |
4f37d29c MK |
185 | #include <pthread.h> |
186 | #include <stdio.h> | |
187 | #include <stdlib.h> | |
188 | #include <unistd.h> | |
4f37d29c | 189 | |
4f37d29c MK |
190 | static void |
191 | display_stack_related_attributes(pthread_attr_t *attr, char *prefix) | |
192 | { | |
193 | int s; | |
194 | size_t stack_size, guard_size; | |
195 | void *stack_addr; | |
196 | ||
197 | s = pthread_attr_getguardsize(attr, &guard_size); | |
198 | if (s != 0) | |
5a5208c1 | 199 | errc(EXIT_FAILURE, s, "pthread_attr_getguardsize"); |
037c6fd4 | 200 | printf("%sGuard size = %zu bytes\en", prefix, guard_size); |
4f37d29c MK |
201 | |
202 | s = pthread_attr_getstack(attr, &stack_addr, &stack_size); | |
203 | if (s != 0) | |
5a5208c1 | 204 | errc(EXIT_FAILURE, s, "pthread_attr_getstack"); |
4f37d29c MK |
205 | printf("%sStack address = %p", prefix, stack_addr); |
206 | if (stack_size > 0) | |
207 | printf(" (EOS = %p)", (char *) stack_addr + stack_size); | |
d1a71985 | 208 | printf("\en"); |
dc97703b | 209 | printf("%sStack size = %#zx (%zu) bytes\en", |
d917c31d | 210 | prefix, stack_size, stack_size); |
4f37d29c MK |
211 | } |
212 | ||
213 | static void | |
214 | display_thread_attributes(pthread_t thread, char *prefix) | |
215 | { | |
216 | int s; | |
217 | pthread_attr_t attr; | |
218 | ||
219 | s = pthread_getattr_np(thread, &attr); | |
220 | if (s != 0) | |
5a5208c1 | 221 | errc(EXIT_FAILURE, s, "pthread_getattr_np"); |
4f37d29c MK |
222 | |
223 | display_stack_related_attributes(&attr, prefix); | |
224 | ||
225 | s = pthread_attr_destroy(&attr); | |
226 | if (s != 0) | |
5a5208c1 | 227 | errc(EXIT_FAILURE, s, "pthread_attr_destroy"); |
4f37d29c MK |
228 | } |
229 | ||
230 | static void * /* Start function for thread we create */ | |
231 | thread_start(void *arg) | |
232 | { | |
d1a71985 MK |
233 | printf("Attributes of created thread:\en"); |
234 | display_thread_attributes(pthread_self(), "\et"); | |
4f37d29c MK |
235 | |
236 | exit(EXIT_SUCCESS); /* Terminate all threads */ | |
237 | } | |
238 | ||
239 | static void | |
240 | usage(char *pname, char *msg) | |
241 | { | |
242 | if (msg != NULL) | |
243 | fputs(msg, stderr); | |
72da9ef1 | 244 | fprintf(stderr, "Usage: %s [\-s stack\-size [\-a]]" |
d1a71985 MK |
245 | " [\-g guard\-size]\en", pname); |
246 | fprintf(stderr, "\et\et\-a means program should allocate stack\en"); | |
4f37d29c MK |
247 | exit(EXIT_FAILURE); |
248 | } | |
249 | ||
250 | static pthread_attr_t * /* Get thread attributes from command line */ | |
251 | get_thread_attributes_from_cl(int argc, char *argv[], | |
252 | pthread_attr_t *attrp) | |
253 | { | |
254 | int s, opt, allocate_stack; | |
7d974613 | 255 | size_t stack_size, guard_size; |
404990ae | 256 | void *stack_addr; |
4f37d29c MK |
257 | pthread_attr_t *ret_attrp = NULL; /* Set to attrp if we initialize |
258 | a thread attributes object */ | |
259 | allocate_stack = 0; | |
260 | stack_size = \-1; | |
261 | guard_size = \-1; | |
262 | ||
263 | while ((opt = getopt(argc, argv, "ag:s:")) != \-1) { | |
264 | switch (opt) { | |
ce5139ca MK |
265 | case \(aqa\(aq: allocate_stack = 1; break; |
266 | case \(aqg\(aq: guard_size = strtoul(optarg, NULL, 0); break; | |
267 | case \(aqs\(aq: stack_size = strtoul(optarg, NULL, 0); break; | |
4f37d29c MK |
268 | default: usage(argv[0], NULL); |
269 | } | |
270 | } | |
271 | ||
272 | if (allocate_stack && stack_size == \-1) | |
d1a71985 | 273 | usage(argv[0], "Specifying \-a without \-s makes no sense\en"); |
4f37d29c MK |
274 | |
275 | if (argc > optind) | |
d1a71985 | 276 | usage(argv[0], "Extraneous command\-line arguments\en"); |
4f37d29c MK |
277 | |
278 | if (stack_size >= 0 || guard_size > 0) { | |
279 | ret_attrp = attrp; | |
280 | ||
281 | s = pthread_attr_init(attrp); | |
282 | if (s != 0) | |
5a5208c1 | 283 | errc(EXIT_FAILURE, s, "pthread_attr_init"); |
4f37d29c MK |
284 | } |
285 | ||
286 | if (stack_size >= 0) { | |
287 | if (!allocate_stack) { | |
288 | s = pthread_attr_setstacksize(attrp, stack_size); | |
289 | if (s != 0) | |
5a5208c1 | 290 | errc(EXIT_FAILURE, s, "pthread_attr_setstacksize"); |
4f37d29c MK |
291 | } else { |
292 | s = posix_memalign(&stack_addr, sysconf(_SC_PAGESIZE), | |
293 | stack_size); | |
294 | if (s != 0) | |
5a5208c1 | 295 | errc(EXIT_FAILURE, s, "posix_memalign"); |
d1a71985 | 296 | printf("Allocated thread stack at %p\en\en", stack_addr); |
4f37d29c MK |
297 | |
298 | s = pthread_attr_setstack(attrp, stack_addr, stack_size); | |
299 | if (s != 0) | |
5a5208c1 | 300 | errc(EXIT_FAILURE, s, "pthread_attr_setstacksize"); |
4f37d29c MK |
301 | } |
302 | } | |
303 | ||
304 | if (guard_size >= 0) { | |
305 | s = pthread_attr_setguardsize(attrp, guard_size); | |
306 | if (s != 0) | |
5a5208c1 | 307 | errc(EXIT_FAILURE, s, "pthread_attr_setstacksize"); |
4f37d29c MK |
308 | } |
309 | ||
310 | return ret_attrp; | |
311 | } | |
312 | ||
313 | int | |
314 | main(int argc, char *argv[]) | |
315 | { | |
316 | int s; | |
317 | pthread_t thr; | |
318 | pthread_attr_t attr; | |
319 | pthread_attr_t *attrp = NULL; /* Set to &attr if we initialize | |
320 | a thread attributes object */ | |
321 | ||
322 | attrp = get_thread_attributes_from_cl(argc, argv, &attr); | |
323 | ||
324 | if (attrp != NULL) { | |
d1a71985 MK |
325 | printf("Thread attributes object after initializations:\en"); |
326 | display_stack_related_attributes(attrp, "\et"); | |
327 | printf("\en"); | |
4f37d29c MK |
328 | } |
329 | ||
330 | s = pthread_create(&thr, attrp, &thread_start, NULL); | |
331 | if (s != 0) | |
5a5208c1 | 332 | errc(EXIT_FAILURE, s, "pthread_create"); |
4f37d29c MK |
333 | |
334 | if (attrp != NULL) { | |
335 | s = pthread_attr_destroy(attrp); | |
336 | if (s != 0) | |
5a5208c1 | 337 | errc(EXIT_FAILURE, s, "pthread_attr_destroy"); |
4f37d29c MK |
338 | } |
339 | ||
340 | pause(); /* Terminates when other thread calls exit() */ | |
341 | } | |
e7d0bb47 | 342 | .EE |
b0b6ab4e | 343 | .\" SRC END |
4f37d29c | 344 | .SH SEE ALSO |
ca8a0bd2 MK |
345 | .ad l |
346 | .nh | |
4f37d29c MK |
347 | .BR pthread_attr_getaffinity_np (3), |
348 | .BR pthread_attr_getdetachstate (3), | |
349 | .BR pthread_attr_getguardsize (3), | |
350 | .BR pthread_attr_getinheritsched (3), | |
351 | .BR pthread_attr_getschedparam (3), | |
352 | .BR pthread_attr_getschedpolicy (3), | |
353 | .BR pthread_attr_getscope (3), | |
354 | .BR pthread_attr_getstack (3), | |
355 | .BR pthread_attr_getstackaddr (3), | |
356 | .BR pthread_attr_getstacksize (3), | |
357 | .BR pthread_attr_init (3), | |
358 | .BR pthread_create (3), | |
359 | .BR pthreads (7) |