On Thu, 2015-10-29 at 12:38 -0700, Richard Henderson wrote: > On 10/29/2015 11:19 AM, Torvald Riegel wrote: > > 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; > > Everything looks good except for this part. The new symbols need to go into a > new symbol version. C.f. libatomic.map for the syntax.
Ah, thanks. OK in the updated patch that's attached? I've also looked at the sized delete paper again, and we should be able to called the underlying unsized delete even if the compiler issued a call to the sized delete (ie, to answer my own question). However, it's not difficult or too much overhead to call the right version, so I'll just keep the patch the way it is.
commit 1125e1b96cddf71b907ff382898239f09410d48e Author: Torvald Riegel <trie...@redhat.com> 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..ac371de 100644 --- a/libitm/libitm.map +++ b/libitm/libitm.map @@ -182,3 +182,8 @@ LIBITM_1.0 { local: *; }; +LIBITM_1.1 { + global: + _ZGTtdlPv?; + _ZGTtdlPv?RKSt9nothrow_t; +} LIBITM_1.0; 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<uintptr_t, gtm_alloc_action>*); 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; +}