Added reference counting to segments. Synchronization objects (mutex, semaphore, barrier, rwlock) now keep a pointer to a segment instead of copying a vector clock for modeling causal relationships.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@7727 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/exp-drd/drd_segment.c b/exp-drd/drd_segment.c
index 1269563..1bb186e 100644
--- a/exp-drd/drd_segment.c
+++ b/exp-drd/drd_segment.c
@@ -46,8 +46,8 @@
// Function definitions.
-/**
- * Note: creator and created may be equal.
+/** Initialize the memory pointed at by sg.
+ * @note The creator and created thread ID's may be equal.
*/
static
void sg_init(Segment* const sg,
@@ -62,9 +62,10 @@
creator_sg = (creator != DRD_INVALID_THREADID
? thread_get_segment(creator) : 0);
-
+
sg->next = 0;
sg->prev = 0;
+ sg->refcnt = 1;
if (vg_created != VG_INVALID_THREADID && VG_(get_SP)(vg_created) != 0)
sg->stacktrace = VG_(record_ExeContext)(vg_created, 0);
@@ -82,23 +83,30 @@
{
char msg[256];
VG_(snprintf)(msg, sizeof(msg),
- "New segment for thread %d/%d with vc ",
- DrdThreadIdToVgThreadId(creator), creator);
+ "New segment for thread %d/%d for vc ",
+ creator != VG_INVALID_THREADID
+ ? DrdThreadIdToVgThreadId(creator)
+ : DRD_INVALID_THREADID,
+ creator);
vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
&sg->vc);
VG_(message)(Vg_UserMsg, "%s", msg);
}
}
+/** Deallocate the memory that was allocated by sg_init(). */
static
void sg_cleanup(Segment* const sg)
{
tl_assert(sg);
+ tl_assert(sg->refcnt == 0);
+
vc_cleanup(&sg->vc);
bm_delete(sg->bm);
sg->bm = 0;
}
+/** Allocate and initialize a new segment. */
Segment* sg_new(ThreadId const creator, ThreadId const created)
{
Segment* sg;
@@ -114,6 +122,7 @@
return sg;
}
+static
void sg_delete(Segment* const sg)
{
#if 1
@@ -135,6 +144,50 @@
VG_(free)(sg);
}
+/** Query the reference count of the specified segment. */
+int sg_get_refcnt(const Segment* const sg)
+{
+ tl_assert(sg);
+
+ return sg->refcnt;
+}
+
+/** Increment the reference count of the specified segment. */
+Segment* sg_get(Segment* const sg)
+{
+ tl_assert(sg);
+
+ sg->refcnt++;
+ return sg;
+}
+
+/** Decrement the reference count of the specified segment and deallocate the
+ * segment if the reference count became zero.
+ */
+void sg_put(Segment* const sg)
+{
+ if (sg == 0)
+ return;
+
+ if (drd_trace_segment)
+ {
+ char msg[256];
+ VG_(snprintf)(msg, sizeof(msg),
+ "Decrementing segment reference count %d -> %d with vc ",
+ sg->refcnt, sg->refcnt - 1);
+ vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
+ &sg->vc);
+ VG_(message)(Vg_UserMsg, "%s", msg);
+ }
+
+ tl_assert(sg->refcnt >= 1);
+
+ if (--sg->refcnt == 0)
+ {
+ sg_delete(sg);
+ }
+}
+
void sg_print(const Segment* const sg)
{
tl_assert(sg);