From patchwork Sun Aug 9 08:17:17 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Frysinger X-Patchwork-Id: 505410 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 501231401F0 for ; Sun, 9 Aug 2015 18:17:35 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b=Xp3o7VnZ; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id; q=dns; s= default; b=C9tEfYTVaa8H8iF8MspUF8X9httRkzsD+EhRfilG5MiPGKe/h1iKP US8Qp0avNuM0CA4nSHOT0AN2/0yaSf8PhPNOE8eo4DId6zrfcTBNyMcMXhPLLFAw LHoVkvHFCd13GwglkM1WaM4lkz9IxX29cCOeO6KQONeZKax4G796Xk= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id; s=default; bh=Gt4qN7J51Sn5e0ANecPA7+VcSjM=; b=Xp3o7VnZqQm2LNMidxO3f7QwwBOt RUqq1HEbydep4IOxNimsfCx3cSxwghUxnsN4j04CLLyXXddqf9zQ72PKwQ+K8BBp b/KQnPcrWeHj4+CMt70Hyk/IiVIhlPml/sxbeJpUlCHwYtK+BjB1o9ewLVnBAClR WzdkIZPmuPtmOO8= Received: (qmail 76459 invoked by alias); 9 Aug 2015 08:17:27 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 76440 invoked by uid 89); 9 Aug 2015 08:17:25 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.8 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 X-HELO: smtp.gentoo.org From: Mike Frysinger To: libc-alpha@sourceware.org Cc: Carlos O'Donell Subject: [PATCH] nptl: support thread stacks that grow up Date: Sun, 9 Aug 2015 04:17:17 -0400 Message-Id: <1439108237-31537-1-git-send-email-vapier@gentoo.org> From: Carlos O'Donell Gentoo has been carrying this for all arches since 2.17. URL: http://bugs.gentoo.org/301642 2015-08-09 Carlos O'Donell * nptl/allocatestack.c (allocate_stack): Declare new stackaddr, assign attr->stackaddr to it, and adjust it down when _STACK_GROWS_UP. Change all attr->stackaddr to stackaddr. [_STACK_GROWS_UP]: Delete assert. * nptl/pthread_create.c (START_THREAD_DEFN) [!_STACK_GROWS_DOWN]: Implement stack grows up logic. * nptl/pthread_getattr_np.c (pthread_getattr_np): Implement stack grows up logic. --- nptl/allocatestack.c | 20 +++++++++++++------- nptl/pthread_create.c | 19 ++++++++++++++++--- nptl/pthread_getattr_np.c | 17 +++++++++++++++-- 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c index 753da61..f182e9a 100644 --- a/nptl/allocatestack.c +++ b/nptl/allocatestack.c @@ -372,6 +372,13 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, if (__glibc_unlikely (attr->flags & ATTR_FLAG_STACKADDR)) { uintptr_t adj; + char *stackaddr = (char *) attr->stackaddr; + + /* Assume the same layout as the _STACK_GROWS_DOWN case, with struct + pthread at the top of the stack block. Later we adjust the guard + location and stack address to match the _STACK_GROWS_UP case. */ + if (_STACK_GROWS_UP) + stackaddr += attr->stacksize; /* If the user also specified the size of the stack make sure it is large enough. */ @@ -381,11 +388,11 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, /* Adjust stack size for alignment of the TLS block. */ #if TLS_TCB_AT_TP - adj = ((uintptr_t) attr->stackaddr - TLS_TCB_SIZE) + adj = ((uintptr_t) stackaddr - TLS_TCB_SIZE) & __static_tls_align_m1; assert (size > adj + TLS_TCB_SIZE); #elif TLS_DTV_AT_TP - adj = ((uintptr_t) attr->stackaddr - __static_tls_size) + adj = ((uintptr_t) stackaddr - __static_tls_size) & __static_tls_align_m1; assert (size > adj); #endif @@ -395,10 +402,10 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, the stack. It is the user's responsibility to do this if it is wanted. */ #if TLS_TCB_AT_TP - pd = (struct pthread *) ((uintptr_t) attr->stackaddr + pd = (struct pthread *) ((uintptr_t) stackaddr - TLS_TCB_SIZE - adj); #elif TLS_DTV_AT_TP - pd = (struct pthread *) (((uintptr_t) attr->stackaddr + pd = (struct pthread *) (((uintptr_t) stackaddr - __static_tls_size - adj) - TLS_PRE_TCB_SIZE); #endif @@ -410,7 +417,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, pd->specific[0] = pd->specific_1stblock; /* Remember the stack-related values. */ - pd->stackblock = (char *) attr->stackaddr - size; + pd->stackblock = (char *) stackaddr - size; pd->stackblock_size = size; /* This is a user-provided stack. It will not be queued in the @@ -634,7 +641,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, char *guard = mem + (((size - guardsize) / 2) & ~pagesize_m1); #elif _STACK_GROWS_DOWN char *guard = mem; -# elif _STACK_GROWS_UP +#elif _STACK_GROWS_UP char *guard = (char *) (((uintptr_t) pd - guardsize) & ~pagesize_m1); #endif if (mprotect (guard, guardsize, PROT_NONE) != 0) @@ -734,7 +741,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, # endif #else *stack = pd->stackblock; - assert (*stack > 0); #endif return 0; diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c index d10f4ea..b08ba45 100644 --- a/nptl/pthread_create.c +++ b/nptl/pthread_create.c @@ -428,12 +428,25 @@ START_THREAD_DEFN #ifdef _STACK_GROWS_DOWN char *sp = CURRENT_STACK_FRAME; size_t freesize = (sp - (char *) pd->stackblock) & ~pagesize_m1; -#else -# error "to do" -#endif assert (freesize < pd->stackblock_size); if (freesize > PTHREAD_STACK_MIN) __madvise (pd->stackblock, freesize - PTHREAD_STACK_MIN, MADV_DONTNEED); +#else + /* Page aligned start of memory to free (higher than or equal + to current sp plus the minimum stack size). */ + void *freeblock = (void*)((size_t)(CURRENT_STACK_FRAME + + PTHREAD_STACK_MIN + + pagesize_m1) + & ~pagesize_m1); + char *free_end = (char *) (((uintptr_t) pd - pd->guardsize) & ~pagesize_m1); + /* Is there any space to free? */ + if (free_end > (char *)freeblock) + { + size_t freesize = (size_t)(free_end - (char *)freeblock); + assert (freesize < pd->stackblock_size); + __madvise (freeblock, freesize, MADV_DONTNEED); + } +#endif /* If the thread is detached free the TCB. */ if (IS_DETACHED (pd)) diff --git a/nptl/pthread_getattr_np.c b/nptl/pthread_getattr_np.c index 52a4602..9834302 100644 --- a/nptl/pthread_getattr_np.c +++ b/nptl/pthread_getattr_np.c @@ -60,7 +60,11 @@ pthread_getattr_np (thread_id, attr) if (__glibc_likely (thread->stackblock != NULL)) { iattr->stacksize = thread->stackblock_size; +#if _STACK_GROWS_DOWN iattr->stackaddr = (char *) thread->stackblock + iattr->stacksize; +#else + iattr->stackaddr = (char *) thread->stackblock; +#endif } else { @@ -105,7 +109,9 @@ pthread_getattr_np (thread_id, attr) char *line = NULL; size_t linelen = 0; +#if _STACK_GROWS_DOWN uintptr_t last_to = 0; +#endif while (! feof_unlocked (fp)) { @@ -129,17 +135,24 @@ pthread_getattr_np (thread_id, attr) stack extension request. */ iattr->stacksize = (iattr->stacksize & -(intptr_t) GLRO(dl_pagesize)); - +#if _STACK_GROWS_DOWN /* The limit might be too high. */ if ((size_t) iattr->stacksize > (size_t) iattr->stackaddr - last_to) iattr->stacksize = (size_t) iattr->stackaddr - last_to; - +#else + /* The limit might be too high. */ + if ((size_t) iattr->stacksize + > to - (size_t) iattr->stackaddr) + iattr->stacksize = to - (size_t) iattr->stackaddr; +#endif /* We succeed and no need to look further. */ ret = 0; break; } +#if _STACK_GROWS_DOWN last_to = to; +#endif } free (line);