diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 187046931..8551e462c 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,13 @@ +2011-05-16 Corinna Vinschen + + * dcrt0.cc (child_info_fork::alloc_stack_hard_way): Check if the + requested stack is application-provided within the user heap or an + mmapped region. If so, just use it. Add comment to explain why. + * miscfuncs.cc (thread_wrapper): If an application-provided stack + has been given, implement cygtls area at the stackbase. Fix comment. + * mmap.cc (is_mmapped_region): New function. + * winsup.h (is_mmapped_region): Declare. + 2011-05-15 Corinna Vinschen * miscfuncs.cc (thread_wrapper): Add comments to assembler code. diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 92056c80f..a6eb2696d 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -398,6 +398,15 @@ child_info_fork::alloc_stack_hard_way (volatile char *b) int newlen; bool guard; + /* First check if the requested stack area is part of the user heap + or part of a mmaped region. If so, we have been started from a + pthread with an application-provided stack, and the stack has just + to be used as is. */ + if ((stacktop >= cygheap->user_heap.base + && stackbottom <= cygheap->user_heap.max) + || is_mmapped_region ((caddr_t) stacktop, (caddr_t) stackbottom)) + return; + if (!VirtualQuery ((LPCVOID) &b, &m, sizeof m)) api_fatal ("fork: couldn't get stack info, %E"); diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc index 73dec4c1a..a166ca1da 100644 --- a/winsup/cygwin/miscfuncs.cc +++ b/winsup/cygwin/miscfuncs.cc @@ -410,16 +410,17 @@ thread_wrapper (VOID *arg) { /* If the application provided the stack, we must make sure that it's actually used by the thread function. So what we do here is - to compute the stackbase of the application-provided stack and - change the stack pointer accordingly. - - NOTE: _my_tls is on the stack created by CreateThread! It's - unlikely the tls structure will ever exceed 64K, but if - so, we have to raise the size of the stack in the call - to CreateThread, too. */ + to compute the stackbase of the application-provided stack, move + _my_tls to the stackbase, and change the stack pointer accordingly. */ wrapper_arg.stackaddr = (PVOID) ((PBYTE) wrapper_arg.stackaddr - + wrapper_arg.stacksize - - sizeof (PVOID)); + + wrapper_arg.stacksize); + _tlsbase = (char *) wrapper_arg.stackaddr; + wrapper_arg.stackaddr = (PVOID) ((PBYTE) wrapper_arg.stackaddr + - CYGTLS_PADSIZE); + _tlstop = (char *) wrapper_arg.stackaddr; + _my_tls.init_thread ((char *) wrapper_arg.stackaddr, + (DWORD (*)(void*, void*)) wrapper_arg.func); + wrapper_arg.stackaddr = (PVOID) (_tlstop - sizeof (PVOID)); __asm__ ("\n\ movl %[WRAPPER_ARG], %%ebx # Load &wrapper_arg into ebx \n\ movl (%%ebx), %%eax # Load thread func into eax \n\ diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc index 059daa186..9daa32fd7 100644 --- a/winsup/cygwin/mmap.cc +++ b/winsup/cygwin/mmap.cc @@ -659,6 +659,34 @@ mmap_areas::del_list (mmap_list *ml) cfree (ml); } +/* This function allows an external function to test if a given memory + region is part of an mmapped memory region. */ +bool +is_mmapped_region (caddr_t start_addr, caddr_t end_address) +{ + bool ret = false; + + size_t len = end_address - start_addr; + + LIST_LOCK (); + mmap_list *map_list = mmapped_areas.get_list_by_fd (-1, NULL); + + mmap_record *rec; + caddr_t u_addr; + DWORD u_len; + + LIST_FOREACH (rec, &map_list->recs, mr_next) + { + if (rec->match (start_addr, len, u_addr, u_len)) + { + ret = true; + break; + } + } + LIST_UNLOCK (); + return ret; +} + /* This function is called from exception_handler when a segmentation violation has occurred. It should also be called from all Cygwin functions that want to support passing noreserve mmap page addresses @@ -677,6 +705,7 @@ mmap_areas::del_list (mmap_list *ml) On MAP_NORESERVE_COMMITED, the exeception handler should return 0 to allow the application to retry the memory access, or the calling Cygwin function should retry the Windows system call. */ + mmap_region_status mmap_is_attached_or_noreserve (void *addr, size_t len) { diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 087da61f4..44f00339b 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -270,6 +270,7 @@ enum mmap_region_status MMAP_NORESERVE_COMMITED }; mmap_region_status mmap_is_attached_or_noreserve (void *addr, size_t len); +bool is_mmapped_region (caddr_t start_addr, caddr_t end_address); inline bool flush_file_buffers (HANDLE h) {