Chinaunix首页 | 论坛 | 博客
  • 博客访问: 455188
  • 博文数量: 143
  • 博客积分: 6159
  • 博客等级: 准将
  • 技术积分: 1667
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-25 23:08
文章分类

全部博文(143)

文章存档

2013年(1)

2012年(11)

2011年(55)

2010年(76)

分类:

2010-10-08 21:41:31

1. pthread创建过程
============================================================

Goals of NPTL:
. POSIX compiliance
. effective use of SMP
. low startup cost
. low link-in cost
. binary compatibility
. hardware scalability
. software scalability
. machine arch support
. NUMA support
. integration with C++


pthread 数据结构:

struct pthread {                                                (nptl/descr.h)
  tcbhead_t header;

  /* This descriptor's link on the `stack_used' or `__stack_user' list.  */
  list_t list;

  /* Thread ID - which is also a 'is this thread descriptor (and
     therefore stack) used' flag.  */
  pid_t tid;

  /* Process ID - thread group ID in kernel speak.  */
  pid_t pid;

  /* List of robust mutexes the thread is holding.  */
  void *robust_prev;
  struct robust_list_head robust_head;

  /* List of cleanup buffers.  */      单向链表, 用于cleanup_push保存注册函数
  struct _pthread_cleanup_buffer *cleanup;

  /* Unwind information.  */           单向链表, 用于支持pthread_cancel
  struct pthread_unwind_buf *cleanup_jmp_buf;

  /* Flags determining processing of cancellation.  */
  int cancelhandling;

  /* Flags.  Including those copied from the thread attribute.  */
  int flags;

  /* We allocate one block of references here.  This should be enough
     to avoid allocating any memory dynamically for most applications.  */
  struct pthread_key_data
  {
    /* Sequence number.  We use uintptr_t to not require padding on
       32- and 64-bit machines.  On 64-bit machines it helps to avoid
       wrapping, too.  */
    uintptr_t seq;

    /* Data pointer.  */
    void *data;
  } specific_1stblock[PTHREAD_KEY_2NDLEVEL_SIZE];

  /* Two-level array for the thread-specific data.  */
  struct pthread_key_data *specific[PTHREAD_KEY_1STLEVEL_SIZE];

  /* Flag which is set when specific data is set.  */
  bool specific_used;

  /* True if events must be reported.  */
  bool report_events;

  /* True if the user provided the stack.  */
  bool user_stack;

  /* True if thread must stop at startup time.  */
  bool stopped_start;

  /* The parent's cancel handling at the time of the pthread_create
     call.  This might be needed to undo the effects of a cancellation.  */
  int parent_cancelhandling;

  /* Lock to synchronize access to the descriptor.  */
  int lock;

  /* Lock for synchronizing setxid calls.  */
  int setxid_futex;

  /* If the thread waits to join another one the ID of the latter is
     stored here.

     In case a thread is detached this field contains a pointer of the
     TCB if the thread itself.  This is something which cannot happen
     in normal operation.  */
  struct pthread *joinid;

  /* The result of the thread function.  */
  void *result;

  /* Scheduling parameters for the new thread.  */
  struct sched_param schedparam;
  int schedpolicy;

  /* Start position of the code to be executed and the argument passed
     to the function.  */
  void *(*start_routine) (void *);
  void *arg;

  /* Debug state.  */
  td_eventbuf_t eventbuf;
  /* Next descriptor with a pending event.  */
  struct pthread *nextevent;

  /* If nonzero pointer to area allocated for the stack and its
     size.  */
  void *stackblock;
  size_t stackblock_size;
  /* Size of the included guard area.  */
  size_t guardsize;
  /* This is what the user specified and what we will report.  */
  size_t reported_guardsize;

  /* Thread Priority Protection data.  */
  struct priority_protection_data *tpp;

  /* Resolver state.  */
  struct __res_state res;

  char end_padding[];
};

============================================================
入口函数:

int pthread_create (pthread_t *thread,
                    pthread_attr_t *attr,
                    void *(*start_routine)(void *),
                    void *arg)                          (nptl/pthread_create.c)

    1. 首先为新thread分配 pthread *pt,
       ALLOCATE_STACK (iattr, &pd),
       通过mmap为新thread分配stack,缺省大小可用ulimit查看,
       将pthread结构放在stack底部,sp指针指于stack顶部
       pd->stackblock =
       pd->stackblock_size =

    2. 初始化pd
       pd->start_routine =
       pd->arg =
       pd->flags =
       pd->joinid = iattr->flags & ATTR_FLAG_DETACHSTATE ? pd : NULL

    3. 根据iattr,设置pd->schedpolicy, pd->schedparam等调度相关参数

    4. 调用create_thread创建线程,create_thread调用do_clone创建线程,
       入口函数为start_thread,
       start_thread中
       a. 初始化 pd->robust_head
       b. 添加对sig-cancel的处理,用于完成pthread_cancel
       c. setjmp,保存jmpbuf于 pd->cleanup_jmp_buf中
       d. 调用pd->start_routine,并将其返回值赋予pd->result
       e. 在pd->start_routine退出后,start_routine负责清理tls等资源


int pthread_exit (void *value_ptr)                  (nptl/pthread_exit.c)
    *value_ptr = THREAD_SELF->result
    __do_cancel()
        1. 设置thread->cancelhandling 为 exiting_bit
        2. __pthread_unwind(self->cleanup_jmp_buf)
            循环调用pd->cleanup所有注册的clearnup函数
            longjmp到 pd->cleanup_jmp_buf
            abort()

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

上一篇:Google TV

下一篇:鲁迅知道的太多了

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