From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 33717 invoked by alias); 29 Oct 2015 18:19:43 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 33699 invoked by uid 89); 29 Oct 2015 18:19:42 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.6 required=5.0 tests=AWL,BAYES_20,RP_MATCHES_RCVD,SPF_HELO_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 29 Oct 2015 18:19:36 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (Postfix) with ESMTPS id 9D662C075D95 for ; Thu, 29 Oct 2015 18:19:35 +0000 (UTC) Received: from [10.36.6.41] (vpn1-6-41.ams2.redhat.com [10.36.6.41]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t9TIJWc5026657 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA256 bits=256 verify=NO); Thu, 29 Oct 2015 14:19:34 -0400 Message-ID: <1446142772.7192.12.camel@localhost.localdomain> Subject: [PATCH] libitm: Support sized delete. From: Torvald Riegel To: GCC Patches Cc: Jason Merrill , Richard Henderson Date: Thu, 29 Oct 2015 18:35:00 -0000 Content-Type: text/plain; charset="UTF-8" Mime-Version: 1.0 Content-Transfer-Encoding: 7bit X-IsSubscribed: yes X-SW-Source: 2015-10/txt/msg03260.txt.bz2 This patch supports the sized variants of operator delete. Tested on x86_64-linux. Is this OK or is it completely sufficient to just call non-sized operator delete from libitm even if the program has a sized delete? (If the latter is the case, I would just remove the special handling for that and use non-sized dlete under the covers.) 2015-10-29 Torvald Riegel * alloc_cpp.cc (_ZdlPvX, _ZdlPvXRKSt9nothrow_t, _ZGTtdlPvX, _ZGTtdlPvXRKSt9nothrow_t, delsz_opnt): New. * libitm.map: Add _ZGTtdlPvX and _ZGTtdlPvXRKSt9nothrow_t. * libitm_i.h (gtm_alloc_action): Add free_fn_sz, sz, sized_delete members. (gtm_thread::forget_allocations): New overload with size_t argument. * alloc.c (gtm_thread::forget_allocation): Define new overload and adapt existing one. (gtm_thread::record_allocation): Adapt. * testsuite/libitm.c++/newdelete.C: New. commit f0d6b07a62681ad3cd477cf3c75904ee22baf75e Author: Torvald Riegel Date: Thu Oct 29 18:52:20 2015 +0100 Support sized delete. This adds transactional clones of the sized version of operator delete. diff --git a/libitm/alloc.cc b/libitm/alloc.cc index bb292da..a72848d 100644 --- a/libitm/alloc.cc +++ b/libitm/alloc.cc @@ -37,6 +37,7 @@ gtm_thread::record_allocation (void *ptr, void (*free_fn)(void *)) a->free_fn = free_fn; a->allocated = true; + a->sized_delete = false; } void @@ -50,6 +51,23 @@ gtm_thread::forget_allocation (void *ptr, void (*free_fn)(void *)) a->free_fn = free_fn; a->allocated = false; + a->sized_delete = false; +} + +void +gtm_thread::forget_allocation (void *ptr, size_t sz, + void (*free_fn_sz)(void *, size_t)) +{ + uintptr_t iptr = (uintptr_t) ptr; + + gtm_alloc_action *a = this->alloc_actions.find(iptr); + if (a == 0) + a = this->alloc_actions.insert(iptr); + + a->free_fn_sz = free_fn_sz; + a->allocated = false; + a->sized_delete = true; + a->sz = sz; } namespace { @@ -102,7 +120,12 @@ commit_allocations_1 (uintptr_t key, gtm_alloc_action *a, void *cb_data) uintptr_t revert_p = (uintptr_t) cb_data; if (a->allocated == revert_p) - a->free_fn (ptr); + { + if (a->sized_delete) + a->free_fn_sz (ptr, a->sz); + else + a->free_fn (ptr); + } } /* Permanently commit allocated memory during transaction. diff --git a/libitm/alloc_cpp.cc b/libitm/alloc_cpp.cc index 8514618..13185a7 100644 --- a/libitm/alloc_cpp.cc +++ b/libitm/alloc_cpp.cc @@ -35,41 +35,50 @@ using namespace GTM; #define _ZnwX S(_Znw,MANGLE_SIZE_T) #define _ZnaX S(_Zna,MANGLE_SIZE_T) +#define _ZdlPvX S(_ZdlPv,MANGLE_SIZE_T) #define _ZnwXRKSt9nothrow_t S(S(_Znw,MANGLE_SIZE_T),RKSt9nothrow_t) #define _ZnaXRKSt9nothrow_t S(S(_Zna,MANGLE_SIZE_T),RKSt9nothrow_t) +#define _ZdlPvXRKSt9nothrow_t S(S(_ZdlPv,MANGLE_SIZE_T),RKSt9nothrow_t) #define _ZGTtnwX S(_ZGTtnw,MANGLE_SIZE_T) #define _ZGTtnaX S(_ZGTtna,MANGLE_SIZE_T) +#define _ZGTtdlPvX S(_ZGTtdlPv,MANGLE_SIZE_T) #define _ZGTtnwXRKSt9nothrow_t S(S(_ZGTtnw,MANGLE_SIZE_T),RKSt9nothrow_t) #define _ZGTtnaXRKSt9nothrow_t S(S(_ZGTtna,MANGLE_SIZE_T),RKSt9nothrow_t) +#define _ZGTtdlPvXRKSt9nothrow_t S(S(_ZGTtdlPv,MANGLE_SIZE_T),RKSt9nothrow_t) /* Everything from libstdc++ is weak, to avoid requiring that library to be linked into plain C applications using libitm.so. */ extern "C" { -extern void *_ZnwX (size_t) __attribute__((weak)); -extern void _ZdlPv (void *) __attribute__((weak)); -extern void *_ZnaX (size_t) __attribute__((weak)); -extern void _ZdaPv (void *) __attribute__((weak)); +extern void *_ZnwX (size_t) __attribute__((weak)); +extern void _ZdlPv (void *) __attribute__((weak)); +extern void _ZdlPvX (void *, size_t) __attribute__((weak)); +extern void *_ZnaX (size_t) __attribute__((weak)); +extern void _ZdaPv (void *) __attribute__((weak)); typedef const struct nothrow_t { } *c_nothrow_p; extern void *_ZnwXRKSt9nothrow_t (size_t, c_nothrow_p) __attribute__((weak)); extern void _ZdlPvRKSt9nothrow_t (void *, c_nothrow_p) __attribute__((weak)); +extern void _ZdlPvXRKSt9nothrow_t +(void *, size_t, c_nothrow_p) __attribute__((weak)); extern void *_ZnaXRKSt9nothrow_t (size_t, c_nothrow_p) __attribute__((weak)); extern void _ZdaPvRKSt9nothrow_t (void *, c_nothrow_p) __attribute__((weak)); #if !defined (HAVE_ELF_STYLE_WEAKREF) -void *_ZnwX (size_t) { return NULL; } -void _ZdlPv (void *) { return; } -void *_ZnaX (size_t) { return NULL; } -void _ZdaPv (void *) { return; } - -void *_ZnwXRKSt9nothrow_t (size_t, c_nothrow_p) { return NULL; } -void _ZdlPvRKSt9nothrow_t (void *, c_nothrow_p) { return; } -void *_ZnaXRKSt9nothrow_t (size_t, c_nothrow_p) { return NULL; } -void _ZdaPvRKSt9nothrow_t (void *, c_nothrow_p) { return; } +void *_ZnwX (size_t) { return NULL; } +void _ZdlPv (void *) { return; } +void _ZdlPvX (void *, size_t) { return; } +void *_ZnaX (size_t) { return NULL; } +void _ZdaPv (void *) { return; } + +void *_ZnwXRKSt9nothrow_t (size_t, c_nothrow_p) { return NULL; } +void _ZdlPvRKSt9nothrow_t (void *, c_nothrow_p) { return; } +void _ZdlPvXRKSt9nothrow_t (void *, size_t, c_nothrow_p) { return; } +void *_ZnaXRKSt9nothrow_t (size_t, c_nothrow_p) { return NULL; } +void _ZdaPvRKSt9nothrow_t (void *, c_nothrow_p) { return; } #endif /* HAVE_ELF_STYLE_WEAKREF */ /* Wrap the delete nothrow symbols for usage with a single argument. @@ -89,6 +98,12 @@ del_opvnt (void *ptr) _ZdaPvRKSt9nothrow_t (ptr, NULL); } +static void +delsz_opnt (void *ptr, size_t sz) +{ + _ZdlPvXRKSt9nothrow_t (ptr, sz, NULL); +} + /* Wrap: operator new (std::size_t sz) */ void * _ZGTtnwX (size_t sz) @@ -161,4 +176,20 @@ _ZGTtdaPvRKSt9nothrow_t (void *ptr, c_nothrow_p nt UNUSED) gtm_thr()->forget_allocation (ptr, del_opvnt); } +/* Wrap: operator delete(void* ptr, std::size_t sz) */ +void +_ZGTtdlPvX (void *ptr, size_t sz) +{ + if (ptr) + gtm_thr()->forget_allocation (ptr, sz, _ZdlPvX); +} + +/* Wrap: operator delete (void *ptr, std::size_t sz, const std::nothrow_t&) */ +void +_ZGTtdlPvXRKSt9nothrow_t (void *ptr, size_t sz, c_nothrow_p nt UNUSED) +{ + if (ptr) + gtm_thr()->forget_allocation (ptr, sz, delsz_opnt); +} + } // extern "C" diff --git a/libitm/libitm.map b/libitm/libitm.map index 21bcfdf..7fc9a41 100644 --- a/libitm/libitm.map +++ b/libitm/libitm.map @@ -168,10 +168,12 @@ LIBITM_1.0 { _ZGTtnw?; _ZGTtna?; _ZGTtdlPv; + _ZGTtdlPv?; _ZGTtdaPv; _ZGTtnw?RKSt9nothrow_t; _ZGTtna?RKSt9nothrow_t; _ZGTtdlPvRKSt9nothrow_t; + _ZGTtdlPv?RKSt9nothrow_t; _ZGTtdaPvRKSt9nothrow_t; _ITM_cxa_allocate_exception; diff --git a/libitm/libitm_i.h b/libitm/libitm_i.h index 0eda01b..5cc5da5 100644 --- a/libitm/libitm_i.h +++ b/libitm/libitm_i.h @@ -101,8 +101,16 @@ namespace GTM HIDDEN { // the template used inside gtm_thread can instantiate. struct gtm_alloc_action { - void (*free_fn)(void *); + // If sized_delete is false, free_fn must be used; free_fn_sz otherwise. + union + { + void (*free_fn)(void *); + void (*free_fn_sz)(void *, size_t); + }; + size_t sz; + // If allocated is true, sized_delete is false; bool allocated; + bool sized_delete; }; struct gtm_thread; @@ -269,6 +277,7 @@ struct gtm_thread void commit_allocations (bool, aa_tree*); void record_allocation (void *, void (*)(void *)); void forget_allocation (void *, void (*)(void *)); + void forget_allocation (void *, size_t, void (*)(void *, size_t)); void drop_references_allocations (const void *ptr) { this->alloc_actions.erase((uintptr_t) ptr); diff --git a/libitm/testsuite/libitm.c++/newdelete.C b/libitm/testsuite/libitm.c++/newdelete.C new file mode 100644 index 0000000..10eba4f --- /dev/null +++ b/libitm/testsuite/libitm.c++/newdelete.C @@ -0,0 +1,12 @@ +// { dg-do run } + +int main () +{ + atomic_commit { + int* data = new int; + delete data; + data = new int[10]; + delete[] data; + } + return 0; +}