- override_stack = CALL_REAL (mmap, NULL, override_stacksize,
- PROT_READ|PROT_WRITE,
- MAP_PRIVATE|MF_MAP_ANON,
- 0, 0);
- if (override_stack == 0 || override_stack == MAP_FAILED)
- {
- errno = EAGAIN;
- return -1;
- }
-
- VERBOSE_TRACE ("thread stack alloc %p size %lu\n",
- override_stack, (unsigned long) override_stacksize);
-
- /* The stackaddr pthreads attribute is a candidate stack pointer.
- It must point near the top or the bottom of this buffer, depending
- on whether stack grows downward or upward, and suitably aligned.
- On the x86, it grows down, so we set stackaddr near the top. */
- override_stack = (void *)
- (((uintptr_t) override_stack + override_stacksize - alignment - perturb)
- & (~(uintptr_t)(alignment-1)));
-
- /* XXX: consider using POSIX2K attr_setstack() */
- if (pthread_attr_setstackaddr (& override_attr, override_stack) != 0 ||
- pthread_attr_setstacksize (& override_attr,
- override_stacksize - alignment - perturb) != 0)
- {
- /* This should not happen. */
- CALL_REAL (munmap, override_stack, override_stacksize);
- errno = EAGAIN;
- return -1;
- }
- }
-
- /* Actually start the child thread. */
- {
- struct pthread_start_info psi;
- struct pthread_info *pi = NULL;
-
- /* Fill in startup-control fields. */
- psi.user_fn = start;
- psi.user_arg = arg;
- psi.thread_info = NULL;
-
- /* Actually create the thread. */
- __mf_state = reentrant;
- result = CALL_REAL (pthread_create, thr, & override_attr,
- & __mf_pthread_spawner, (void *) & psi);
- __mf_state = active;
- /* We also hook pthread_join/pthread_exit to get into reentrant
- mode during thread shutdown/cleanup. */
-
- /* Wait until child thread has progressed far enough into its
- __mf_pthread_spawner() call. */
- while (1) /* XXX: timeout? */
- {
- volatile struct pthread_start_info *psip = & psi;
- pi = psip->thread_info;
- if (pi != NULL)
- break;
- sched_yield ();
- }
-
- /* Fill in remaining fields in pthread_info. */
- pi->stack = override_stack;
- pi->stack_size = override_stacksize;
- /* XXX: this might be too late for future heuristics that attempt
- to use thread stack bounds. We may need to put the new thread
- to sleep. */
- }
-
-
- /* May need to clean up if we created a pthread_attr_t of our own. */
- if (attr == NULL)
- pthread_attr_destroy (& override_attr); /* NB: this shouldn't deallocate stack */
-
- return result;