{
UWord tid; // A DrdThreadId declared as UWord because
// this member variable is the key of an OSet.
- Segment* sg[2]; // Segments of the last two
- // pthread_barrier() calls by thread tid.
- ExeContext* wait_call_ctxt;// call stack for *_barrier_wait() call.
+ Segment* sg; // Segment of the last pthread_barrier() call
+ // by thread tid.
Segment* post_wait_sg; // Segment created after *_barrier_wait() finished
+ ExeContext* wait_call_ctxt;// call stack for *_barrier_wait() call.
+ Bool thread_finished;// Whether thread 'tid' has finished.
};
void DRD_(barrier_thread_initialize)(struct barrier_thread_info* const p,
const DrdThreadId tid)
{
- p->tid = tid;
- p->sg[0] = 0;
- p->sg[1] = 0;
- p->wait_call_ctxt = 0;
- p->post_wait_sg = 0;
+ p->tid = tid;
+ p->sg = NULL;
+ p->post_wait_sg = 0;
+ p->wait_call_ctxt = 0;
+ p->thread_finished = False;
}
/**
static void DRD_(barrier_thread_destroy)(struct barrier_thread_info* const p)
{
tl_assert(p);
- DRD_(sg_put)(p->sg[0]);
- DRD_(sg_put)(p->sg[1]);
+ DRD_(sg_put)(p->sg);
DRD_(sg_put)(p->post_wait_sg);
}
const BarrierT barrier_type,
const Word count)
{
+ int i;
+
tl_assert(barrier != 0);
tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier);
tl_assert(p->a1 == barrier);
tl_assert(sizeof(((struct barrier_thread_info*)0)->tid) == sizeof(Word));
tl_assert(sizeof(((struct barrier_thread_info*)0)->tid)
>= sizeof(DrdThreadId));
- p->oset = VG_(OSetGen_Create)(0, 0, VG_(malloc), "drd.barrier.bi.1",
- VG_(free));
+ for (i = 0; i < 2; i++) {
+ p->oset[i] = VG_(OSetGen_Create)(0, 0, VG_(malloc), "drd.barrier.bi.1",
+ VG_(free));
+ }
}
/**
{
struct barrier_thread_info* q;
Segment* latest_sg = 0;
+ OSet* oset;
+ int i;
tl_assert(p);
- if (p->pre_waiters_left != p->count)
- {
+ DRD_(thread_get_latest_segment)(&latest_sg, DRD_(thread_get_running_tid)());
+ tl_assert(latest_sg);
+
+ if (p->pre_waiters_left != p->count) {
BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 };
VG_(maybe_record_error)(VG_(get_running_tid)(),
BarrierErr,
"Destruction of barrier that is being waited"
" upon",
&bei);
- }
-
- DRD_(thread_get_latest_segment)(&latest_sg, DRD_(thread_get_running_tid)());
- tl_assert(latest_sg);
-
- VG_(OSetGen_ResetIter)(p->oset);
- for ( ; (q = VG_(OSetGen_Next)(p->oset)) != 0; )
- {
- if (q->post_wait_sg
- && ! DRD_(vc_lte)(&q->post_wait_sg->vc, &latest_sg->vc))
- {
- barrier_report_wait_delete_race(p, q);
+ } else {
+ oset = p->oset[1 - p->pre_iteration];
+ VG_(OSetGen_ResetIter)(oset);
+ for ( ; (q = VG_(OSetGen_Next)(oset)) != 0; ) {
+ if (q->post_wait_sg && !DRD_(vc_lte)(&q->post_wait_sg->vc,
+ &latest_sg->vc))
+ {
+ barrier_report_wait_delete_race(p, q);
+ }
+ DRD_(barrier_thread_destroy)(q);
}
+ }
- DRD_(barrier_thread_destroy)(q);
+ for (i = 0; i < 2; i++) {
+ VG_(OSetGen_Destroy)(p->oset[i]);
+ p->oset[i] = NULL;
}
- VG_(OSetGen_Destroy)(p->oset);
DRD_(sg_put)(latest_sg);
}
}
/**
- * Look up the address of the information associated with the client-side
- * barrier object.
+ * Look up the address of the struct barrier_info associated with the
+ * client-side barrier object.
*/
static struct barrier_info* DRD_(barrier_get)(const Addr barrier)
{
}
/**
- * Initialize a barrier with client address barrier, client size size, and
- * where count threads participate in each barrier.
+ * Initialize a barrier with given client address, barrier type and number of
+ * participants. The 'reinitialization' argument indicates whether a barrier
+ * object is being initialized or reinitialized.
*
* Called before pthread_barrier_init().
*/
&bei);
}
}
+
p = DRD_(barrier_get_or_allocate)(barrier, barrier_type, count);
if (s_trace_barrier)
struct barrier_info* p;
struct barrier_thread_info* q;
const UWord word_tid = tid;
+ OSet* oset;
p = DRD_(barrier_get)(barrier);
if (p == 0 && barrier_type == gomp_barrier)
p->pre_iteration);
}
+ /* Clean up nodes associated with finished threads. */
+ oset = p->oset[p->pre_iteration];
+ tl_assert(oset);
+ VG_(OSetGen_ResetIter)(oset);
+ for ( ; (q = VG_(OSetGen_Next)(oset)) != 0; ) {
+ if (q->thread_finished) {
+ void* r = VG_(OSetGen_Remove)(oset, &q->tid);
+ tl_assert(r == q);
+ DRD_(barrier_thread_destroy)(q);
+ VG_(OSetGen_FreeNode)(oset, q);
+ VG_(OSetGen_ResetIterAt)(oset, &word_tid);
+ }
+ }
/* Allocate the per-thread data structure if necessary. */
- q = VG_(OSetGen_Lookup)(p->oset, &word_tid);
- if (q == 0)
- {
- q = VG_(OSetGen_AllocNode)(p->oset, sizeof(*q));
+ q = VG_(OSetGen_Lookup)(oset, &word_tid);
+ if (q == NULL) {
+ q = VG_(OSetGen_AllocNode)(oset, sizeof(*q));
DRD_(barrier_thread_initialize)(q, tid);
- VG_(OSetGen_Insert)(p->oset, q);
- tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q);
+ VG_(OSetGen_Insert)(oset, q);
+ tl_assert(VG_(OSetGen_Lookup)(oset, &word_tid) == q);
}
/* Record *_barrier_wait() call context. */
* Store a pointer to the latest segment of the current thread in the
* per-thread data structure.
*/
- DRD_(thread_get_latest_segment)(&q->sg[p->pre_iteration], tid);
+ DRD_(thread_get_latest_segment)(&q->sg, tid);
/*
* If the same number of threads as the barrier count indicates have
const UWord word_tid = tid;
struct barrier_thread_info* q;
struct barrier_thread_info* r;
+ OSet* oset;
p = DRD_(barrier_get)(barrier);
if (! waited)
return;
- q = VG_(OSetGen_Lookup)(p->oset, &word_tid);
+ oset = p->oset[p->post_iteration];
+ q = VG_(OSetGen_Lookup)(oset, &word_tid);
if (q == 0)
{
BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 };
" barrier_destroy()",
&bei);
- q = VG_(OSetGen_AllocNode)(p->oset, sizeof(*q));
+ q = VG_(OSetGen_AllocNode)(oset, sizeof(*q));
DRD_(barrier_thread_initialize)(q, tid);
- VG_(OSetGen_Insert)(p->oset, q);
- tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q);
+ VG_(OSetGen_Insert)(oset, q);
+ tl_assert(VG_(OSetGen_Lookup)(oset, &word_tid) == q);
}
/* Create a new segment and store a pointer to that segment. */
VectorClock old_vc;
DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[tid].last->vc);
- VG_(OSetGen_ResetIter)(p->oset);
- for ( ; (r = VG_(OSetGen_Next)(p->oset)) != 0; )
+ VG_(OSetGen_ResetIter)(oset);
+ for ( ; (r = VG_(OSetGen_Next)(oset)) != 0; )
{
if (r != q)
{
- tl_assert(r->sg[p->post_iteration]);
+ tl_assert(r->sg);
DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc,
- &r->sg[p->post_iteration]->vc);
+ &r->sg->vc);
}
}
DRD_(thread_update_conflict_set)(tid, &old_vc);
{
struct barrier_thread_info* q;
const UWord word_tid = tid;
+ int i;
- q = VG_(OSetGen_Remove)(p->oset, &word_tid);
-
- /*
- * q is only non-zero if the barrier object has been used by thread tid
- * after the barrier_init() call and before the thread finished.
- */
- if (q)
- {
- DRD_(barrier_thread_destroy)(q);
- VG_(OSetGen_FreeNode)(p->oset, q);
+ for (i = 0; i < 2; i++) {
+ q = VG_(OSetGen_Lookup)(p->oset[i], &word_tid);
+ if (q)
+ q->thread_finished = True;
}
}