This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] libitm: Support sized delete.
- From: Torvald Riegel <triegel at redhat dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Cc: Jason Merrill <jason at redhat dot com>, Richard Henderson <rth at redhat dot com>
- Date: Thu, 29 Oct 2015 19:19:32 +0100
- Subject: [PATCH] libitm: Support sized delete.
- Authentication-results: sourceware.org; auth=none
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 <triegel@redhat.com>
* 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 <triegel@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..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<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;
+}