- int pthread_create(pthread_t
*restrict thread,
-
const pthread_attr_t *restrict attr,
-
void *(*start_routine)(void*), void *restrict arg);
以NULL attr, static linked为例子
1. 使用default_attr;
2. 分配线程栈,struct pthread结构放在栈底(添加或者删除元素的一端叫栈顶,另一端叫栈底)
pthread代表新的线程, pthread结构上面是TLS(thread local storage)空间,它的内容为程序中
可执行文件中的(libc初始化时会查出来在哪)副本, 这样每个线程都有一份
_______________
|struct pthread|
| TLS |
STACK top
3. pd->start_routine = start_routine;
pd->arg = arg;
4. 调用
clone函
数, 建立新线程,它的起始函数为start_thread, 该函数的参数为刚刚分配的pthread结构
! 用户传的start_routine在pthread中有
给clone传递的tls参数和初始化的时候用set_thread_area一样,除了base_addr指向自身的
TLS之外
- /* The "thread register" gets initialized from a segment descriptor.
-
Initialize such a descriptor first. */
-
#define PREPARE_CREATE \
-
union user_desc_init desc; \
-
\
-
/* Describe the thread-local storage segment. */ \
-
\
-
/* The 'entry_number' field. The first three bits of the segment \
-
register value select the GDT, ignore them. We get the index \
-
from the value of the %gs register in the current thread. */ \
-
desc.vals[0] = TLS_GET_GS () >> 3; \
-
/* The 'base_addr' field. Pointer to the TCB. */ \
-
desc.vals[1] = (unsigned long int) pd; \
-
/* The 'limit' field. We use 4GB which is 0xfffff pages. */ \
-
desc.vals[2] = 0xfffff; \
-
/* Collapsed value of the bitfield: \
-
.seg_32bit = 1 \
-
.contents = 0 \
-
.read_exec_only = 0 \
-
.limit_in_pages = 1 \
-
.seg_not_present = 0 \
-
.useable = 1 */ \
-
desc.vals[3] = 0x51
5. start_thread 调用 pd->start_routine,
线程的起始函数pd->start_routine的被调用和整个程序
的main函数被调用的方式类似
- static int
-
start_thread (void *arg)
-
{
-
struct pthread *pd = (struct pthread *) arg;
-
-
struct pthread_unwind_buf
unwind_buf;
-
-
int not_first_call;
-
not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);
- 会两次到这里来,一次是开始,一次是 _被_
结束或者主动调用pthread_exit
- 否则只有一次,start_routine可能直接返回
-
if (!
not_first_call)
-
{
-
/* Run the code the user
provided. */
- pd->start_routine
(pd->arg));
-
-
}
-
-
/* Run the destructor for the
thread-local data. */
-
__nptl_deallocate_tsd ();
-
-
-
/* If this is the last thread
we terminate the process now. We
-
do not notify the debugger, it might just irritate it if there
-
is no thread left. */
- 最后一个线程
-
if (__builtin_expect (atomic_decrement_and_test (&__nptl_nthreads), 0))
-
/* This was the last thread.
*/
-
exit (0);
-
-
/* We cannot call '_exit' here.
'_exit' will terminate the process.
-
-
The 'exit' implementation in the kernel will signal when the
-
process is really dead since 'clone' got passed the CLONE_CLEARTID
-
flag. The 'tid' field in the TCB will be set to zero.
-
-
The exit code is zero since in case all threads exit by calling
-
'pthread_exit' the exit status must be 0 (zero). */
-
__exit_thread_inline (0);
-
-
/* NOTREACHED */
-
return 0;
-
}
阅读(2401) | 评论(0) | 转发(0) |