From patchwork Wed Dec 29 04:42:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stafford Horne X-Patchwork-Id: 49364 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 0F9723858005 for ; Wed, 29 Dec 2021 04:47:03 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 0F9723858005 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1640753223; bh=G2YEQV7YkHpEw+2T/RvlZ5T5xUiVZvlIaZY/+WmXL88=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=by9Q9DZyguUe2EgQpfcI2wDnkbhaNLzkgt+9te5jZoWlKQz5y01YU8JJmvdsuXuPd +NuoBKr44oUt997XtqM+vxAkjkEtMbuYXcv/de17Wr17TrXowSJ/Lm3b9F6Rm7F7cr lMWhFplt9CD4F+PamhE3k+zLO0vtsNChHQ4/FFio= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pj1-x102b.google.com (mail-pj1-x102b.google.com [IPv6:2607:f8b0:4864:20::102b]) by sourceware.org (Postfix) with ESMTPS id 034E23858404 for ; Wed, 29 Dec 2021 04:43:13 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 034E23858404 Received: by mail-pj1-x102b.google.com with SMTP id b1-20020a17090a990100b001b14bd47532so18902914pjp.0 for ; Tue, 28 Dec 2021 20:43:12 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=G2YEQV7YkHpEw+2T/RvlZ5T5xUiVZvlIaZY/+WmXL88=; b=z7Cx0EYZ0X33Jzh3/dLxBFkzVEP2WsTG4gPcFQ2TJ8yPSFT4IvNx5EoFT0LTwTbkM3 IsLBUsAkq7yMFztc8vIrkZmClr0YRF3tjrfEmGamIVdPdxy2vc/3t+mp4drrG60rIXOT gbBwLTmm0xr5BrNhp/1ry0+ho7v+muOtawFwwIHxJALiVyvq5sRCDGgjvOTMBtbS1bLq H5IsQuWGKTYNfujRggCPwbx11p1zVwY9Sxxvb/jMOAPuKHHoOm57GbCAO3jzYK7PuyAe 3OSzKCOycbpp637d5YoOBOOkuZcMbPBITatE0bRKaHjUvMfp6KwjWTOCmiWknzops9ui v5sA== X-Gm-Message-State: AOAM531T1W8fS+4qnvzr2zpoL/qKiCEBnXOyPD3ZXra+n9a2hDZXPRuN p80bbNZ4WiPufYqAO9iPQFOl61T3fdo= X-Google-Smtp-Source: ABdhPJwQ8hmKLLPS/AMvfQaA815tsnPSN2WFwGlggzEZCifEICwh9g7pg8yo/WC3Q6qnhEae1Gv0FQ== X-Received: by 2002:a17:90b:38c1:: with SMTP id nn1mr30325540pjb.65.1640752991603; Tue, 28 Dec 2021 20:43:11 -0800 (PST) Received: from localhost ([2409:10:24a0:4700:e8ad:216a:2a9d:6d0c]) by smtp.gmail.com with ESMTPSA id t10sm23403210pfg.105.2021.12.28.20.43.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Dec 2021 20:43:10 -0800 (PST) To: GLIBC patches Subject: [PATCH v4 05/13] or1k: Thread Local Storage support Date: Wed, 29 Dec 2021 13:42:43 +0900 Message-Id: <20211229044251.2203653-6-shorne@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211229044251.2203653-1-shorne@gmail.com> References: <20211229044251.2203653-1-shorne@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Stafford Horne via Libc-alpha From: Stafford Horne Reply-To: Stafford Horne Cc: Openrisc Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" OpenRISC includes 3 TLS addressing models. Local Dynamic optimizations are not done in the linker and therefore use the same code sequences as Global Dynamic. Reviewed-by: Adhemerval Zanella --- sysdeps/or1k/dl-tls.h | 27 ++++++ sysdeps/or1k/libc-tls.c | 34 ++++++++ sysdeps/or1k/nptl/tls.h | 184 +++++++++++++++++++++++++++++++++++++++ sysdeps/or1k/stackinfo.h | 34 ++++++++ 4 files changed, 279 insertions(+) create mode 100644 sysdeps/or1k/dl-tls.h create mode 100644 sysdeps/or1k/libc-tls.c create mode 100644 sysdeps/or1k/nptl/tls.h create mode 100644 sysdeps/or1k/stackinfo.h diff --git a/sysdeps/or1k/dl-tls.h b/sysdeps/or1k/dl-tls.h new file mode 100644 index 0000000000..382588d504 --- /dev/null +++ b/sysdeps/or1k/dl-tls.h @@ -0,0 +1,27 @@ +/* TLS definitions for the ELF dynamic linker. OpenRISC version. + Copyright (C) 2021 Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + +extern void *__tls_get_addr (tls_index *ti); diff --git a/sysdeps/or1k/libc-tls.c b/sysdeps/or1k/libc-tls.c new file mode 100644 index 0000000000..1524855e88 --- /dev/null +++ b/sysdeps/or1k/libc-tls.c @@ -0,0 +1,34 @@ +/* Thread-local storage handling in the ELF dynamic linker. + OpenRISC version. + Copyright (C) 2021 Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include + +/* On OpenRISC, linker optimizations are not required, so __tls_get_addr + can be called even in statically linked binaries. In this case module + must be always 1 and PT_TLS segment exist in the binary, otherwise it + would not link. */ + +void * +__tls_get_addr (tls_index *ti) +{ + dtv_t *dtv = THREAD_DTV (); + return (char *) dtv[1].pointer.val + ti->ti_offset; +} diff --git a/sysdeps/or1k/nptl/tls.h b/sysdeps/or1k/nptl/tls.h new file mode 100644 index 0000000000..c9e86add6d --- /dev/null +++ b/sysdeps/or1k/nptl/tls.h @@ -0,0 +1,184 @@ +/* Definition for thread-local data handling. NPTL/OpenRISC version. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#ifndef _TLS_H +#define _TLS_H 1 + +#include + +#ifndef __ASSEMBLER__ +# include +# include +# include +# include + +typedef struct +{ + dtv_t *dtv; + void *__padding[3]; +} tcbhead_t; + +register tcbhead_t *__thread_self __asm__("r10"); + +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +/* Get system call information. */ +# include + +/* The TP points to the start of the TLS block. + As I understand it, this isn't strictly that "TP points to DTV" - it's + more where to place the TCB in the TLS block. This will place it in + the beginning. + + Layout: + +-----+-----+----------------------+ + | PRE | TCB | TLS MEMORY .. | + +-----+-----+----------------------+ + ^ r10 / TP + + PRE is the struct pthread described below + TCB is tcbhead_t + TLS memory is where the TLS program sections are loaded + + See _dl_allocate_tls_storage and __libc_setup_tls for more information. */ + +# define TLS_DTV_AT_TP 1 +# define TLS_TCB_AT_TP 0 + +/* Get the thread descriptor definition. */ +# include + +/* Requirements for the TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) +# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) + +# define TLS_TCB_SIZE sizeof (tcbhead_t) +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size of the TCB. */ + +/* This is the size we need before TCB. + To support THREAD_GETMEM with friends we want to have a + struct pthread available. + Yank it in infront of everything, I'm sure nobody will mind. + + This memory is really allocated PRE the TLS block, so it's possible + to do ((char*)tlsblock) - TLS_PRE_TCB_SIZE to access it. + This is done for THREAD_SELF. */ + +# define TLS_PRE_TCB_SIZE sizeof (struct pthread) + +/* Install the dtv pointer. + When called, dtvp is a pointer not the DTV per say (which should start + with the generation counter) but to the length of the DTV. + We can always index with -1, so we store dtvp[1]. */ + +# define INSTALL_DTV(tcbp, dtvp) \ + (((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1) + +/* Install new dtv for current thread + In a logicial world dtv here would also point to the length of the DTV. + However it does not, this time it points to the generation counter, + so just store it. + + Note: -1 is still valid and contains the length. */ + +# define INSTALL_NEW_DTV(dtv) (THREAD_DTV() = (dtv)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) (((tcbhead_t *) (tcbp))->dtv) + +/* Code to initially initialize the thread pointer. + + Set TP to the address _after_ tcbhead_t. This will allow us + to change the size of tcbhead_t without having to re-link everything. + + This has to return NULL on success (or a string with the failure text). + It's hard to fail this, so return NULL always. */ + +# define TLS_INIT_TP(tcbp) \ + ({__thread_self = ((tcbhead_t *)tcbp + 1); NULL;}) + +/* Value passed to 'clone' for initialization of the thread register. */ +# define TLS_DEFINE_INIT_TP(tp, pd) \ + void *tp = ((char *) pd + TLS_PRE_TCB_SIZE + TLS_INIT_TCB_SIZE) + +/* Return the address of the dtv for the current thread. + + Dereference TP, offset to dtv - really straightforward. + Remember that we made TP point to after tcb, so we need to reverse that. */ + +# define THREAD_DTV() \ + ((((tcbhead_t *)__thread_self)-1)->dtv) + +/* Return the thread descriptor for the current thread. + + Return a pointer to the TLS_PRE area where we allocated space for + a struct pthread. Again, TP points to after tcbhead_t, compensate with + TLS_INIT_TCB_SIZE. + + I regard this is a seperate system from the "normal" TLS. */ + +# define THREAD_SELF \ + ((struct pthread *) ((char *) __thread_self - TLS_INIT_TCB_SIZE \ + - TLS_PRE_TCB_SIZE)) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ + +# define DB_THREAD_SELF \ + REGISTER (32, 32, 10 * 4, - TLS_INIT_TCB_SIZE - TLS_PRE_TCB_SIZE) + +# include + +/* Access to data in the thread descriptor is easy. */ + +#define THREAD_GETMEM(descr, member) \ + descr->member +#define THREAD_GETMEM_NC(descr, member, idx) \ + descr->member[idx] +#define THREAD_SETMEM(descr, member, value) \ + descr->member = (value) +#define THREAD_SETMEM_NC(descr, member, idx, value) \ + descr->member[idx] = (value) + +/* Get and set the global scope generation counter in struct pthread. */ + +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { \ + int __res = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag,\ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, \ + LLL_PRIVATE); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) + +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/sysdeps/or1k/stackinfo.h b/sysdeps/or1k/stackinfo.h new file mode 100644 index 0000000000..9273e709bd --- /dev/null +++ b/sysdeps/or1k/stackinfo.h @@ -0,0 +1,34 @@ +/* Stack definitions for OpenRISC. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +#include + +/* On or1k the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +/* Default to an executable stack. PF_X can be overridden if PT_GNU_STACK is + present, but it is presumed absent. */ +#define DEFAULT_STACK_PERMS (PF_R | PF_W | PF_X) + +#endif /* stackinfo.h */