From patchwork Mon Feb 12 18:50:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 872308 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-473096-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="q26Bldko"; dkim-atps=neutral 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 3zgF9V1b0sz9sPk for ; Tue, 13 Feb 2018 05:50:36 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=k1o5rYQbdR6ImmxGKV5FwoFIQPYfkjg79PPY/Ny6t4c9lW n7atkJKzXFPkIY6nRDaxDhc7BOKJw9MCoQtQq9TyEx/Trd6dJrOaiQmX737QfX1l d0QauOkUbHWriMa5kKR3RH5fx/LNW6jTTiMC1wz+Yt5wZ2ir5eRUdhO1dn4hw= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; s= default; bh=dgrJQUK5mM/DF2++qf86nWnmRsE=; b=q26Bldkoptje7TqAPWnP Qp5EvLGdwxGExFjJvYKK70/uAIq3xl7jY0Wduj928ac431bllY5cOXozSyp9W+B2 Dtmh0PeW+ZAcZHQ4ruJqO+o+f7N7NvGJ0DlHC3nzcKP/M80gnxDyqN46/3TTOgmZ wOxKt+qYL9uu0XaO0DepkDY= Received: (qmail 96357 invoked by alias); 12 Feb 2018 18:50:29 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 96346 invoked by uid 89); 12 Feb 2018 18:50:28 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-11.0 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=linkname, rights, reserved X-HELO: mail-wm0-f54.google.com Received: from mail-wm0-f54.google.com (HELO mail-wm0-f54.google.com) (74.125.82.54) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 12 Feb 2018 18:50:26 +0000 Received: by mail-wm0-f54.google.com with SMTP id r71so11495022wmd.1 for ; Mon, 12 Feb 2018 10:50:26 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=czuMO4jyJbOvVBh2uLbUl+r+Okr3oZLNuUtbo6kDkhU=; b=tXhJHIJ8NxUTatULj5Au9lhCIXDYD1ZCTIJa03kA/kzHAQ6bAEgNJE43HUEpdYBg8F E/fZ47d18rPjARht4Uv17PEzCD7b+W/AXAdmHd6NDF8DV//Eb2407OBu3PGq5S6dIEem D29ik/04Avsn7ChCcjqNjnnhbp6r6YoQxxiilu60g3gnqy/aKspuXtdog8DafC9XlzNZ u5/RVAP70DzTrxNaNLNQALGuSnRmI87t7eTI7VJRMmu1QfgcxGuTCO8zU6nOla3L1ij9 35IjlkaZrnkTFqshBaoi+gDhU9v/owKSKWBOzDG2Lj2Bs7QYn+2dCnEOKka4P9IuWVKU HYuQ== X-Gm-Message-State: APf1xPDi7OSCsyW3+PBd9o3UD5dOIHB4kkg9doFQ/iqyCwW4nlxjc1qP +oSTO7uvGiVly08B8XHGzK59fwUGi76VqfVGJSxZa2r7 X-Google-Smtp-Source: AH8x225RIk+rDHa3P7unt+1S91pIEMIkxxn5d9kmYG50F97HFgdITA7hhrmETbhTTtBEEc+ffL2ViB6iU17C6VrC2sg= X-Received: by 10.80.215.146 with SMTP id w18mr17551763edi.208.1518461424490; Mon, 12 Feb 2018 10:50:24 -0800 (PST) MIME-Version: 1.0 Received: by 10.80.148.168 with HTTP; Mon, 12 Feb 2018 10:50:23 -0800 (PST) From: Ian Lance Taylor Date: Mon, 12 Feb 2018 10:50:23 -0800 Message-ID: Subject: libgo patch committed: Use write barrier for atomic pointer functions To: gcc-patches , gofrontend-dev@googlegroups.com This patch to the Go frontend uses a write barrier for atomic pointer functions. This copies atomic_pointer.go from 1.10rc2. It was omitted during the transition of the runtime from C to Go, and I forgot about it. This may help with PR 84215; I'm not sure since I haven't been able to recreate the problems described there. Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu. Committed to mainline. Ian Index: gcc/go/gofrontend/MERGE =================================================================== --- gcc/go/gofrontend/MERGE (revision 257540) +++ gcc/go/gofrontend/MERGE (working copy) @@ -1,4 +1,4 @@ -89105404f94005ffa8e2b08df78015dc9ac91362 +cebdbf3f293f5b0f3120c009c47da0ceadc113cb The first line of this file holds the git revision number of the last merge done from the gofrontend repository. Index: libgo/go/runtime/atomic_pointer.go =================================================================== --- libgo/go/runtime/atomic_pointer.go (nonexistent) +++ libgo/go/runtime/atomic_pointer.go (working copy) @@ -0,0 +1,69 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime + +import ( + "runtime/internal/atomic" + "unsafe" +) + +// These functions cannot have go:noescape annotations, +// because while ptr does not escape, new does. +// If new is marked as not escaping, the compiler will make incorrect +// escape analysis decisions about the pointer value being stored. +// Instead, these are wrappers around the actual atomics (casp1 and so on) +// that use noescape to convey which arguments do not escape. + +// atomicstorep performs *ptr = new atomically and invokes a write barrier. +// +//go:nosplit +func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) { + writebarrierptr_prewrite((*uintptr)(ptr), uintptr(new)) + atomic.StorepNoWB(noescape(ptr), new) +} + +//go:nosplit +func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool { + // The write barrier is only necessary if the CAS succeeds, + // but since it needs to happen before the write becomes + // public, we have to do it conservatively all the time. + writebarrierptr_prewrite((*uintptr)(unsafe.Pointer(ptr)), uintptr(new)) + return atomic.Casp1((*unsafe.Pointer)(noescape(unsafe.Pointer(ptr))), noescape(old), new) +} + +// Like above, but implement in terms of sync/atomic's uintptr operations. +// We cannot just call the runtime routines, because the race detector expects +// to be able to intercept the sync/atomic forms but not the runtime forms. + +//go:linkname sync_atomic_StoreUintptr sync_atomic.StoreUintptr +func sync_atomic_StoreUintptr(ptr *uintptr, new uintptr) + +//go:linkname sync_atomic_StorePointer sync_atomic.StorePointer +//go:nosplit +func sync_atomic_StorePointer(ptr *unsafe.Pointer, new unsafe.Pointer) { + writebarrierptr_prewrite((*uintptr)(unsafe.Pointer(ptr)), uintptr(new)) + sync_atomic_StoreUintptr((*uintptr)(unsafe.Pointer(ptr)), uintptr(new)) +} + +//go:linkname sync_atomic_SwapUintptr sync_atomic.SwapUintptr +func sync_atomic_SwapUintptr(ptr *uintptr, new uintptr) uintptr + +//go:linkname sync_atomic_SwapPointer sync_atomic.SwapPointer +//go:nosplit +func sync_atomic_SwapPointer(ptr *unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer { + writebarrierptr_prewrite((*uintptr)(unsafe.Pointer(ptr)), uintptr(new)) + old := unsafe.Pointer(sync_atomic_SwapUintptr((*uintptr)(noescape(unsafe.Pointer(ptr))), uintptr(new))) + return old +} + +//go:linkname sync_atomic_CompareAndSwapUintptr sync_atomic.CompareAndSwapUintptr +func sync_atomic_CompareAndSwapUintptr(ptr *uintptr, old, new uintptr) bool + +//go:linkname sync_atomic_CompareAndSwapPointer sync_atomic.CompareAndSwapPointer +//go:nosplit +func sync_atomic_CompareAndSwapPointer(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool { + writebarrierptr_prewrite((*uintptr)(unsafe.Pointer(ptr)), uintptr(new)) + return sync_atomic_CompareAndSwapUintptr((*uintptr)(noescape(unsafe.Pointer(ptr))), uintptr(old), uintptr(new)) +} Index: libgo/go/runtime/stubs.go =================================================================== --- libgo/go/runtime/stubs.go (revision 257527) +++ libgo/go/runtime/stubs.go (working copy) @@ -5,7 +5,6 @@ package runtime import ( - "runtime/internal/atomic" "runtime/internal/sys" "unsafe" ) @@ -307,15 +306,6 @@ func setSupportAES(v bool) { support_aes = v } -// Here for gccgo until we port atomic_pointer.go and mgc.go. -//go:nosplit -func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool { - if !atomic.Casp1((*unsafe.Pointer)(noescape(unsafe.Pointer(ptr))), noescape(old), new) { - return false - } - return true -} - // Here for gccgo until we port lock_*.go. func lock(l *mutex) func unlock(l *mutex) @@ -347,12 +337,6 @@ func persistentalloc(size, align uintptr // Temporary for gccgo until we port mheap.go func setprofilebucket(p unsafe.Pointer, b *bucket) -// Temporary for gccgo until we port atomic_pointer.go. -//go:nosplit -func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) { - atomic.StorepNoWB(noescape(ptr), new) -} - // Get signal trampoline, written in C. func getSigtramp() uintptr Index: libgo/go/sync/atomic/atomic.c =================================================================== --- libgo/go/sync/atomic/atomic.c (revision 257527) +++ libgo/go/sync/atomic/atomic.c (working copy) @@ -62,16 +62,6 @@ SwapUintptr (uintptr_t *addr, uintptr_t return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST); } -void *SwapPointer (void **, void *) - __asm__ (GOSYM_PREFIX "sync_atomic.SwapPointer") - __attribute__ ((no_split_stack)); - -void * -SwapPointer (void **addr, void *new) -{ - return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST); -} - _Bool CompareAndSwapInt32 (int32_t *, int32_t, int32_t) __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapInt32") __attribute__ ((no_split_stack)); @@ -126,16 +116,6 @@ CompareAndSwapUintptr (uintptr_t *val, u return __sync_bool_compare_and_swap (val, old, new); } -_Bool CompareAndSwapPointer (void **, void *, void *) - __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapPointer") - __attribute__ ((no_split_stack)); - -_Bool -CompareAndSwapPointer (void **val, void *old, void *new) -{ - return __sync_bool_compare_and_swap (val, old, new); -} - int32_t AddInt32 (int32_t *, int32_t) __asm__ (GOSYM_PREFIX "sync_atomic.AddInt32") __attribute__ ((no_split_stack)); @@ -355,19 +335,5 @@ StoreUintptr (uintptr_t *addr, uintptr_t v = *addr; while (! __sync_bool_compare_and_swap (addr, v, val)) - v = *addr; -} - -void StorePointer (void **addr, void *val) - __asm__ (GOSYM_PREFIX "sync_atomic.StorePointer") - __attribute__ ((no_split_stack)); - -void -StorePointer (void **addr, void *val) -{ - void *v; - - v = *addr; - while (! __sync_bool_compare_and_swap (addr, v, val)) v = *addr; }