android中库bionic线程函数pthread_create的具体执行流程
int pthread_create(pthread_t *thread_out, pthread_attr_t const * attr,
void *(*start_routine)(void *), void * arg)
{
......
// Create a mutex for the thread in TLS_SLOT_SELF to wait on once it starts so we can keep
// it from doing anything until after we notify the debugger about it
start_mutex = (pthread_mutex_t *) &tls[TLS_SLOT_SELF];
pthread_mutex_init(start_mutex, NULL); // 初始化thread启动锁
pthread_mutex_lock(start_mutex); // 获取thread的启动锁,clone返回
// 之后下面的__thread_entryh函数将因为调用pthread_mutex_lock(start_mutex);而被pending
// 直到pthread_create函数退出时调用下面第10行的pthread_mutex_unlock(start_mutex);解锁
// 函数,__thread_entryh函数才能获取启动锁,进而开始执行start_routine函数
// 所以我们可以看到函数pthread_create一旦返回,线程即开始自动执行[luther.gliethttp]
tls[TLS_SLOT_THREAD_ID] = thread;
tid = __pthread_clone((int(*)(void*))start_routine, tls,
CLONE_FILES | CLONE_FS | CLONE_VM | CLONE_SIGHAND
| CLONE_THREAD | CLONE_SYSVSEM | CLONE_DETACHED,
arg); // 调用__pthread_clone函数swi陷入内核让内核执行实际clone操作
......
// Let the thread do it's thing
pthread_mutex_unlock(start_mutex); // pthread_create函数执行完毕,
// 那么我们在这里释放启动锁,这样下面的__thread_entry将获取到启动锁而
// 正常启动pthread_create函数传入的参数处理函数start_routine[luther.gliethttp]
*thread_out = (pthread_t)thread;
return 0;
}
==> __pthread_clone该函数位于bionic/libc/arch-arm/bionic/clone.S
.text
.type __pthread_clone, #function
.global __pthread_clone
.align 4
__pthread_clone:
......
#if __ARM_EABI__
stmfd sp!, {r4, r7}
ldr r7, =__NR_clone
swi #0 swi软中断陷入内核,让内核执行clone操作
#else
swi #__NR_clone
#endif
......
b __thread_entry swi返回之后执行该函数
......
==> __thread_entry该函数位于bionic/libc/bionic/pthread.c
/*
* This trampoline is called from the assembly clone() function
*/
void __thread_entry(int (*func)(void*), void *arg, void **tls)
{
int retValue;
pthread_internal_t * thrInfo;
// Wait for our creating thread to release us. This lets it have time to
// notify gdb about this thread before it starts doing anything.
pthread_mutex_t * start_mutex = (pthread_mutex_t *)&tls[TLS_SLOT_SELF];
pthread_mutex_lock(start_mutex); // 直到pthread_create函数
// 退出时执行pthread_mutex_unlock(start_mutex);这里的启动锁才能正常获取到,进而该线程
// 开始继续执行下面的操作,完成正常启动工作[luther.gliethttp]
pthread_mutex_destroy(start_mutex);
thrInfo = (pthread_internal_t *) tls[TLS_SLOT_THREAD_ID];
__init_tls( tls, thrInfo );
pthread_exit( (void*)func(arg) );
}
阅读(5899) | 评论(1) | 转发(0) |