new_thread->p_spinlock = &(__pthread_handles[sseg].h_spinlock);
new_thread->p_lock = &(__pthread_handles[sseg].h_lock);
static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,				 void * (*start_routine)(void *), void *arg,				 sigset_t * mask, int father_pid){  size_t sseg;  int pid;  pthread_descr new_thread;  char * new_thread_bottom;  pthread_t new_thread_id;  void *guardaddr = NULL;  /* Find a free stack segment for the current stack */  for (sseg = 1; ; sseg++)    {      if (sseg >= PTHREAD_THREADS_MAX)	return EAGAIN;      if (__pthread_handles[sseg].h_descr != NULL)	continue;      if (attr == NULL || !attr->stackaddr_set)	{	  new_thread = thread_segment(sseg);	  new_thread_bottom = (char *) new_thread - STACK_SIZE;	  /* Allocate space for stack and thread descriptor. */	  if (mmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),		   INITIAL_STACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,		   MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_GROWSDOWN,		   -1, 0) != MAP_FAILED)	    {	      /* We manage to get a stack.  Now see whether we need a guard		 and allocate it if necessary.  */	      if (attr == NULL || attr->guardsize != 0)		{		  guardaddr = mmap ((caddr_t)((char *)(new_thread+1)					      - STACK_SIZE),				    attr ? attr->guardsize : __getpagesize (),				    0, MAP_FIXED, -1, 0);		  if (guardaddr == MAP_FAILED)		    /* We don't make this an error.  */		    guardaddr = NULL;		}	      break;	    }	  /* It seems part of this segment is already mapped. Try the next. */	}      else	{	  new_thread = (pthread_descr) ((long) attr->stackaddr					& -sizeof(void *)) - 1;	  new_thread_bottom = (char *) attr->stackaddr - attr->stacksize;	  break;	}    }  /* Allocate new thread identifier */  pthread_threads_counter += PTHREAD_THREADS_MAX;  new_thread_id = sseg + pthread_threads_counter;  /* Initialize the thread descriptor */  new_thread->p_nextwaiting = NULL;  new_thread->p_tid = new_thread_id;  new_thread->p_priority = 0;  new_thread->p_spinlock = &(__pthread_handles[sseg].h_spinlock);  new_thread->p_signal = 0;  new_thread->p_signal_jmp = NULL;  new_thread->p_cancel_jmp = NULL;  new_thread->p_terminated = 0;  new_thread->p_detached = attr == NULL ? 0 : attr->detachstate;  new_thread->p_exited = 0;  new_thread->p_retval = NULL;  new_thread->p_joining = NULL;  new_thread->p_cleanup = NULL;  new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE;  new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED;  new_thread->p_canceled = 0;  new_thread->p_errnop = &new_thread->p_errno;  new_thread->p_errno = 0;  new_thread->p_h_errnop = &new_thread->p_h_errno;  new_thread->p_h_errno = 0;  new_thread->p_guardaddr = guardaddr;  new_thread->p_guardsize = (guardaddr == NULL			     ? 0			     : (attr == NULL				? __getpagesize () : attr->guardsize));  new_thread->p_userstack = attr != NULL && attr->stackaddr_set;  memset (new_thread->p_specific, '\0',	  PTHREAD_KEY_1STLEVEL_SIZE * sizeof (new_thread->p_specific[0]));  /* Initialize the thread handle */  __pthread_handles[sseg].h_spinlock = 0; /* should already be 0 */  __pthread_handles[sseg].h_descr = new_thread;  __pthread_handles[sseg].h_bottom = new_thread_bottom;  /* Determine scheduling parameters for the thread */  new_thread->p_start_args.schedpolicy = -1;  if (attr != NULL) {    switch(attr->inheritsched) {    case PTHREAD_EXPLICIT_SCHED:      new_thread->p_start_args.schedpolicy = attr->schedpolicy;      new_thread->p_start_args.schedparam = attr->schedparam;      break;    case PTHREAD_INHERIT_SCHED:      /* schedpolicy doesn't need to be set, only get priority */      __sched_getparam(father_pid, &new_thread->p_start_args.schedparam);      break;    }    new_thread->p_priority =      new_thread->p_start_args.schedparam.sched_priority;  }  /* Finish setting up arguments to pthread_start_thread */  new_thread->p_start_args.start_routine = start_routine;  new_thread->p_start_args.arg = arg;  new_thread->p_start_args.mask = *mask;  /* Raise priority of thread manager if needed */  __pthread_manager_adjust_prio(new_thread->p_priority);  /* Do the cloning */  pid = __clone(pthread_start_thread, (void **) new_thread,                CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |                PTHREAD_SIG_RESTART,                new_thread);  /* Check if cloning succeeded */  if (pid == -1) {    /* Free the stack if we allocated it */    if (attr == NULL || !attr->stackaddr_set)      {	munmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),	       INITIAL_STACK_SIZE);	if (new_thread->p_guardsize != 0)	  munmap(new_thread->p_guardaddr, new_thread->p_guardsize);      }    __pthread_handles[sseg].h_descr = NULL;    return errno;  }  /* Insert new thread in doubly linked list of active threads */  new_thread->p_prevlive = __pthread_main_thread;  new_thread->p_nextlive = __pthread_main_thread->p_nextlive;  __pthread_main_thread->p_nextlive->p_prevlive = new_thread;  __pthread_main_thread->p_nextlive = new_thread;  /* Set pid field of the new thread, in case we get there before the     child starts. */  new_thread->p_pid = pid;  /* We're all set */  *thread = new_thread_id;  return 0;}