int attribute_hidden __old_pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) { /* We have to check against the maximum allowed stack size. This is no problem if the manager is already started and we determined it. If this hasn't happened, we have to find the limit outself. */ if (__pthread_max_stacksize == 0) __pthread_init_max_stacksize (); if (stacksize > __pthread_max_stacksize) return EINVAL; /* We don't accept value smaller than old PTHREAD_STACK_MIN. */ if (stacksize < 16384) return EINVAL; attr->__stacksize = stacksize; return 0; }
int __pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) { #ifdef FLOATING_STACKS /* We have to check against the maximum allowed stack size. This is no problem if the manager is already started and we determined it. If this hasn't happened, we have to find the limit outself. */ if (__pthread_max_stacksize == 0) __pthread_init_max_stacksize (); if (stacksize > __pthread_max_stacksize) return EINVAL; #else /* We have a fixed size limit. */ if (stacksize > STACK_SIZE) return EINVAL; #endif /* We don't accept value smaller than PTHREAD_STACK_MIN. */ if (stacksize < PTHREAD_STACK_MIN) return EINVAL; attr->__stacksize = stacksize; return 0; }
int __pthread_initialize_manager(void) { int manager_pipe[2]; int pid; struct pthread_request request; #ifndef HAVE_Z_NODELETE if (__builtin_expect (&__dso_handle != NULL, 1)) __cxa_atexit ((void (*) (void *)) pthread_atexit_retcode, NULL, __dso_handle); #endif if (__pthread_max_stacksize == 0) __pthread_init_max_stacksize (); /* If basic initialization not done yet (e.g. we're called from a constructor run before our constructor), do it now */ if (__pthread_initial_thread_bos == NULL) pthread_initialize(); /* Setup stack for thread manager */ __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE); if (__pthread_manager_thread_bos == NULL) return -1; __pthread_manager_thread_tos = __pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE; /* Setup pipe to communicate with thread manager */ if (__libc_pipe(manager_pipe) == -1) { free(__pthread_manager_thread_bos); return -1; } /* Start the thread manager */ pid = 0; if (__builtin_expect (__pthread_initial_thread.p_report_events, 0)) { /* It's a bit more complicated. We have to report the creation of the manager thread. */ int idx = __td_eventword (TD_CREATE); uint32_t mask = __td_eventmask (TD_CREATE); if ((mask & (__pthread_threads_events.event_bits[idx] | __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx])) != 0) { __pthread_lock(__pthread_manager_thread.p_lock, NULL); #ifdef NEED_SEPARATE_REGISTER_STACK pid = __clone2(__pthread_manager_event, (void **) __pthread_manager_thread_bos, THREAD_MANAGER_STACK_SIZE, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, (void *)(long)manager_pipe[0]); #elif _STACK_GROWS_UP pid = __clone(__pthread_manager_event, (void **) __pthread_manager_thread_bos, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, (void *)(long)manager_pipe[0]); #else pid = __clone(__pthread_manager_event, (void **) __pthread_manager_thread_tos, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, (void *)(long)manager_pipe[0]); #endif if (pid != -1) { /* Now fill in the information about the new thread in the newly created thread's data structure. We cannot let the new thread do this since we don't know whether it was already scheduled when we send the event. */ __pthread_manager_thread.p_eventbuf.eventdata = &__pthread_manager_thread; __pthread_manager_thread.p_eventbuf.eventnum = TD_CREATE; __pthread_last_event = &__pthread_manager_thread; __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1; __pthread_manager_thread.p_pid = pid; /* Now call the function which signals the event. */ __linuxthreads_create_event (); } /* Now restart the thread. */ __pthread_unlock(__pthread_manager_thread.p_lock); } } if (__builtin_expect (pid, 0) == 0) { #ifdef NEED_SEPARATE_REGISTER_STACK pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_bos, THREAD_MANAGER_STACK_SIZE, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, (void *)(long)manager_pipe[0]); #elif _STACK_GROWS_UP pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_bos, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, (void *)(long)manager_pipe[0]); #else pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, (void *)(long)manager_pipe[0]); #endif } if (__builtin_expect (pid, 0) == -1) { free(__pthread_manager_thread_bos); __libc_close(manager_pipe[0]); __libc_close(manager_pipe[1]); return -1; } __pthread_manager_request = manager_pipe[1]; /* writing end */ __pthread_manager_reader = manager_pipe[0]; /* reading end */ __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1; __pthread_manager_thread.p_pid = pid; /* Make gdb aware of new thread manager */ if (__builtin_expect (__pthread_threads_debug, 0) && __pthread_sig_debug > 0) { raise(__pthread_sig_debug); /* We suspend ourself and gdb will wake us up when it is ready to handle us. */ __pthread_wait_for_restart_signal(thread_self()); } /* Synchronize debugging of the thread manager */ request.req_kind = REQ_DEBUG; TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request, (char *) &request, sizeof(request))); return 0; }
static void pthread_initialize(void) { struct sigaction sa; sigset_t mask; /* If already done (e.g. by a constructor called earlier!), bail out */ if (__pthread_initial_thread_bos != NULL) return; #ifdef TEST_FOR_COMPARE_AND_SWAP /* Test if compare-and-swap is available */ __pthread_has_cas = compare_and_swap_is_available(); #endif #ifdef FLOATING_STACKS /* We don't need to know the bottom of the stack. Give the pointer some value to signal that initialization happened. */ __pthread_initial_thread_bos = (void *) -1l; #else /* Determine stack size limits . */ __pthread_init_max_stacksize (); # ifdef _STACK_GROWS_UP /* The initial thread already has all the stack it needs */ __pthread_initial_thread_bos = (char *) ((long)CURRENT_STACK_FRAME &~ (STACK_SIZE - 1)); # else /* For the initial stack, reserve at least STACK_SIZE bytes of stack below the current stack address, and align that on a STACK_SIZE boundary. */ __pthread_initial_thread_bos = (char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1)); # endif #endif /* Update the descriptor for the initial thread. */ __pthread_initial_thread.p_pid = __getpid(); /* Likewise for the resolver state _res. */ __pthread_initial_thread.p_resp = &_res; #ifdef __SIGRTMIN /* Initialize real-time signals. */ init_rtsigs (); #endif /* Setup signal handlers for the initial thread. Since signal handlers are shared between threads, these settings will be inherited by all other threads. */ sa.sa_handler = pthread_handle_sigrestart; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; __libc_sigaction(__pthread_sig_restart, &sa, NULL); sa.sa_handler = pthread_handle_sigcancel; // sa.sa_flags = 0; __libc_sigaction(__pthread_sig_cancel, &sa, NULL); if (__pthread_sig_debug > 0) { sa.sa_handler = pthread_handle_sigdebug; sigemptyset(&sa.sa_mask); // sa.sa_flags = 0; __libc_sigaction(__pthread_sig_debug, &sa, NULL); } /* Initially, block __pthread_sig_restart. Will be unblocked on demand. */ sigemptyset(&mask); sigaddset(&mask, __pthread_sig_restart); sigprocmask(SIG_BLOCK, &mask, NULL); /* Register an exit function to kill all other threads. */ /* Do it early so that user-registered atexit functions are called before pthread_*exit_process. */ #ifndef HAVE_Z_NODELETE if (__builtin_expect (&__dso_handle != NULL, 1)) __cxa_atexit ((void (*) (void *)) pthread_atexit_process, NULL, __dso_handle); else #endif on_exit (pthread_onexit_process, NULL); /* How many processors. */ __pthread_smp_kernel = is_smp_system (); }