MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXES, -1, 0);
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
static int pthread_allocate_stack(const pthread_attr_t *attr,                                  pthread_descr default_new_thread,                                  int pagesize,                                  pthread_descr * out_new_thread,                                  char ** out_new_thread_bottom,                                  char ** out_guardaddr,                                  size_t * out_guardsize){  pthread_descr new_thread;  char * new_thread_bottom;  char * guardaddr;  size_t stacksize, guardsize;  if (attr != NULL && attr->__stackaddr_set)    {      /* The user provided a stack.  For now we interpret the supplied	 address as 1 + the highest addr. in the stack segment.  If a	 separate register stack is needed, we place it at the low end	 of the segment, relying on the associated stacksize to	 determine the low end of the segment.  This differs from many	 (but not all) other pthreads implementations.  The intent is	 that on machines with a single stack growing toward higher	 addresses, stackaddr would be the lowest address in the stack	 segment, so that it is consistently close to the initial sp	 value. */      new_thread =        (pthread_descr) ((long)(attr->__stackaddr) & -sizeof(void *)) - 1;      new_thread_bottom = (char *) attr->__stackaddr - attr->__stacksize;      guardaddr = new_thread_bottom;      guardsize = 0;#ifndef THREAD_SELF      __pthread_nonstandard_stacks = 1;#endif      /* Clear the thread data structure.  */      memset (new_thread, '\0', sizeof (*new_thread));    }  else    {#ifdef NEED_SEPARATE_REGISTER_STACK      size_t granularity = 2 * pagesize;      /* Try to make stacksize/2 a multiple of pagesize */#else      size_t granularity = pagesize;#endif      void *map_addr;      /* Allocate space for stack and thread descriptor at default address */#ifdef NEED_SEPARATE_REGISTER_STACK      void *res_addr;      if (attr != NULL)	{	  guardsize = page_roundup (attr->__guardsize, granularity);	  stacksize = STACK_SIZE - guardsize;	  stacksize = MIN (stacksize,			   page_roundup (attr->__stacksize, granularity));	}      else	{	  guardsize = granularity;	  stacksize = STACK_SIZE - granularity;	}      new_thread = default_new_thread;      new_thread_bottom = (char *) (new_thread + 1) - stacksize - guardsize;      /* Includes guard area, unlike the normal case.  Use the bottom       end of the segment as backing store for the register stack.       Needed on IA64.  In this case, we also map the entire stack at       once.  According to David Mosberger, that's cheaper.  It also       avoids the risk of intermittent failures due to other mappings       in the same region.  The cost is that we might be able to map       slightly fewer stacks.  */      /* XXX Fix for floating stacks with variable sizes.  */      /* First the main stack: */      map_addr = (caddr_t)((char *)(new_thread + 1) - stacksize / 2);      res_addr = mmap(map_addr, stacksize / 2,		      PROT_READ | PROT_WRITE | PROT_EXEC,		      MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);      if (res_addr != map_addr)	{	  /* Bad luck, this segment is already mapped. */	  if (res_addr != MAP_FAILED)	    munmap(res_addr, stacksize / 2);	  return -1;	}      /* Then the register stack:	*/      map_addr = (caddr_t)new_thread_bottom;      res_addr = mmap(map_addr, stacksize/2,		      PROT_READ | PROT_WRITE | PROT_EXEC,		      MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXES, -1, 0);      if (res_addr != map_addr)	{	  if (res_addr != MAP_FAILED)	    munmap(res_addr, stacksize / 2);	  munmap((caddr_t)((char *)(new_thread + 1) - stacksize/2),		 stacksize/2);	  return -1;	}      guardaddr = new_thread_bottom + stacksize/2;      /* We leave the guard area in the middle unmapped.	*/#else  /* !NEED_SEPARATE_REGISTER_STACK */# if FLOATING_STACKS      if (attr != NULL)	{	  guardsize = page_roundup (attr->__guardsize, granularity);	  stacksize = __pthread_max_stacksize - guardsize;	  stacksize = MIN (stacksize,			   page_roundup (attr->__stacksize, granularity));	}      else	{	  guardsize = granularity;	  stacksize = __pthread_max_stacksize - guardsize;	}      map_addr = mmap(NULL, stacksize + guardsize,		      PROT_READ | PROT_WRITE | PROT_EXEC,		      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);      if (map_addr == MAP_FAILED)        /* No more memory available.  */        return -1;      guardaddr = map_addr;      if (guardsize > 0)	mprotect (guardaddr, guardsize, PROT_NONE);      new_thread_bottom = (char *) map_addr + guardsize;      new_thread = ((pthread_descr) (new_thread_bottom + stacksize)) - 1;# else /* !FLOATING_STACKS */      void *res_addr;      if (attr != NULL)	{	  guardsize = page_roundup (attr->__guardsize, granularity);	  stacksize = STACK_SIZE - guardsize;	  stacksize = MIN (stacksize,			   page_roundup (attr->__stacksize, granularity));	}      else	{	  guardsize = granularity;	  stacksize = STACK_SIZE - granularity;	}      new_thread = default_new_thread;      new_thread_bottom = (char *) (new_thread + 1) - stacksize;      map_addr = new_thread_bottom - guardsize;      res_addr = mmap(map_addr, stacksize + guardsize,		      PROT_READ | PROT_WRITE | PROT_EXEC,		      MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);      if (res_addr != map_addr)	{	  /* Bad luck, this segment is already mapped. */	  if (res_addr != MAP_FAILED)	    munmap (res_addr, stacksize + guardsize);	  return -1;	}      /* We manage to get a stack.  Protect the guard area pages if	 necessary.  */      guardaddr = map_addr;      if (guardsize > 0)	mprotect (guardaddr, guardsize, PROT_NONE);# endif#endif /* !NEED_SEPARATE_REGISTER_STACK */    }  *out_new_thread = new_thread;  *out_new_thread_bottom = new_thread_bottom;  *out_guardaddr = guardaddr;  *out_guardsize = guardsize;  return 0;}