blob: 0d79374ac6cde60a7d1006bdd4771b203b161fbb [file] [log] [blame]
Elliott Hughes3e898472013-02-12 16:40:24 +00001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <pthread.h>
30
Elliott Hughes57b7a612014-08-25 17:26:50 -070031#include <inttypes.h>
32#include <stdio.h>
33#include <sys/resource.h>
Elliott Hughes9afb2f22014-10-09 14:01:47 -070034#include <unistd.h>
Elliott Hughes57b7a612014-08-25 17:26:50 -070035
Christopher Ferris7a3681e2017-04-24 17:48:32 -070036#include <async_safe/log.h>
37
Elliott Hughes57b7a612014-08-25 17:26:50 -070038#include "private/bionic_string_utils.h"
39#include "private/ErrnoRestorer.h"
Elliott Hughes3e898472013-02-12 16:40:24 +000040#include "pthread_internal.h"
41
Elliott Hughes3e898472013-02-12 16:40:24 +000042int pthread_attr_init(pthread_attr_t* attr) {
Elliott Hughes6d339182013-02-12 16:36:04 -080043 attr->flags = 0;
44 attr->stack_base = NULL;
Brian Carlstrom50af69e2013-09-13 16:34:43 -070045 attr->stack_size = PTHREAD_STACK_SIZE_DEFAULT;
Elliott Hughesd6c678c2017-06-27 17:01:57 -070046 attr->guard_size = PTHREAD_GUARD_SIZE;
Elliott Hughes6d339182013-02-12 16:36:04 -080047 attr->sched_policy = SCHED_NORMAL;
48 attr->sched_priority = 0;
Elliott Hughes3e898472013-02-12 16:40:24 +000049 return 0;
50}
51
52int pthread_attr_destroy(pthread_attr_t* attr) {
53 memset(attr, 0x42, sizeof(pthread_attr_t));
54 return 0;
55}
56
Elliott Hughes8aecba72017-10-17 15:34:41 -070057int pthread_attr_setinheritsched(pthread_attr_t* attr, int flag) {
58 if (flag == PTHREAD_EXPLICIT_SCHED) {
59 attr->flags &= ~PTHREAD_ATTR_FLAG_INHERIT;
60 } else if (flag == PTHREAD_INHERIT_SCHED) {
61 attr->flags |= PTHREAD_ATTR_FLAG_INHERIT;
62 } else {
63 return EINVAL;
64 }
65 return 0;
66}
67
68int pthread_attr_getinheritsched(const pthread_attr_t* attr, int* flag) {
69 *flag = (attr->flags & PTHREAD_ATTR_FLAG_INHERIT) ? PTHREAD_INHERIT_SCHED
70 : PTHREAD_EXPLICIT_SCHED;
71 return 0;
72}
73
Elliott Hughes3e898472013-02-12 16:40:24 +000074int pthread_attr_setdetachstate(pthread_attr_t* attr, int state) {
75 if (state == PTHREAD_CREATE_DETACHED) {
76 attr->flags |= PTHREAD_ATTR_FLAG_DETACHED;
77 } else if (state == PTHREAD_CREATE_JOINABLE) {
78 attr->flags &= ~PTHREAD_ATTR_FLAG_DETACHED;
79 } else {
80 return EINVAL;
81 }
82 return 0;
83}
84
Elliott Hughesc3f11402013-10-30 14:40:09 -070085int pthread_attr_getdetachstate(const pthread_attr_t* attr, int* state) {
Elliott Hughes3e898472013-02-12 16:40:24 +000086 *state = (attr->flags & PTHREAD_ATTR_FLAG_DETACHED) ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE;
87 return 0;
88}
89
90int pthread_attr_setschedpolicy(pthread_attr_t* attr, int policy) {
91 attr->sched_policy = policy;
92 return 0;
93}
94
Elliott Hughesc3f11402013-10-30 14:40:09 -070095int pthread_attr_getschedpolicy(const pthread_attr_t* attr, int* policy) {
Elliott Hughes3e898472013-02-12 16:40:24 +000096 *policy = attr->sched_policy;
97 return 0;
98}
99
Elliott Hughesc3f11402013-10-30 14:40:09 -0700100int pthread_attr_setschedparam(pthread_attr_t* attr, const sched_param* param) {
Elliott Hughes3e898472013-02-12 16:40:24 +0000101 attr->sched_priority = param->sched_priority;
102 return 0;
103}
104
Elliott Hughesc3f11402013-10-30 14:40:09 -0700105int pthread_attr_getschedparam(const pthread_attr_t* attr, sched_param* param) {
Elliott Hughes3e898472013-02-12 16:40:24 +0000106 param->sched_priority = attr->sched_priority;
107 return 0;
108}
109
110int pthread_attr_setstacksize(pthread_attr_t* attr, size_t stack_size) {
Elliott Hughesb95cf0d2013-07-15 14:51:07 -0700111 if (stack_size < PTHREAD_STACK_MIN) {
Elliott Hughes3e898472013-02-12 16:40:24 +0000112 return EINVAL;
113 }
114 attr->stack_size = stack_size;
115 return 0;
116}
117
Elliott Hughesc3f11402013-10-30 14:40:09 -0700118int pthread_attr_getstacksize(const pthread_attr_t* attr, size_t* stack_size) {
Elliott Hughes57b7a612014-08-25 17:26:50 -0700119 void* unused;
120 return pthread_attr_getstack(attr, &unused, stack_size);
Elliott Hughes3e898472013-02-12 16:40:24 +0000121}
122
Elliott Hughes3e898472013-02-12 16:40:24 +0000123int pthread_attr_setstack(pthread_attr_t* attr, void* stack_base, size_t stack_size) {
124 if ((stack_size & (PAGE_SIZE - 1) || stack_size < PTHREAD_STACK_MIN)) {
125 return EINVAL;
126 }
Elliott Hughes405f8552013-10-01 17:25:28 -0700127 if (reinterpret_cast<uintptr_t>(stack_base) & (PAGE_SIZE - 1)) {
Elliott Hughes3e898472013-02-12 16:40:24 +0000128 return EINVAL;
129 }
130 attr->stack_base = stack_base;
131 attr->stack_size = stack_size;
132 return 0;
133}
134
Mor-sarid, Nitzan56933322015-09-11 05:31:36 +0000135static uintptr_t __get_main_stack_startstack() {
136 FILE* fp = fopen("/proc/self/stat", "re");
137 if (fp == nullptr) {
Christopher Ferris7a3681e2017-04-24 17:48:32 -0700138 async_safe_fatal("couldn't open /proc/self/stat: %s", strerror(errno));
Mor-sarid, Nitzan56933322015-09-11 05:31:36 +0000139 }
140
141 char line[BUFSIZ];
142 if (fgets(line, sizeof(line), fp) == nullptr) {
Christopher Ferris7a3681e2017-04-24 17:48:32 -0700143 async_safe_fatal("couldn't read /proc/self/stat: %s", strerror(errno));
Mor-sarid, Nitzan56933322015-09-11 05:31:36 +0000144 }
145
146 fclose(fp);
147
148 // See man 5 proc. There's no reason comm can't contain ' ' or ')',
149 // so we search backwards for the end of it. We're looking for this field:
150 //
151 // startstack %lu (28) The address of the start (i.e., bottom) of the stack.
152 uintptr_t startstack = 0;
153 const char* end_of_comm = strrchr(line, ')');
154 if (sscanf(end_of_comm + 1, " %*c "
155 "%*d %*d %*d %*d %*d "
156 "%*u %*u %*u %*u %*u %*u %*u "
157 "%*d %*d %*d %*d %*d %*d "
158 "%*u %*u %*d %*u %*u %*u %" SCNuPTR, &startstack) != 1) {
Christopher Ferris7a3681e2017-04-24 17:48:32 -0700159 async_safe_fatal("couldn't parse /proc/self/stat");
Mor-sarid, Nitzan56933322015-09-11 05:31:36 +0000160 }
161
162 return startstack;
163}
164
Elliott Hughes57b7a612014-08-25 17:26:50 -0700165static int __pthread_attr_getstack_main_thread(void** stack_base, size_t* stack_size) {
166 ErrnoRestorer errno_restorer;
167
Elliott Hughes9e4ffa72014-08-27 15:32:01 -0700168 rlimit stack_limit;
169 if (getrlimit(RLIMIT_STACK, &stack_limit) == -1) {
170 return errno;
171 }
172
173 // If the current RLIMIT_STACK is RLIM_INFINITY, only admit to an 8MiB stack for sanity's sake.
174 if (stack_limit.rlim_cur == RLIM_INFINITY) {
175 stack_limit.rlim_cur = 8 * 1024 * 1024;
176 }
177
Mor-sarid, Nitzan56933322015-09-11 05:31:36 +0000178 // Ask the kernel where our main thread's stack started.
179 uintptr_t startstack = __get_main_stack_startstack();
180
181 // Hunt for the region that contains that address.
182 FILE* fp = fopen("/proc/self/maps", "re");
183 if (fp == nullptr) {
Elliott Hughes7b0af7a2017-09-15 16:09:22 -0700184 async_safe_fatal("couldn't open /proc/self/maps: %s", strerror(errno));
Elliott Hughes57b7a612014-08-25 17:26:50 -0700185 }
186 char line[BUFSIZ];
187 while (fgets(line, sizeof(line), fp) != NULL) {
Mor-sarid, Nitzan56933322015-09-11 05:31:36 +0000188 uintptr_t lo, hi;
189 if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR, &lo, &hi) == 2) {
190 if (lo <= startstack && startstack <= hi) {
Elliott Hughes9e4ffa72014-08-27 15:32:01 -0700191 *stack_size = stack_limit.rlim_cur;
192 *stack_base = reinterpret_cast<void*>(hi - *stack_size);
Elliott Hughes57b7a612014-08-25 17:26:50 -0700193 fclose(fp);
194 return 0;
195 }
196 }
197 }
Christopher Ferris7a3681e2017-04-24 17:48:32 -0700198 async_safe_fatal("Stack not found in /proc/self/maps");
Elliott Hughes57b7a612014-08-25 17:26:50 -0700199}
200
Elliott Hughesc3f11402013-10-30 14:40:09 -0700201int pthread_attr_getstack(const pthread_attr_t* attr, void** stack_base, size_t* stack_size) {
Elliott Hughes3e898472013-02-12 16:40:24 +0000202 *stack_base = attr->stack_base;
203 *stack_size = attr->stack_size;
204 return 0;
205}
206
207int pthread_attr_setguardsize(pthread_attr_t* attr, size_t guard_size) {
Elliott Hughes3e898472013-02-12 16:40:24 +0000208 attr->guard_size = guard_size;
209 return 0;
210}
211
Elliott Hughesc3f11402013-10-30 14:40:09 -0700212int pthread_attr_getguardsize(const pthread_attr_t* attr, size_t* guard_size) {
Elliott Hughes3e898472013-02-12 16:40:24 +0000213 *guard_size = attr->guard_size;
214 return 0;
215}
216
Elliott Hughes57b7a612014-08-25 17:26:50 -0700217int pthread_getattr_np(pthread_t t, pthread_attr_t* attr) {
Yabin Cui9d0c7932015-03-06 13:48:58 -0800218 pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(t);
219 *attr = thread->attr;
Yabin Cui58cf31b2015-03-06 17:23:53 -0800220 // We prefer reading join_state here to setting thread->attr.flags in pthread_detach.
221 // Because data race exists in the latter case.
222 if (atomic_load(&thread->join_state) == THREAD_DETACHED) {
223 attr->flags |= PTHREAD_ATTR_FLAG_DETACHED;
224 }
Yabin Cui9d0c7932015-03-06 13:48:58 -0800225 // The main thread's stack information is not stored in thread->attr, and we need to
226 // collect that at runtime.
227 if (thread->tid == getpid()) {
228 return __pthread_attr_getstack_main_thread(&attr->stack_base, &attr->stack_size);
229 }
Elliott Hughes3e898472013-02-12 16:40:24 +0000230 return 0;
231}
232
Elliott Hughesc3f11402013-10-30 14:40:09 -0700233int pthread_attr_setscope(pthread_attr_t*, int scope) {
Elliott Hughes3e898472013-02-12 16:40:24 +0000234 if (scope == PTHREAD_SCOPE_SYSTEM) {
235 return 0;
236 }
237 if (scope == PTHREAD_SCOPE_PROCESS) {
238 return ENOTSUP;
239 }
240 return EINVAL;
241}
242
Elliott Hughesc3f11402013-10-30 14:40:09 -0700243int pthread_attr_getscope(const pthread_attr_t*, int* scope) {
244 *scope = PTHREAD_SCOPE_SYSTEM;
245 return 0;
Elliott Hughes3e898472013-02-12 16:40:24 +0000246}