Chinaunix首页 | 论坛 | 博客
  • 博客访问: 263603
  • 博文数量: 52
  • 博客积分: 1379
  • 博客等级: 大尉
  • 技术积分: 525
  • 用 户 组: 普通用户
  • 注册时间: 2006-06-18 17:34
文章分类

全部博文(52)

文章存档

2011年(48)

2010年(4)

分类: LINUX

2011-03-14 11:54:16

pthread_join - wait for thread termination
(pthread_tryjoin_np pthread_timedjoin_np)非阻塞版本和超时版本
超时通过futex控制

  • 检查是否detached
/* Is the thread joinable?.  */
  if (IS_DETACHED (pd))
    /* We cannot wait for the thread.  */
    return EINVAL;

每个线程都有一个joinid, 表示谁正在join该线程,如果pd->joinid == pd自身, 就是detached了
detached的线程在退出时会自己释放资源

pthread_detach 函数会设置该值
另外,如果设置了DETACHSTATE标志,那么pthread_create返回之前就会设置该值
pd->joinid = iattr->flags & ATTR_FLAG_DETACHSTATE ? pd : NULL;
  • 设置自身可以被异步取消
struct pthread *self = THREAD_SELF;
  int result = 0;

  /* During the wait we change to asynchronous cancellation.  If we
     are canceled the thread we are waiting for must be marked as
     un-wait-ed for again.  */
  pthread_cleanup_push (cleanup, &pd->joinid);

  /* Switch to asynchronous cancellation.  */
  int oldtype = CANCEL_ASYNC ();

默认情况,线程是同步取消,  这意味这只有在某个遇到某个取消点才允许被取消, 换句话说
如果线程已经阻塞了,或者while(1); 线程是不会退出的

如果线程a试图join线程b,那么a被设置为异步取消,这样,只要有人试图pthread_cancel(a)
a将会退出
cleanup 函数在被取消的情况下会调用,其参数为&pd->joinid

它再次允许别的线程取消
  1. static void
  2. cleanup (void *arg)
  3. {//
  4.   /* If we already changed the waiter ID, reset it. The call cannot
  5.      fail for any reason but the thread not having done that yet so
  6.      there is no reason for a loop. */
  7.   (void) atomic_compare_and_exchange_bool_acq ((struct pthread **) arg, NULL,
  8.                      THREAD_SELF);
  9. }


  • 原子的设置joinid为self,不允许别的线程再join该线程

/* Wait for the thread to finish.  If it is already locked something
     is wrong.  There can only be one waiter.  */
if (atomic_compare_and_exchange_bool_acq (&pd->joinid, self, NULL))
    return EINVAL;

即如果joinid == NULL, 则设置其值为self, 如果 joinid != NULL则不做改动,标示它被别人join了

  • 等待线程退出

  1. /* Wait for the child. */
  2.     lll_wait_tid (pd->tid);
该函数使用futex系统调用,直到pd->tid等于0
(内核会在thread退出的时候唤醒等待线程,  因为clone的时候使用了CLONE_CHILD_CLEARTID)


  • 修改取消模式
  /* Remove the handler.  */
  pthread_cleanup_pop (0);
不执行cleanup函数

  • 释放内存并返回
      /* Store the return value if the caller is interested.  */
      if (thread_return != NULL)
    *thread_return = pd->result;


      /* Free the TCB.  */
      __free_tcb (pd);


阅读(3918) | 评论(0) | 转发(0) |
0

上一篇:errno

下一篇:pthread_once

给主人留下些什么吧!~~