From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-qk1-x732.google.com (mail-qk1-x732.google.com [IPv6:2607:f8b0:4864:20::732]) by sourceware.org (Postfix) with ESMTPS id 1CBB13858020 for ; Thu, 15 Apr 2021 18:21:52 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 1CBB13858020 Received: by mail-qk1-x732.google.com with SMTP id 18so9349930qkl.3 for ; Thu, 15 Apr 2021 11:21:52 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=MEvYNDrCHSho8YHIwTFAl120uS83cbTjm8PHqI79tDA=; b=PVnS4q+r9vhNRigbj2GZj8tZrsS/3eoPa/8AjEI1vnkKXDqpfwFU5uJmbc7lX5rKRP dsZzGW8avDkPdUwe1LfghF9olv131UkdOyMOkgk65xDFNFojqoYGJtjK3+Lb0SKBfJB1 egg+F9EfQ5HR25ifmMpoclo44wahnR/uikT+JjpRls7ZXwV7edq3CxLEqUkstP5ylzp9 q2dbK6JJQMC0PGXaUvEF9jRBNpR0+MjqEPBtzFly5/rKRlQWCHzKbVKkZL8mu884iixd 1JHHVsHW6MWmACOBqH09/m27goPvB7A6+AcvTJ7PzQFla7Mr3RYt976kLPPdGMbhMg3b I5/g== X-Gm-Message-State: AOAM532KlEaEYlUPLyKW5H2CJmO/2YMYjmeosMzDlS1xmQXB14GwG4hq HE4wuIVBJmnxLTmgm6RdJU9GoQ== X-Google-Smtp-Source: ABdhPJxX1k2z/5ytKwsMPm8ssMDP5qtPnEHz+NOOCjp7ikV4fsaEoFyxEfPxs4wzOt0UiCZAk1N13g== X-Received: by 2002:a37:7043:: with SMTP id l64mr4628147qkc.358.1618510911440; Thu, 15 Apr 2021 11:21:51 -0700 (PDT) Received: from [192.168.1.132] ([177.194.41.149]) by smtp.gmail.com with ESMTPSA id t63sm2561585qkh.6.2021.04.15.11.21.50 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 15 Apr 2021 11:21:51 -0700 (PDT) Subject: Re: [PATCH v2 06/14] elf: Use relaxed atomics for racy accesses [BZ #19329] To: libc-alpha@sourceware.org, Szabolcs Nagy References: <10fb15a36b3f6bc3e5ca62cda081c86512f47d32.1618301209.git.szabolcs.nagy@arm.com> From: Adhemerval Zanella Message-ID: <37965321-dec2-f901-325c-ac4bad72484f@linaro.org> Date: Thu, 15 Apr 2021 15:21:48 -0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.7.1 MIME-Version: 1.0 In-Reply-To: <10fb15a36b3f6bc3e5ca62cda081c86512f47d32.1618301209.git.szabolcs.nagy@arm.com> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-12.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, NICE_REPLY_A, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) 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-List-Received-Date: Thu, 15 Apr 2021 18:21:53 -0000 On 13/04/2021 05:19, Szabolcs Nagy via Libc-alpha wrote: > This is a follow up patch to the fix for bug 19329. This adds > relaxed MO atomics to accesses that are racy, but relaxed MO is > enough. Could you extend a bit why relaxed MO should be suffice? Patch looks good, just a small request below. Reviewed-by: Adhemerval Zanella > > -- > v2: > - handle x86_64 dl-tls.c too > --- > elf/dl-close.c | 20 +++++++++++++------- > elf/dl-open.c | 5 ++++- > elf/dl-tls.c | 31 +++++++++++++++++++++++-------- > sysdeps/x86_64/dl-tls.c | 3 ++- > 4 files changed, 42 insertions(+), 17 deletions(-) > > diff --git a/elf/dl-close.c b/elf/dl-close.c > index c51becd06b..3720e47dd1 100644 > --- a/elf/dl-close.c > +++ b/elf/dl-close.c > @@ -79,9 +79,10 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp, > { > assert (old_map->l_tls_modid == idx); > > - /* Mark the entry as unused. */ > - listp->slotinfo[idx - disp].gen = GL(dl_tls_generation) + 1; > - listp->slotinfo[idx - disp].map = NULL; > + /* Mark the entry as unused. These can be read concurrently. */ > + atomic_store_relaxed (&listp->slotinfo[idx - disp].gen, > + GL(dl_tls_generation) + 1); > + atomic_store_relaxed (&listp->slotinfo[idx - disp].map, NULL); > } > > /* If this is not the last currently used entry no need to look Ok. > @@ -96,8 +97,8 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp, > > if (listp->slotinfo[idx - disp].map != NULL) > { > - /* Found a new last used index. */ > - GL(dl_tls_max_dtv_idx) = idx; > + /* Found a new last used index. This can be read concurrently. */ > + atomic_store_relaxed (&GL(dl_tls_max_dtv_idx), idx); > return true; > } > } Ok. > @@ -571,7 +572,9 @@ _dl_close_worker (struct link_map *map, bool force) > GL(dl_tls_dtv_slotinfo_list), 0, > imap->l_init_called)) > /* All dynamically loaded modules with TLS are unloaded. */ > - GL(dl_tls_max_dtv_idx) = GL(dl_tls_static_nelem); > + /* Can be read concurrently. */ > + atomic_store_relaxed (&GL(dl_tls_max_dtv_idx), > + GL(dl_tls_static_nelem)); > > if (imap->l_tls_offset != NO_TLS_OFFSET > && imap->l_tls_offset != FORCED_DYNAMIC_TLS_OFFSET) Ok. > @@ -769,8 +772,11 @@ _dl_close_worker (struct link_map *map, bool force) > /* If we removed any object which uses TLS bump the generation counter. */ > if (any_tls) > { > - if (__glibc_unlikely (++GL(dl_tls_generation) == 0)) > + size_t newgen = GL(dl_tls_generation) + 1; > + if (__glibc_unlikely (newgen == 0)) > _dl_fatal_printf ("TLS generation counter wrapped! Please report as described in "REPORT_BUGS_TO".\n"); > + /* Can be read concurrently. */ > + atomic_store_relaxed (&GL(dl_tls_generation), newgen); > > if (tls_free_end == GL(dl_tls_static_used)) > GL(dl_tls_static_used) = tls_free_start; Ok. > diff --git a/elf/dl-open.c b/elf/dl-open.c > index ab7aaa345e..83b8e96a5c 100644 > --- a/elf/dl-open.c > +++ b/elf/dl-open.c > @@ -395,9 +395,12 @@ update_tls_slotinfo (struct link_map *new) > } > } > > - if (__builtin_expect (++GL(dl_tls_generation) == 0, 0)) > + size_t newgen = GL(dl_tls_generation) + 1; > + if (__builtin_expect (newgen == 0, 0)) > _dl_fatal_printf (N_("\ Use __glibc_unlikely since you are modifying it. > TLS generation counter wrapped! Please report this.")); > + /* Can be read concurrently. */ > + atomic_store_relaxed (&GL(dl_tls_generation), newgen); > > /* We need a second pass for static tls data, because > _dl_update_slotinfo must not be run while calls to Ok. > diff --git a/elf/dl-tls.c b/elf/dl-tls.c > index 33c06782b1..c4466bd9fc 100644 > --- a/elf/dl-tls.c > +++ b/elf/dl-tls.c > @@ -175,7 +175,9 @@ _dl_next_tls_modid (void) > /* No gaps, allocate a new entry. */ > nogaps: > > - result = ++GL(dl_tls_max_dtv_idx); > + result = GL(dl_tls_max_dtv_idx) + 1; > + /* Can be read concurrently. */ > + atomic_store_relaxed (&GL(dl_tls_max_dtv_idx), result); > } > > return result; Ok. > @@ -359,10 +361,12 @@ allocate_dtv (void *result) > dtv_t *dtv; > size_t dtv_length; > > + /* Relaxed MO, because the dtv size is later rechecked, not relied on. */ > + size_t max_modid = atomic_load_relaxed (&GL(dl_tls_max_dtv_idx)); > /* We allocate a few more elements in the dtv than are needed for the > initial set of modules. This should avoid in most cases expansions > of the dtv. */ > - dtv_length = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS; > + dtv_length = max_modid + DTV_SURPLUS; > dtv = calloc (dtv_length + 2, sizeof (dtv_t)); > if (dtv != NULL) > { Ok. > @@ -767,7 +771,7 @@ _dl_update_slotinfo (unsigned long int req_modid) > if (modid > max_modid) > break; > > - size_t gen = listp->slotinfo[cnt].gen; > + size_t gen = atomic_load_relaxed (&listp->slotinfo[cnt].gen); > > if (gen > new_gen) > /* Not relevant. */ Ok. > @@ -779,7 +783,8 @@ _dl_update_slotinfo (unsigned long int req_modid) > continue; > > /* If there is no map this means the entry is empty. */ > - struct link_map *map = listp->slotinfo[cnt].map; > + struct link_map *map > + = atomic_load_relaxed (&listp->slotinfo[cnt].map); > /* Check whether the current dtv array is large enough. */ > if (dtv[-1].counter < modid) > { OK. > @@ -923,7 +928,12 @@ __tls_get_addr (GET_ADDR_ARGS) > { > dtv_t *dtv = THREAD_DTV (); > > - if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation))) > + /* Update is needed if dtv[0].counter < the generation of the accessed > + module. The global generation counter is used here as it is easier > + to check. Synchronization for the relaxed MO access is guaranteed > + by user code, see CONCURRENCY NOTES in _dl_update_slotinfo. */ > + size_t gen = atomic_load_relaxed (&GL(dl_tls_generation)); > + if (__glibc_unlikely (dtv[0].counter != gen)) > return update_get_addr (GET_ADDR_PARAM); > > void *p = dtv[GET_ADDR_MODULE].pointer.val; Ok. > @@ -946,7 +956,10 @@ _dl_tls_get_addr_soft (struct link_map *l) > return NULL; > > dtv_t *dtv = THREAD_DTV (); > - if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation))) > + /* This may be called without holding the GL(dl_load_lock). Reading > + arbitrary gen value is fine since this is best effort code. */ > + size_t gen = atomic_load_relaxed (&GL(dl_tls_generation)); > + if (__glibc_unlikely (dtv[0].counter != gen)) > { > /* This thread's DTV is not completely current, > but it might already cover this module. */ Ok. > @@ -1032,7 +1045,9 @@ cannot create TLS data structures")); > /* Add the information into the slotinfo data structure. */ > if (do_add) > { > - listp->slotinfo[idx].map = l; > - listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1; > + /* Can be read concurrently. See _dl_update_slotinfo. */ > + atomic_store_relaxed (&listp->slotinfo[idx].map, l); > + atomic_store_relaxed (&listp->slotinfo[idx].gen, > + GL(dl_tls_generation) + 1); > } > } Ok. > diff --git a/sysdeps/x86_64/dl-tls.c b/sysdeps/x86_64/dl-tls.c > index 6595f6615b..24ef560b71 100644 > --- a/sysdeps/x86_64/dl-tls.c > +++ b/sysdeps/x86_64/dl-tls.c > @@ -40,7 +40,8 @@ __tls_get_addr_slow (GET_ADDR_ARGS) > { > dtv_t *dtv = THREAD_DTV (); > > - if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation))) > + size_t gen = atomic_load_relaxed (&GL(dl_tls_generation)); > + if (__glibc_unlikely (dtv[0].counter != gen)) > return update_get_addr (GET_ADDR_PARAM); > > return tls_get_addr_tail (GET_ADDR_PARAM, dtv, NULL); > Ok. X86_64 also access dl_tls_generation on sysdeps/x86_64/tls_get_addr.S, but I afaik the default memory ordering for x86_64 already guarantee relaxed MO.