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

全部博文(52)

文章存档

2011年(48)

2010年(4)

分类: LINUX

2011-03-11 16:05:37


  1. int pthread_create(pthread_t *restrict thread,
  2.               const pthread_attr_t *restrict attr,
  3.               void *(*start_routine)(void*), void *restrict arg);

以NULL attr, static linked为例子

1. 使用default_attr;

2. 分配线程栈,struct pthread结构放在栈底(添加或者删除元素的一端叫栈顶,另一端叫栈底)
    pthread代表新的线程,  pthread结构上面是TLS(thread local storage)空间,它的内容为程序中
   可执行文件中的(libc初始化时会查出来在哪)副本, 这样每个线程都有一份
   _______________
   |struct pthread|
   |      TLS            |

   STACK top

3.   pd->start_routine = start_routine;
      pd->arg = arg;

4.  调用clone函 数, 建立新线程,它的起始函数为start_thread, 该函数的参数为刚刚分配的pthread结构
     ! 用户传的start_routine在pthread中有
     给clone传递的tls参数和初始化的时候用set_thread_area一样,除了base_addr指向自身的
     TLS之外
     
    
  1. /* The "thread register" gets initialized from a segment descriptor.
  2.    Initialize such a descriptor first. */
  3. #define PREPARE_CREATE \
  4.   union user_desc_init desc;                         \
  5.                                      \
  6.   /* Describe the thread-local storage segment. */             \
  7.                                      \
  8.   /* The 'entry_number' field. The first three bits of the segment     \
  9.      register value select the GDT, ignore them. We get the index     \
  10.      from the value of the %gs register in the current thread. */     \
  11.   desc.vals[0] = TLS_GET_GS () >> 3;                     \
  12.   /* The 'base_addr' field. Pointer to the TCB. */             \
  13.   desc.vals[1] = (unsigned long int) pd;                 \
  14.   /* The 'limit' field. We use 4GB which is 0xfffff pages. */         \
  15.   desc.vals[2] = 0xfffff;                         \
  16.   /* Collapsed value of the bitfield:                     \
  17.        .seg_32bit = 1                             \
  18.        .contents = 0                             \
  19.        .read_exec_only = 0                         \
  20.        .limit_in_pages = 1                         \
  21.        .seg_not_present = 0                         \
  22.        .useable = 1 */                             \
  23.   desc.vals[3] = 0x51
 

  

5.  start_thread 调用 pd->start_routine,  线程的起始函数pd->start_routine的被调用和整个程序
      的main函数被调用的方式类似
    
  1. static int
  2. start_thread (void *arg)
  3. {
  4.   struct pthread *pd = (struct pthread *) arg;
  5.  
  6.   struct pthread_unwind_buf unwind_buf;

  7.   int not_first_call;
  8.   not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);
  9.   会两次到这里来,一次是开始,一次是 _被_ 结束或者主动调用pthread_exit
  10.   否则只有一次,start_routine可能直接返回
  11.   if (! not_first_call)
  12.     {
  13.       /* Run the code the user provided. */
  14.          pd->start_routine (pd->arg));

  15.     }

  16.   /* Run the destructor for the thread-local data. */
  17.   __nptl_deallocate_tsd ();


  18.   /* If this is the last thread we terminate the process now. We
  19.      do not notify the debugger, it might just irritate it if there
  20.      is no thread left. */
  21.   最后一个线程
  22.   if (__builtin_expect (atomic_decrement_and_test (&__nptl_nthreads), 0))
  23.     /* This was the last thread. */
  24.     exit (0);

  25.   /* We cannot call '_exit' here. '_exit' will terminate the process.

  26.      The 'exit' implementation in the kernel will signal when the
  27.      process is really dead since 'clone' got passed the CLONE_CLEARTID
  28.      flag. The 'tid' field in the TCB will be set to zero.

  29.      The exit code is zero since in case all threads exit by calling
  30.      'pthread_exit' the exit status must be 0 (zero). */
  31.   __exit_thread_inline (0);

  32.   /* NOTREACHED */
  33.   return 0;
  34. }



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

上一篇:clone

下一篇:pthread_exit

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