pthread_attr.cpp revision 57b7a6110e7e8b446fc23cce4765ff625ee0a105
13e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes/* 23e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * Copyright (C) 2008 The Android Open Source Project 33e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * All rights reserved. 43e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * 53e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * Redistribution and use in source and binary forms, with or without 63e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * modification, are permitted provided that the following conditions 73e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * are met: 83e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * * Redistributions of source code must retain the above copyright 93e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * notice, this list of conditions and the following disclaimer. 103e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * * Redistributions in binary form must reproduce the above copyright 113e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * notice, this list of conditions and the following disclaimer in 123e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * the documentation and/or other materials provided with the 133e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * distribution. 143e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * 153e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 163e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 173e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 183e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 193e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 203e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 213e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 223e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 233e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 243e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 253e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 263e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes * SUCH DAMAGE. 273e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes */ 283e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 293e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes#include <pthread.h> 303e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 3157b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes#include <inttypes.h> 3257b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes#include <stdio.h> 3357b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes#include <sys/resource.h> 3457b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes 3557b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes#include "private/bionic_string_utils.h" 3657b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes#include "private/ErrnoRestorer.h" 3757b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes#include "private/libc_logging.h" 383e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes#include "pthread_internal.h" 393e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 403e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughesint pthread_attr_init(pthread_attr_t* attr) { 416d339182070b035ca94f19bc37c94f4d9813c374Elliott Hughes attr->flags = 0; 426d339182070b035ca94f19bc37c94f4d9813c374Elliott Hughes attr->stack_base = NULL; 4350af69e8f326b2762a44d5fea2b118e7616e5d20Brian Carlstrom attr->stack_size = PTHREAD_STACK_SIZE_DEFAULT; 446d339182070b035ca94f19bc37c94f4d9813c374Elliott Hughes attr->guard_size = PAGE_SIZE; 456d339182070b035ca94f19bc37c94f4d9813c374Elliott Hughes attr->sched_policy = SCHED_NORMAL; 466d339182070b035ca94f19bc37c94f4d9813c374Elliott Hughes attr->sched_priority = 0; 473e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return 0; 483e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes} 493e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 503e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughesint pthread_attr_destroy(pthread_attr_t* attr) { 513e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes memset(attr, 0x42, sizeof(pthread_attr_t)); 523e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return 0; 533e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes} 543e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 553e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughesint pthread_attr_setdetachstate(pthread_attr_t* attr, int state) { 563e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes if (state == PTHREAD_CREATE_DETACHED) { 573e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes attr->flags |= PTHREAD_ATTR_FLAG_DETACHED; 583e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes } else if (state == PTHREAD_CREATE_JOINABLE) { 593e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes attr->flags &= ~PTHREAD_ATTR_FLAG_DETACHED; 603e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes } else { 613e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return EINVAL; 623e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes } 633e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return 0; 643e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes} 653e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 66c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_attr_getdetachstate(const pthread_attr_t* attr, int* state) { 673e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes *state = (attr->flags & PTHREAD_ATTR_FLAG_DETACHED) ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE; 683e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return 0; 693e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes} 703e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 713e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughesint pthread_attr_setschedpolicy(pthread_attr_t* attr, int policy) { 723e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes attr->sched_policy = policy; 733e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return 0; 743e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes} 753e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 76c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_attr_getschedpolicy(const pthread_attr_t* attr, int* policy) { 773e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes *policy = attr->sched_policy; 783e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return 0; 793e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes} 803e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 81c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_attr_setschedparam(pthread_attr_t* attr, const sched_param* param) { 823e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes attr->sched_priority = param->sched_priority; 833e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return 0; 843e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes} 853e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 86c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_attr_getschedparam(const pthread_attr_t* attr, sched_param* param) { 873e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes param->sched_priority = attr->sched_priority; 883e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return 0; 893e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes} 903e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 913e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughesint pthread_attr_setstacksize(pthread_attr_t* attr, size_t stack_size) { 92b95cf0d23a1db3b7c37bd98b0c86196796c9b029Elliott Hughes if (stack_size < PTHREAD_STACK_MIN) { 933e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return EINVAL; 943e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes } 953e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes attr->stack_size = stack_size; 963e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return 0; 973e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes} 983e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 99c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_attr_getstacksize(const pthread_attr_t* attr, size_t* stack_size) { 10057b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes void* unused; 10157b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes return pthread_attr_getstack(attr, &unused, stack_size); 1023e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes} 1033e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 1043e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughesint pthread_attr_setstack(pthread_attr_t* attr, void* stack_base, size_t stack_size) { 1053e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes if ((stack_size & (PAGE_SIZE - 1) || stack_size < PTHREAD_STACK_MIN)) { 1063e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return EINVAL; 1073e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes } 108405f8553cf19c583158d59ab44a5d668eade360dElliott Hughes if (reinterpret_cast<uintptr_t>(stack_base) & (PAGE_SIZE - 1)) { 1093e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return EINVAL; 1103e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes } 1113e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes attr->stack_base = stack_base; 1123e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes attr->stack_size = stack_size; 1133e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return 0; 1143e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes} 1153e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 11657b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughesstatic int __pthread_attr_getstack_main_thread(void** stack_base, size_t* stack_size) { 11757b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes ErrnoRestorer errno_restorer; 11857b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes 11957b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes // It doesn't matter which thread we are; we're just looking for "[stack]". 12057b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes FILE* fp = fopen("/proc/self/maps", "re"); 12157b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes if (fp == NULL) { 12257b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes return errno; 12357b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes } 12457b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes char line[BUFSIZ]; 12557b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes while (fgets(line, sizeof(line), fp) != NULL) { 12657b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes if (ends_with(line, " [stack]\n")) { 12757b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes uintptr_t lo, hi; 12857b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR, &lo, &hi) == 2) { 12957b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes *stack_base = reinterpret_cast<void*>(lo); 13057b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes *stack_size = hi - lo; 13157b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes 13257b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes // Does our current RLIMIT_STACK mean we won't actually get everything /proc/maps promises? 13357b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes rlimit stack_limit; 13457b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes if (getrlimit(RLIMIT_STACK, &stack_limit) != -1) { 13557b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes if (*stack_size > stack_limit.rlim_cur) { 13657b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes *stack_size = stack_limit.rlim_cur; 13757b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes } 13857b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes } 13957b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes 14057b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes fclose(fp); 14157b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes return 0; 14257b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes } 14357b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes } 14457b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes } 14557b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes __libc_fatal("No [stack] line found in /proc/self/maps!"); 14657b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes} 14757b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes 148c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_attr_getstack(const pthread_attr_t* attr, void** stack_base, size_t* stack_size) { 14957b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes if ((attr->flags & PTHREAD_ATTR_FLAG_MAIN_THREAD) != 0) { 15057b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes return __pthread_attr_getstack_main_thread(stack_base, stack_size); 15157b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes } 1523e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes *stack_base = attr->stack_base; 1533e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes *stack_size = attr->stack_size; 1543e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return 0; 1553e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes} 1563e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 1573e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughesint pthread_attr_setguardsize(pthread_attr_t* attr, size_t guard_size) { 1583e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes attr->guard_size = guard_size; 1593e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return 0; 1603e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes} 1613e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 162c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_attr_getguardsize(const pthread_attr_t* attr, size_t* guard_size) { 1633e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes *guard_size = attr->guard_size; 1643e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return 0; 1653e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes} 1663e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 16757b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughesint pthread_getattr_np(pthread_t t, pthread_attr_t* attr) { 16857b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes *attr = reinterpret_cast<pthread_internal_t*>(t)->attr; 1693e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return 0; 1703e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes} 1713e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 172c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_attr_setscope(pthread_attr_t*, int scope) { 1733e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes if (scope == PTHREAD_SCOPE_SYSTEM) { 1743e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return 0; 1753e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes } 1763e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes if (scope == PTHREAD_SCOPE_PROCESS) { 1773e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return ENOTSUP; 1783e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes } 1793e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes return EINVAL; 1803e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes} 1813e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 182c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_attr_getscope(const pthread_attr_t*, int* scope) { 183c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes *scope = PTHREAD_SCOPE_SYSTEM; 184c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes return 0; 1853e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes} 186