前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >线程源码分析之join.c(基于linuxthreads2.0.1)

线程源码分析之join.c(基于linuxthreads2.0.1)

作者头像
theanarkh
发布2019-10-08 12:22:56
9560
发布2019-10-08 12:22:56
举报
文章被收录于专栏:原创分享原创分享

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

1 pthread_exit

代码语言:javascript
复制
// 线程退出
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

代码语言:javascript
复制
// 调用该函数的线程会等待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

代码语言:javascript
复制
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;
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程杂技 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档