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>
349afb2f2106a5d659854c175c574c1c31e0e205a2Elliott Hughes#include <unistd.h>
3557b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes
3657b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes#include "private/bionic_string_utils.h"
3757b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes#include "private/ErrnoRestorer.h"
3857b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes#include "private/libc_logging.h"
393e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes#include "pthread_internal.h"
403e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes
413e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughesint pthread_attr_init(pthread_attr_t* attr) {
426d339182070b035ca94f19bc37c94f4d9813c374Elliott Hughes  attr->flags = 0;
436d339182070b035ca94f19bc37c94f4d9813c374Elliott Hughes  attr->stack_base = NULL;
4450af69e8f326b2762a44d5fea2b118e7616e5d20Brian Carlstrom  attr->stack_size = PTHREAD_STACK_SIZE_DEFAULT;
456d339182070b035ca94f19bc37c94f4d9813c374Elliott Hughes  attr->guard_size = PAGE_SIZE;
466d339182070b035ca94f19bc37c94f4d9813c374Elliott Hughes  attr->sched_policy = SCHED_NORMAL;
476d339182070b035ca94f19bc37c94f4d9813c374Elliott Hughes  attr->sched_priority = 0;
483e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  return 0;
493e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes}
503e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes
513e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughesint pthread_attr_destroy(pthread_attr_t* attr) {
523e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  memset(attr, 0x42, sizeof(pthread_attr_t));
533e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  return 0;
543e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes}
553e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes
563e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughesint pthread_attr_setdetachstate(pthread_attr_t* attr, int state) {
573e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  if (state == PTHREAD_CREATE_DETACHED) {
583e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes    attr->flags |= PTHREAD_ATTR_FLAG_DETACHED;
593e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  } else if (state == PTHREAD_CREATE_JOINABLE) {
603e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes    attr->flags &= ~PTHREAD_ATTR_FLAG_DETACHED;
613e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  } else {
623e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes    return EINVAL;
633e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  }
643e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  return 0;
653e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes}
663e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes
67c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_attr_getdetachstate(const pthread_attr_t* attr, int* state) {
683e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  *state = (attr->flags & PTHREAD_ATTR_FLAG_DETACHED) ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE;
693e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  return 0;
703e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes}
713e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes
723e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughesint pthread_attr_setschedpolicy(pthread_attr_t* attr, int policy) {
733e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  attr->sched_policy = policy;
743e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  return 0;
753e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes}
763e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes
77c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_attr_getschedpolicy(const pthread_attr_t* attr, int* policy) {
783e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  *policy = attr->sched_policy;
793e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  return 0;
803e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes}
813e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes
82c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_attr_setschedparam(pthread_attr_t* attr, const sched_param* param) {
833e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  attr->sched_priority = param->sched_priority;
843e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  return 0;
853e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes}
863e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes
87c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_attr_getschedparam(const pthread_attr_t* attr, sched_param* param) {
883e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  param->sched_priority = attr->sched_priority;
893e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  return 0;
903e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes}
913e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes
923e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughesint pthread_attr_setstacksize(pthread_attr_t* attr, size_t stack_size) {
93b95cf0d23a1db3b7c37bd98b0c86196796c9b029Elliott Hughes  if (stack_size < PTHREAD_STACK_MIN) {
943e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes    return EINVAL;
953e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  }
963e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  attr->stack_size = stack_size;
973e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  return 0;
983e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes}
993e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes
100c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_attr_getstacksize(const pthread_attr_t* attr, size_t* stack_size) {
10157b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes  void* unused;
10257b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes  return pthread_attr_getstack(attr, &unused, stack_size);
1033e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes}
1043e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes
1053e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughesint pthread_attr_setstack(pthread_attr_t* attr, void* stack_base, size_t stack_size) {
1063e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  if ((stack_size & (PAGE_SIZE - 1) || stack_size < PTHREAD_STACK_MIN)) {
1073e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes    return EINVAL;
1083e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  }
109405f8553cf19c583158d59ab44a5d668eade360dElliott Hughes  if (reinterpret_cast<uintptr_t>(stack_base) & (PAGE_SIZE - 1)) {
1103e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes    return EINVAL;
1113e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  }
1123e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  attr->stack_base = stack_base;
1133e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  attr->stack_size = stack_size;
1143e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  return 0;
1153e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes}
1163e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes
117569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzanstatic uintptr_t __get_main_stack_startstack() {
118569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  FILE* fp = fopen("/proc/self/stat", "re");
119569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  if (fp == nullptr) {
120569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan    __libc_fatal("couldn't open /proc/self/stat: %s", strerror(errno));
121569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  }
122569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan
123569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  char line[BUFSIZ];
124569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  if (fgets(line, sizeof(line), fp) == nullptr) {
125569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan    __libc_fatal("couldn't read /proc/self/stat: %s", strerror(errno));
126569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  }
127569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan
128569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  fclose(fp);
129569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan
130569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  // See man 5 proc. There's no reason comm can't contain ' ' or ')',
131569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  // so we search backwards for the end of it. We're looking for this field:
132569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  //
133569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  //  startstack %lu (28) The address of the start (i.e., bottom) of the stack.
134569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  uintptr_t startstack = 0;
135569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  const char* end_of_comm = strrchr(line, ')');
136569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  if (sscanf(end_of_comm + 1, " %*c "
137569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan             "%*d %*d %*d %*d %*d "
138569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan             "%*u %*u %*u %*u %*u %*u %*u "
139569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan             "%*d %*d %*d %*d %*d %*d "
140569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan             "%*u %*u %*d %*u %*u %*u %" SCNuPTR, &startstack) != 1) {
141569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan    __libc_fatal("couldn't parse /proc/self/stat");
142569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  }
143569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan
144569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  return startstack;
145569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan}
146569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan
14757b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughesstatic int __pthread_attr_getstack_main_thread(void** stack_base, size_t* stack_size) {
14857b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes  ErrnoRestorer errno_restorer;
14957b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes
1509e4ffa7032eaab308876b8e3da86b05c3c613878Elliott Hughes  rlimit stack_limit;
1519e4ffa7032eaab308876b8e3da86b05c3c613878Elliott Hughes  if (getrlimit(RLIMIT_STACK, &stack_limit) == -1) {
1529e4ffa7032eaab308876b8e3da86b05c3c613878Elliott Hughes    return errno;
1539e4ffa7032eaab308876b8e3da86b05c3c613878Elliott Hughes  }
1549e4ffa7032eaab308876b8e3da86b05c3c613878Elliott Hughes
1559e4ffa7032eaab308876b8e3da86b05c3c613878Elliott Hughes  // If the current RLIMIT_STACK is RLIM_INFINITY, only admit to an 8MiB stack for sanity's sake.
1569e4ffa7032eaab308876b8e3da86b05c3c613878Elliott Hughes  if (stack_limit.rlim_cur == RLIM_INFINITY) {
1579e4ffa7032eaab308876b8e3da86b05c3c613878Elliott Hughes    stack_limit.rlim_cur = 8 * 1024 * 1024;
1589e4ffa7032eaab308876b8e3da86b05c3c613878Elliott Hughes  }
1599e4ffa7032eaab308876b8e3da86b05c3c613878Elliott Hughes
160569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  // Ask the kernel where our main thread's stack started.
161569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  uintptr_t startstack = __get_main_stack_startstack();
162569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan
163569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  // Hunt for the region that contains that address.
164569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  FILE* fp = fopen("/proc/self/maps", "re");
165569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  if (fp == nullptr) {
166569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan    __libc_fatal("couldn't open /proc/self/maps");
16757b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes  }
16857b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes  char line[BUFSIZ];
16957b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes  while (fgets(line, sizeof(line), fp) != NULL) {
170569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan    uintptr_t lo, hi;
171569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan    if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR, &lo, &hi) == 2) {
172569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan      if (lo <= startstack && startstack <= hi) {
1739e4ffa7032eaab308876b8e3da86b05c3c613878Elliott Hughes        *stack_size = stack_limit.rlim_cur;
1749e4ffa7032eaab308876b8e3da86b05c3c613878Elliott Hughes        *stack_base = reinterpret_cast<void*>(hi - *stack_size);
17557b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes        fclose(fp);
17657b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes        return 0;
17757b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes      }
17857b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes    }
17957b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes  }
180569333293aeefbe792826cd59140dc23704018c4Mor-sarid, Nitzan  __libc_fatal("Stack not found in /proc/self/maps");
18157b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes}
18257b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes
183c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_attr_getstack(const pthread_attr_t* attr, void** stack_base, size_t* stack_size) {
1843e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  *stack_base = attr->stack_base;
1853e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  *stack_size = attr->stack_size;
1863e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  return 0;
1873e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes}
1883e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes
1893e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughesint pthread_attr_setguardsize(pthread_attr_t* attr, size_t guard_size) {
1903e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  attr->guard_size = guard_size;
1913e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  return 0;
1923e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes}
1933e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes
194c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_attr_getguardsize(const pthread_attr_t* attr, size_t* guard_size) {
1953e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  *guard_size = attr->guard_size;
1963e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  return 0;
1973e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes}
1983e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes
19957b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughesint pthread_getattr_np(pthread_t t, pthread_attr_t* attr) {
2009d0c79304d2413028aa5c213f7a567f00feccde5Yabin Cui  pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(t);
2019d0c79304d2413028aa5c213f7a567f00feccde5Yabin Cui  *attr = thread->attr;
20258cf31b50699ed9f523de38c8e943f3bbd1ced9eYabin Cui  // We prefer reading join_state here to setting thread->attr.flags in pthread_detach.
20358cf31b50699ed9f523de38c8e943f3bbd1ced9eYabin Cui  // Because data race exists in the latter case.
20458cf31b50699ed9f523de38c8e943f3bbd1ced9eYabin Cui  if (atomic_load(&thread->join_state) == THREAD_DETACHED) {
20558cf31b50699ed9f523de38c8e943f3bbd1ced9eYabin Cui    attr->flags |= PTHREAD_ATTR_FLAG_DETACHED;
20658cf31b50699ed9f523de38c8e943f3bbd1ced9eYabin Cui  }
2079d0c79304d2413028aa5c213f7a567f00feccde5Yabin Cui  // The main thread's stack information is not stored in thread->attr, and we need to
2089d0c79304d2413028aa5c213f7a567f00feccde5Yabin Cui  // collect that at runtime.
2099d0c79304d2413028aa5c213f7a567f00feccde5Yabin Cui  if (thread->tid == getpid()) {
2109d0c79304d2413028aa5c213f7a567f00feccde5Yabin Cui    return __pthread_attr_getstack_main_thread(&attr->stack_base, &attr->stack_size);
2119d0c79304d2413028aa5c213f7a567f00feccde5Yabin Cui  }
2123e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  return 0;
2133e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes}
2143e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes
215c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_attr_setscope(pthread_attr_t*, int scope) {
2163e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  if (scope == PTHREAD_SCOPE_SYSTEM) {
2173e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes    return 0;
2183e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  }
2193e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  if (scope == PTHREAD_SCOPE_PROCESS) {
2203e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes    return ENOTSUP;
2213e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  }
2223e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes  return EINVAL;
2233e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes}
2243e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes
225c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_attr_getscope(const pthread_attr_t*, int* scope) {
226c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes  *scope = PTHREAD_SCOPE_SYSTEM;
227c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes  return 0;
2283e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes}
229