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