基于linuxthreads2.0.1线程如何进行源码分析join.c

发布时间:2021-12-09 09:35:12 作者:柒染
来源:亿速云 阅读:142

基于linuxthreads2.0.1线程如何进行源码分析join.c,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

join.c文件一共有三个函数,下面我们一个个看一下。

1 pthread_exit

基于linuxthreads2.0.1线程如何进行源码分析join.c

   
     
 
    
    

// 线程退出
void pthread_exit(void * retval)
{
 // 获取当前线程的结构体
 pthread_t self = thread_self();
 pthread_t joining;
 struct pthread_request request;

 /* Reset the cancellation flag to avoid looping if the cleanup handlers
    contain cancellation points */
 // 设置成0,避免其他函数里判断是cancel状态,然后再调pthread_exit函数
 self->p_canceled = 0;
 /* Call cleanup functions and destroy the thread-specific data */
 // 执行clean节点的函数
 __pthread_perform_cleanup();
 // 遍历pthread_keys数组,销毁线程中的specifics数据
 __pthread_destroy_specifics();
 /* Store return value */
 // 加锁
 acquire(&self->p_spinlock);
 // 退出值,可以在join中返回给其他线程
 self->p_retval = retval;
 /* Say that we've terminated */
 // 已终止
 self->p_terminated = 1;
 /* See if someone is joining on us */
 // 判断有没有其他线程在等待该线程退出
 joining = self->p_joining;
 release(&self->p_spinlock);
 /* Restart joining thread if any */
 // 唤醒他
 if (joining != NULL) restart(joining);
 /* If this is the initial thread, block until all threads have terminated.
    If another thread calls exit, we'll be terminated from our signal
    handler. */
 // 如果是主线程退出,通知manage线程,如果是一般线程则直接执行exit退出
 if (self == __pthread_main_thread && __pthread_manager_request >= 0) {
   request.req_thread = self;
   request.req_kind = REQ_MAIN_THREAD_EXIT;
   // 写入管道
   __libc_write(__pthread_manager_request, (char *)&request, sizeof(request));
   // 挂起等待唤醒,全部子线程都退出后了才唤醒主线程,然后主线程也退出,见manager.c的__pthread_manager函数
   suspend(self);
 }
 /* Exit the process (but don't flush stdio streams, and don't run
    atexit functions). */
 // 线程退出,见操作系统实现
 _exit(0);
}              

2 pthread_join

基于linuxthreads2.0.1线程如何进行源码分析join.c

   
     
 
    
    

// 调用该函数的线程会等待th线程结束
int pthread_join(pthread_t th, void ** thread_return)
{
 volatile pthread_t self = thread_self();
 struct pthread_request request;
 // 不能等待自己结束,否则会死锁,即自己无法结束
 if (th == self) return EDEADLK;
 acquire(&th->p_spinlock);
 /* If detached or already joined, error */
 // th线程已经是detach状态,即不是joinable的,或者已经被jion过了
 if (th->p_detached || th->p_joining != NULL) {
   release(&th->p_spinlock);
   return EINVAL;
 }
 /* If not terminated yet, suspend ourselves. */
 // join的线程还在运行,则需要等待
 if (! th->p_terminated) {
   // 记录谁在join th
   th->p_joining = self;
   release(&th->p_spinlock);
   // 挂起等待唤醒,th退出的时候才会唤醒self线程,见pthread_exit的restart
   suspend_with_cancellation(self);
   acquire(&th->p_spinlock);
   /* This is a cancellation point */
   // 取消点
   if (self->p_canceled && self->p_cancelstate == PTHREAD_CANCEL_ENABLE) {
     th->p_joining = NULL;
     release(&th->p_spinlock);
     pthread_exit(PTHREAD_CANCELED);
   }
 }
 /* Get return value */
 // 线程已经结束,设置线程的返回值
 if (thread_return != NULL) *thread_return = th->p_retval;
 release(&th->p_spinlock);
 /* Send notification to thread manager */
 // 管道的写端,join的线程已经退出,通知manage线程回收退出线程的资源,见REQ_FREE的处理
 if (__pthread_manager_request >= 0) {
   // 发送th线程已经结束的通知给manager线程,self是发送者
   request.req_thread = self;
   request.req_kind = REQ_FREE;
   request.req_args.free.thread = th;
   // 写入管道
   __libc_write(__pthread_manager_request,
(char *) &request, sizeof(request));
 }
 return 0;
}

             

3 pthread_detach

基于linuxthreads2.0.1线程如何进行源码分析join.c

   
     
 
    
    

int pthread_detach(pthread_t th)
{
 int terminated;
 struct pthread_request request;

 acquire(&th->p_spinlock);
 /* If already detached, error */
 // detach过了
 if (th->p_detached) {
   release(&th->p_spinlock);
   return EINVAL;
 }
 /* If already joining, don't do anything. */
 // 有线程join了该线程,不能detach
 if (th->p_joining != NULL) {
   release(&th->p_spinlock);
   return 0;
 }
 /* Mark as detached */
 // 标记已经detach
 th->p_detached = 1;
 terminated = th->p_terminated;
 release(&th->p_spinlock);
 /* If already terminated, notify thread manager to reclaim resources */
 // 线程已经退出了,detach的时候,通知manager,__pthread_manager_request是管道写端
 if (terminated && __pthread_manager_request >= 0) {
   request.req_thread = thread_self();
   request.req_kind = REQ_FREE;
   request.req_args.free.thread = th;
   __libc_write(__pthread_manager_request,
(char *) &request, sizeof(request));
 }
 return 0;
}  

关于基于linuxthreads2.0.1线程如何进行源码分析join.c问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。

推荐阅读:
  1. 怎么进行ActionInvoker源码分析
  2. 如何进行ThreadLocal源码分析

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

linuxthreads

上一篇:php几千条数据如何插入数据库

下一篇:nodejs中的get/post请求方法是什么

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》