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

全部博文(52)

文章存档

2011年(48)

2010年(4)

分类: LINUX

2011-03-15 18:10:40

pthread_cancel(pthread_t pd);


用于取消一个函数,它通常需要被取消线程的配合

默认情况(延迟取消),它就是给pd设置取消标志, pd线程在很多时候会查看自己是否有取消请求
如果有就主动退出, 这些查看是否有取消的地方称为取消点

如果是异步取消(pthread_setcanceltype设置),那么 pthread_cancel同时还给发送信号通知对方
对方理解会结束自己

pthread_cancel (pd):

设置pd的请求标志
如果是异步模式,发送信号
pd收到信号后退出(线程如何退出参考 pthread_create )



取消点的本质就是修改取消模式为异步模式,并检查是否有未决取消请求
  1. int
  2. attribute_hidden
  3. __pthread_enable_asynccancel (void)
  4. {//
  5.   struct pthread *self = THREAD_SELF;
  6.   int oldval = THREAD_GETMEM (self, cancelhandling);

  7.   while (1)
  8.     {
  9.       int newval = oldval | CANCELTYPE_BITMASK;
  10.       已经是异步模式,无须任何检查,因为异步模式中线程只要收到请求,就会退出
  11.       if (newval == oldval)
  12.     break;

  13.       int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
  14.                      oldval);
  15.       if (__builtin_expect (curval == oldval, 1))
  16.     {
  17.      if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
  18.      {
  19.      THREAD_SETMEM (self, result, PTHREAD_CANCELED);
  20.      __do_cancel ();
  21.      }

  22.      break;
  23.     }

  24.       /* Prepare the next round. */
  25.       oldval = curval;
  26.     }

  27.   return oldval;
  28. }

如果原来是异步取消类型,那么pthread_cancel将直接导致它被取消,所以根本不需要主动检查
(CANCELTYPE_BIT标示异步), 否则设置并检查


很多地方都是包含取消点,包括
pthread_join()、 pthread_testcancel()、pthread_cond_wait()、 pthread_cond_timedwait()、sem_wait()、sigwait()

write,read,大多数会阻塞的系统调用


pthread_join
  /* Switch to asynchronous cancellation.  */
  int oldtype = CANCEL_ASYNC ();
等待线程结束

  /* Restore cancellation mode.  */
  CANCEL_RESET (oldtype);



write等的实现在
./nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h 中

本质就是
old = enable async type
syscall
restore old type


xcm@u32:~/test/pthread$ cat write.c
int main()
{
    write(1, "\n", 1);
}
xcm@u32:~/test/pthread$ gcc write.c -static
xcm@u32:~/test/pthread$ objdump -d >tmp


  1. 0804f8a0 <__libc_write>:
  2. %gs:0xc检查是否多线程,单线程没有必要
  3.  804f8a0:    65 83 3d 0c 00 00 00     cmpl $0x0,%gs:0xc
  4.  804f8a7:    00
  5.  804f8a8:    75 21     jne 804f8cb <__write_nocancel+0x21>

  6. 0804f8aa <__write_nocancel>:
  7.  804f8aa:    53     push %ebx
  8.  804f8ab:    8b 54 24 10     mov 0x10(%esp),%edx
  9.  804f8af:    8b 4c 24 0c     mov 0xc(%esp),%ecx
  10.  804f8b3:    8b 5c 24 08     mov 0x8(%esp),%ebx
  11.  804f8b7:    b8 04 00 00 00     mov $0x4,%eax
  12.  804f8bc:    cd 80     int $0x80
  13.  804f8be:    5b     pop %ebx
  14.  804f8bf:    3d 01 f0 ff ff     cmp $0xfffff001,%eax
  15.  804f8c4:    0f 83 36 20 00 00     jae 8051900 <__syscall_error>
  16.  804f8ca:    c3     ret
  17.  804f8cb:    e8 30 0e 00 00     call 8050700 <__libc_enable_asynccancel>

默认情况下,只要有取消请求,并且遇到取消点就会退出
所以如果一个线程不到达取消点, 比如仅仅操作一些数据结构就没有被中断的风险
否则容易死锁

  1. #include <pthread.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <sys/wait.h>

  6. pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
  7. void unlock(void *unused)
  8. {
  9.     pthread_mutex_unlock(&lock);
  10. }

  11. void *threadfunc(void *parm)
  12. {
  13.     while (1)
  14.     {
  15.         //pthread_cleanup_push(unlock, 0);
  16.         pthread_mutex_lock(&lock);
  17.         write(111, "\n", 1);
  18.         pthread_mutex_unlock(&lock);
  19.         //pthread_cleanup_pop(0);
  20.     }
  21.     return 0;
  22. }

  23. int main(int argc, char **argv)
  24. {
  25.     pthread_t thread;
  26.     while (1)
  27.     {
  28.         pthread_create(&thread, NULL, threadfunc, NULL);
  29.         pthread_cancel(thread);
  30.         pthread_join(thread, 0);

  31.         printf("locking ..\n");
  32.         pthread_mutex_lock(&lock);
  33.         printf("done\n");
  34.         pthread_mutex_unlock(&lock);
  35.     }
  36.     return 0;
  37. }

把注释去掉就OK了,它在退出之前会先执行其cleanup函数


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

上一篇:pthread_once

下一篇:linux tcpdump

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