#include "namespace.h"
#include <sys/param.h>
#include <sys/signalvar.h>
#include <sys/ioctl.h>
#include <sys/sysctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/ttycom.h>
#include <sys/mman.h>
#include <stdio.h>
#include <fcntl.h>
#include <paths.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "un-namespace.h"
#include "libc_private.h"
#include "thr_private.h"
struct __pthread_attr_s _pthread_attr_default = {
.sched_policy = SCHED_OTHER,
.sched_inherit = 0,
.prio = THR_DEFAULT_PRIORITY,
.suspend = THR_CREATE_RUNNING,
.flags = PTHREAD_SCOPE_SYSTEM,
.stackaddr_attr = NULL,
.stacksize_attr = THR_STACK_DEFAULT,
.guardsize_attr = 0
};
struct __pthread_mutexattr_s _pthread_mutexattr_default = {
.m_type = PTHREAD_MUTEX_DEFAULT,
.m_protocol = PTHREAD_PRIO_NONE,
.m_ceiling = 0,
.m_flags = 0
};
struct __pthread_condattr_s _pthread_condattr_default = {
.c_pshared = PTHREAD_PROCESS_PRIVATE,
.c_clockid = CLOCK_REALTIME
};
STATIC_LIB_REQUIRE(_pthread_attr_init);
STATIC_LIB_REQUIRE(_pthread_barrier_init);
STATIC_LIB_REQUIRE(_pthread_barrierattr_init);
STATIC_LIB_REQUIRE(_pthread_cancel);
STATIC_LIB_REQUIRE(_pthread_cleanup_push);
STATIC_LIB_REQUIRE(_pthread_getconcurrency);
STATIC_LIB_REQUIRE(_pthread_setconcurrency);
STATIC_LIB_REQUIRE(_pthread_cond_init);
STATIC_LIB_REQUIRE(_pthread_condattr_init);
STATIC_LIB_REQUIRE(_pthread_create);
STATIC_LIB_REQUIRE(_pthread_detach);
STATIC_LIB_REQUIRE(_pthread_equal);
STATIC_LIB_REQUIRE(_pthread_exit);
STATIC_LIB_REQUIRE(_pthread_atfork);
STATIC_LIB_REQUIRE(_fork);
STATIC_LIB_REQUIRE(_pthread_getaffinity_np);
STATIC_LIB_REQUIRE(_pthread_getcpuclockid);
STATIC_LIB_REQUIRE(_pthread_getprio);
STATIC_LIB_REQUIRE(_pthread_getschedparam);
STATIC_LIB_REQUIRE(_pthread_getthreadid_np);
STATIC_LIB_REQUIRE(_pthread_get_name_np);
STATIC_LIB_REQUIRE(_pthread_getname_np);
STATIC_LIB_REQUIRE(_pthread_set_name_np);
STATIC_LIB_REQUIRE(_pthread_setname_np);
STATIC_LIB_REQUIRE(_pthread_init_early);
STATIC_LIB_REQUIRE(_pthread_join);
STATIC_LIB_REQUIRE(_pthread_kill);
STATIC_LIB_REQUIRE(_pthread_main_np);
STATIC_LIB_REQUIRE(_pthread_multi_np);
STATIC_LIB_REQUIRE(_pthread_mutex_init);
STATIC_LIB_REQUIRE(_pthread_mutexattr_getprioceiling);
STATIC_LIB_REQUIRE(_pthread_mutexattr_getprotocol);
STATIC_LIB_REQUIRE(_pthread_mutexattr_init);
STATIC_LIB_REQUIRE(_pthread_once);
STATIC_LIB_REQUIRE(_pthread_spin_init);
STATIC_LIB_REQUIRE(_pthread_resume_np);
STATIC_LIB_REQUIRE(_pthread_rwlock_init);
STATIC_LIB_REQUIRE(_pthread_rwlockattr_init);
STATIC_LIB_REQUIRE(_pthread_self);
STATIC_LIB_REQUIRE(_sem_init);
STATIC_LIB_REQUIRE(_pthread_setaffinity_np);
STATIC_LIB_REQUIRE(_pthread_setprio);
STATIC_LIB_REQUIRE(_pthread_setschedparam);
STATIC_LIB_REQUIRE(_sigwait);
STATIC_LIB_REQUIRE(_pthread_single_np);
STATIC_LIB_REQUIRE(_pthread_key_create);
STATIC_LIB_REQUIRE(_spinlock);
STATIC_LIB_REQUIRE(_pthread_suspend_np);
STATIC_LIB_REQUIRE(_pthread_switch_add_np);
STATIC_LIB_REQUIRE(_thread_state_running);
STATIC_LIB_REQUIRE(__wait4);
STATIC_LIB_REQUIRE(_pthread_yield);
char *_usrstack;
pthread_t _thr_initial;
static void *_thr_main_redzone;
pid_t _thr_pid;
size_t _thr_guard_default;
size_t _thr_stack_default = THR_STACK_DEFAULT;
size_t _thr_stack_initial = THR_STACK_INITIAL;
int _thr_page_size;
static void init_private(void);
static void _libpthread_uninit(void);
static void init_main_thread(pthread_t thread);
void _thread_init(void) __attribute__ ((constructor));
void
_thread_init(void)
{
_libpthread_init(NULL);
_libc_thr_init();
}
void _thread_uninit(void) __attribute__ ((destructor));
void
_thread_uninit(void)
{
_libpthread_uninit();
}
void _pthread_init_early(void);
void
_pthread_init_early(void)
{
_libpthread_init(NULL);
}
void
_libpthread_init(pthread_t curthread)
{
int fd, first = 0;
sigset_t sigset, oldset;
if ((_thr_initial != NULL) && (curthread == NULL))
return;
if ((_thr_pid = getpid()) == 1) {
if (setsid() == -1)
PANIC("Can't set session ID");
if (revoke(_PATH_CONSOLE) != 0)
PANIC("Can't revoke console");
if ((fd = __sys_open(_PATH_CONSOLE, O_RDWR)) < 0)
PANIC("Can't open console");
if (setlogin("root") == -1)
PANIC("Can't set login to root");
if (__sys_ioctl(fd, TIOCSCTTY, NULL) == -1)
PANIC("Can't set controlling terminal");
}
init_private();
if (curthread == NULL) {
first = 1;
curthread = _thr_alloc(NULL);
if (curthread == NULL)
PANIC("Can't allocate initial thread");
init_main_thread(curthread);
}
THR_LIST_ADD(curthread);
_thread_active_threads = 1;
tls_set_tcb(curthread->tcb);
if (first) {
SIGFILLSET(sigset);
__sys_sigprocmask(SIG_SETMASK, &sigset, &oldset);
_thr_signal_init();
_thr_initial = curthread;
SIGDELSET(oldset, SIGCANCEL);
__sys_sigprocmask(SIG_SETMASK, &oldset, NULL);
if (td_eventismember(&_thread_event_mask, TD_CREATE))
_thr_report_creation(curthread, curthread);
_thr_rtld_init();
_thr_malloc_init();
_thr_sem_init();
}
}
static void
_libpthread_uninit(void)
{
if (_thr_initial == NULL)
return;
if (_thr_main_redzone && _thr_main_redzone != MAP_FAILED) {
munmap(_thr_main_redzone, _thr_guard_default);
_thr_main_redzone = NULL;
}
_thr_stack_cleanup();
}
static void
init_main_thread(pthread_t thread)
{
thread->tid = _thr_get_tid();
thread->attr = _pthread_attr_default;
_thr_main_redzone = mmap(_usrstack - _thr_stack_initial -
_thr_guard_default, _thr_guard_default,
0, MAP_ANON | MAP_TRYFIXED, -1, 0);
if (_thr_main_redzone == MAP_FAILED) {
PANIC("Cannot allocate red zone for initial thread");
}
thread->attr.stackaddr_attr = _usrstack - _thr_stack_initial;
thread->attr.stacksize_attr = _thr_stack_initial;
thread->attr.guardsize_attr = _thr_guard_default;
thread->attr.flags |= THR_STACK_USER;
thread->magic = THR_MAGIC;
thread->cancelflags = PTHREAD_CANCEL_ENABLE | PTHREAD_CANCEL_DEFERRED;
thread->name = __malloc(16);
snprintf(thread->name, 16, "initial thread");
thread->base_priority = THR_DEFAULT_PRIORITY;
thread->active_priority = THR_DEFAULT_PRIORITY;
thread->inherited_priority = 0;
TAILQ_INIT(&thread->mutexq);
thread->state = PS_RUNNING;
thread->uniqueid = 0;
}
static int64_t
get_mainthread_size(void)
{
struct rlimit rlim;
if (getrlimit(RLIMIT_STACK, &rlim) == -1)
PANIC("Cannot get stack rlimit");
return rlim.rlim_cur;
}
static void
init_private(void)
{
static int init_once = 0;
size_t len;
int mib[2];
if (init_once == 0) {
mib[0] = CTL_KERN;
mib[1] = KERN_USRSTACK;
len = sizeof (_usrstack);
if (sysctl(mib, 2, &_usrstack, &len, NULL, 0) == -1)
PANIC("Cannot get kern.usrstack from sysctl");
_thr_stack_initial = get_mainthread_size();
_thr_page_size = getpagesize();
_thr_guard_default = _thr_page_size;
_pthread_attr_default.guardsize_attr = _thr_guard_default;
TAILQ_INIT(&_thr_atfork_list);
TAILQ_INIT(&_thr_atfork_kern_list);
init_once = 1;
}
_thr_umtx_init(&_mutex_static_lock);
_thr_umtx_init(&_cond_static_lock);
_thr_umtx_init(&_rwlock_static_lock);
_thr_umtx_init(&_keytable_lock);
_thr_umtx_init(&_thr_atfork_lock);
_thr_umtx_init(&_thr_event_lock);
_thr_spinlock_init();
_thr_list_init();
}
__strong_reference(_pthread_init_early, pthread_init_early);