1. pthread创建过程
============================================================
Goals of NPTL:
. POSIX compiliance
. effective use of SMP
. low startup cost
. low link-in cost
. binary compatibility
. hardware scalability
. software scalability
. machine arch support
. NUMA support
. integration with C++
pthread 数据结构:
struct pthread { (nptl/descr.h)
tcbhead_t header;
/* This descriptor's link on the `stack_used' or `__stack_user' list. */
list_t list;
/* Thread ID - which is also a 'is this thread descriptor (and
therefore stack) used' flag. */
pid_t tid;
/* Process ID - thread group ID in kernel speak. */
pid_t pid;
/* List of robust mutexes the thread is holding. */
void *robust_prev;
struct robust_list_head robust_head;
/* List of cleanup buffers. */ 单向链表, 用于cleanup_push保存注册函数
struct _pthread_cleanup_buffer *cleanup;
/* Unwind information. */ 单向链表, 用于支持pthread_cancel
struct pthread_unwind_buf *cleanup_jmp_buf;
/* Flags determining processing of cancellation. */
int cancelhandling;
/* Flags. Including those copied from the thread attribute. */
int flags;
/* We allocate one block of references here. This should be enough
to avoid allocating any memory dynamically for most applications. */
struct pthread_key_data
{
/* Sequence number. We use uintptr_t to not require padding on
32- and 64-bit machines. On 64-bit machines it helps to avoid
wrapping, too. */
uintptr_t seq;
/* Data pointer. */
void *data;
} specific_1stblock[PTHREAD_KEY_2NDLEVEL_SIZE];
/* Two-level array for the thread-specific data. */
struct pthread_key_data *specific[PTHREAD_KEY_1STLEVEL_SIZE];
/* Flag which is set when specific data is set. */
bool specific_used;
/* True if events must be reported. */
bool report_events;
/* True if the user provided the stack. */
bool user_stack;
/* True if thread must stop at startup time. */
bool stopped_start;
/* The parent's cancel handling at the time of the pthread_create
call. This might be needed to undo the effects of a cancellation. */
int parent_cancelhandling;
/* Lock to synchronize access to the descriptor. */
int lock;
/* Lock for synchronizing setxid calls. */
int setxid_futex;
/* If the thread waits to join another one the ID of the latter is
stored here.
In case a thread is detached this field contains a pointer of the
TCB if the thread itself. This is something which cannot happen
in normal operation. */
struct pthread *joinid;
/* The result of the thread function. */
void *result;
/* Scheduling parameters for the new thread. */
struct sched_param schedparam;
int schedpolicy;
/* Start position of the code to be executed and the argument passed
to the function. */
void *(*start_routine) (void *);
void *arg;
/* Debug state. */
td_eventbuf_t eventbuf;
/* Next descriptor with a pending event. */
struct pthread *nextevent;
/* If nonzero pointer to area allocated for the stack and its
size. */
void *stackblock;
size_t stackblock_size;
/* Size of the included guard area. */
size_t guardsize;
/* This is what the user specified and what we will report. */
size_t reported_guardsize;
/* Thread Priority Protection data. */
struct priority_protection_data *tpp;
/* Resolver state. */
struct __res_state res;
char end_padding[];
};
============================================================
入口函数:
int pthread_create (pthread_t *thread,
pthread_attr_t *attr,
void *(*start_routine)(void *),
void *arg) (nptl/pthread_create.c)
1. 首先为新thread分配 pthread *pt,
ALLOCATE_STACK (iattr, &pd),
通过mmap为新thread分配stack,缺省大小可用ulimit查看,
将pthread结构放在stack底部,sp指针指于stack顶部
pd->stackblock =
pd->stackblock_size =
2. 初始化pd
pd->start_routine =
pd->arg =
pd->flags =
pd->joinid = iattr->flags & ATTR_FLAG_DETACHSTATE ? pd : NULL
3. 根据iattr,设置pd->schedpolicy, pd->schedparam等调度相关参数
4. 调用create_thread创建线程,create_thread调用do_clone创建线程,
入口函数为start_thread,
start_thread中
a. 初始化 pd->robust_head
b. 添加对sig-cancel的处理,用于完成pthread_cancel
c. setjmp,保存jmpbuf于 pd->cleanup_jmp_buf中
d. 调用pd->start_routine,并将其返回值赋予pd->result
e. 在pd->start_routine退出后,start_routine负责清理tls等资源
int pthread_exit (void *value_ptr) (nptl/pthread_exit.c)
*value_ptr = THREAD_SELF->result
__do_cancel()
1. 设置thread->cancelhandling 为 exiting_bit
2. __pthread_unwind(self->cleanup_jmp_buf)
循环调用pd->cleanup所有注册的clearnup函数
longjmp到 pd->cleanup_jmp_buf
abort()
阅读(1026) | 评论(0) | 转发(0) |