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