===================================================================
@@ -57,4 +57,15 @@ _ITM_free (void *ptr)
gtm_tx()->forget_allocation (ptr, free);
}
+/* Forget any internal references to PTR. */
+
+__attribute__((transaction_pure))
+void ITM_REGPARM
+_ITM_dropReferences (const void *ptr, size_t len)
+{
+ gtm_transaction *tx = gtm_tx();
+ tx->drop_references_local (ptr, len);
+ tx->drop_references_allocations (ptr);
+}
+
} // extern "C"
===================================================================
@@ -167,6 +167,7 @@ LIBITM_1.0 {
_ITM_malloc;
_ITM_calloc;
_ITM_free;
+ _ITM_dropReferences;
_ZGTtnwm;
_ZGTtnam;
===================================================================
@@ -152,6 +152,7 @@ extern void _ITM_addUserUndoAction(_ITM_
extern int _ITM_getThreadnum(void) ITM_REGPARM;
+__attribute__((transaction_pure))
extern void _ITM_dropReferences (const void *, size_t) ITM_REGPARM;
===================================================================
@@ -33,7 +33,10 @@ gtm_transaction::record_allocation (void
gtm_alloc_action *a = this->alloc_actions.find(iptr);
if (a == 0)
- a = this->alloc_actions.insert(iptr);
+ {
+ a = this->alloc_actions.insert(iptr);
+ a->ignore = false;
+ }
a->free_fn = free_fn;
a->allocated = true;
@@ -46,7 +49,10 @@ gtm_transaction::forget_allocation (void
gtm_alloc_action *a = this->alloc_actions.find(iptr);
if (a == 0)
- a = this->alloc_actions.insert(iptr);
+ {
+ a = this->alloc_actions.insert(iptr);
+ a->ignore = false;
+ }
a->free_fn = free_fn;
a->allocated = false;
@@ -58,6 +64,9 @@ commit_allocations_1 (uintptr_t key, gtm
void *ptr = (void *)key;
uintptr_t revert_p = (uintptr_t) cb_data;
+ if (a->ignore)
+ return;
+
if (a->allocated == revert_p)
a->free_fn (ptr);
}
@@ -74,4 +83,24 @@ gtm_transaction::commit_allocations (boo
this->alloc_actions.clear ();
}
+/* Forget any references to PTR in the allocations tree.
+
+ ?? We ignore the chunk length. Pray this doesn't wreck havoc. */
+
+void
+gtm_transaction::drop_references_allocations (const void *ptr)
+{
+ 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 = NULL;
+ a->allocated = false;
+ }
+
+ a->ignore = true;
+}
+
} // namespace GTM
===================================================================
@@ -0,0 +1,11 @@
+#include <libitm.h>
+
+char *pp;
+
+int main()
+{
+ __transaction {
+ _ITM_dropReferences (pp, 555);
+ }
+ return 0;
+}
===================================================================
@@ -0,0 +1,11 @@
+#include <libitm.h>
+
+char *pp;
+
+int main()
+{
+ __transaction {
+ _ITM_dropReferences (pp, 555);
+ }
+ return 0;
+}
===================================================================
@@ -155,6 +155,7 @@ struct gtm_alloc_action
{
void (*free_fn)(void *);
bool allocated;
+ bool ignore;
};
// This type is private to local.c.
@@ -226,6 +227,7 @@ struct gtm_transaction
void commit_allocations (bool);
void record_allocation (void *, void (*)(void *));
void forget_allocation (void *, void (*)(void *));
+ void drop_references_allocations (const void *);
// In beginend.cc
void rollback ();
@@ -247,6 +249,7 @@ struct gtm_transaction
// In local.cc
void commit_local (void);
void rollback_local (void);
+ void drop_references_local (const void *, size_t);
// In retry.cc
void decide_retry_strategy (gtm_restart_reason);
===================================================================
@@ -30,6 +30,7 @@ struct gtm_local_undo
{
void *addr;
size_t len;
+ bool ignore;
char saved[];
};
@@ -65,13 +66,36 @@ gtm_transaction::rollback_local (void)
for (i = n; i-- > 0; )
{
gtm_local_undo *u = local_undo[i];
- memcpy (u->addr, u->saved, u->len);
+ if (!u->ignore)
+ memcpy (u->addr, u->saved, u->len);
free (u);
}
this->n_local_undo = 0;
}
}
+/* Forget any references to PTR in the local log. */
+
+void
+gtm_transaction::drop_references_local (const void *ptr, size_t len)
+{
+ gtm_local_undo **local_undo = this->local_undo;
+ size_t i, n = this->n_local_undo;
+
+ if (n > 0)
+ {
+ for (i = n; i > 0; i--)
+ {
+ gtm_local_undo *u = local_undo[i];
+ /* ?? Do we need such granularity, or can we get away with
+ just comparing PTR and LEN. ?? */
+ if ((const char *)u->addr >= (const char *)ptr
+ && ((const char *)u->addr + u->len <= (const char *)ptr + len))
+ u->ignore = true;
+ }
+ }
+}
+
void ITM_REGPARM
GTM_LB (const void *ptr, size_t len)
{
@@ -81,6 +105,7 @@ GTM_LB (const void *ptr, size_t len)
undo = (gtm_local_undo *) xmalloc (sizeof (struct gtm_local_undo) + len);
undo->addr = (void *) ptr;
undo->len = len;
+ undo->ignore = false;
if (tx->local_undo == NULL)
{