Ejemplo n.º 1
0
/** Called after pthread_barrier_destroy() / gomp_barrier_destroy(). */
void DRD_(barrier_destroy)(const Addr barrier, const BarrierT barrier_type)
{
    struct barrier_info* p;

    p = DRD_(barrier_get)(barrier);

    if (s_trace_barrier)
    {
        VG_(message)(Vg_UserMsg,
                     "[%d] barrier_destroy   %s 0x%lx\n",
                     DRD_(thread_get_running_tid)(),
                     barrier_get_typename(p),
                     barrier);
    }

    if (p == 0)
    {
        GenericErrInfo GEI = {
            .tid = DRD_(thread_get_running_tid)(),
            .addr = barrier,
        };
        VG_(maybe_record_error)(VG_(get_running_tid)(),
                                GenericErr,
                                VG_(get_IP)(VG_(get_running_tid)()),
                                "Not a barrier",
                                &GEI);
        return;
    }
Ejemplo n.º 2
0
/** Called after pthread_barrier_destroy() / gomp_barrier_destroy(). */
void DRD_(barrier_destroy)(const Addr barrier, const BarrierT barrier_type)
{
   struct barrier_info* p;

   p = DRD_(barrier_get)(barrier);

   if (s_trace_barrier)
   {
      VG_(message)(Vg_UserMsg,
                   "[%d/%d] barrier_destroy   %s 0x%lx",
                   VG_(get_running_tid)(),
                   DRD_(thread_get_running_tid)(),
                   barrier_get_typename(p),
                   barrier);
   }

   if (p == 0)
   {
      GenericErrInfo GEI;
      VG_(maybe_record_error)(VG_(get_running_tid)(),
                              GenericErr,
                              VG_(get_IP)(VG_(get_running_tid)()),
                              "Not a barrier",
                              &GEI);
      return;
   }

   if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count)
   {
      BarrierErrInfo bei = { p->a1, 0, 0 };
      VG_(maybe_record_error)(VG_(get_running_tid)(),
                              BarrierErr,
                              VG_(get_IP)(VG_(get_running_tid)()),
                              "Destruction of a barrier with active waiters",
                              &bei);
   }

   DRD_(clientobj_remove)(p->a1, ClientBarrier);
}
Ejemplo n.º 3
0
/**
 * 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().
 */
void DRD_(barrier_init)(const Addr barrier,
                        const BarrierT barrier_type, const Word count,
                        const Bool reinitialization)
{
    struct barrier_info* p;

    tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier);

    if (count == 0)
    {
        BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), barrier, 0, 0 };
        VG_(maybe_record_error)(VG_(get_running_tid)(),
                                BarrierErr,
                                VG_(get_IP)(VG_(get_running_tid)()),
                                "pthread_barrier_init: 'count' argument is zero",
                                &bei);
    }

    if (! reinitialization && barrier_type == pthread_barrier)
    {
        p = DRD_(barrier_get)(barrier);
        if (p)
        {
            BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), barrier, 0, 0 };
            VG_(maybe_record_error)(VG_(get_running_tid)(),
                                    BarrierErr,
                                    VG_(get_IP)(VG_(get_running_tid)()),
                                    "Barrier reinitialization",
                                    &bei);
        }
    }

    p = DRD_(barrier_get_or_allocate)(barrier, barrier_type, count);

    if (s_trace_barrier)
    {
        if (reinitialization)
        {
            VG_(message)(Vg_UserMsg,
                         "[%d] barrier_reinit    %s 0x%lx count %ld -> %ld\n",
                         DRD_(thread_get_running_tid)(),
                         barrier_get_typename(p),
                         barrier,
                         p->count,
                         count);
        }
        else
        {
            VG_(message)(Vg_UserMsg,
                         "[%d] barrier_init      %s 0x%lx\n",
                         DRD_(thread_get_running_tid)(),
                         barrier_get_typename(p),
                         barrier);
        }
    }

    if (reinitialization && p->count != count)
    {
        if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count)
        {
            BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 };
            VG_(maybe_record_error)(VG_(get_running_tid)(),
                                    BarrierErr,
                                    VG_(get_IP)(VG_(get_running_tid)()),
                                    "Reinitialization of barrier with active"
                                    " waiters",
                                    &bei);
        }
        p->count = count;
    }
}
Ejemplo n.º 4
0
/** Called after pthread_barrier_wait() / gomp_barrier_wait(). */
void DRD_(barrier_post_wait)(const DrdThreadId tid, const Addr barrier,
                             const BarrierT barrier_type, const Bool waited,
                             const Bool serializing)
{
   struct barrier_info* p;
   const UWord word_tid = tid;
   struct barrier_thread_info* q;
   struct barrier_thread_info* r;

   p = DRD_(barrier_get)(barrier);

   if (s_trace_barrier)
   {
      VG_(message)(Vg_UserMsg,
                   "[%d/%d] barrier_post_wait %s 0x%lx iteration %ld%s",
                   VG_(get_running_tid)(),
                   tid,
                   p ? barrier_get_typename(p) : "(?)",
                   barrier,
                   p ? p->post_iteration : -1,
                   serializing ? " (serializing)" : "");
   }

   /*
    * If p == 0, this means that the barrier has been destroyed after
    * *_barrier_wait() returned and before this function was called. Just
    * return in that case -- race conditions between *_barrier_wait()
    * and *_barrier_destroy() are detected by the *_barrier_destroy() wrapper.
    */
   if (p == 0)
      return;

   /* If the *_barrier_wait() call returned an error code, exit. */
   if (! waited)
      return;

   q = VG_(OSetGen_Lookup)(p->oset, &word_tid);
   if (q == 0)
   {
      BarrierErrInfo bei = { p->a1, 0, 0 };
      VG_(maybe_record_error)(VG_(get_running_tid)(),
                              BarrierErr,
                              VG_(get_IP)(VG_(get_running_tid)()),
                              "Error in barrier implementation"
                              " -- barrier_wait() started before"
                              " barrier_destroy() and finished after"
                              " barrier_destroy()",
                              &bei);

      q = VG_(OSetGen_AllocNode)(p->oset, sizeof(*q));
      DRD_(barrier_thread_initialize)(q, tid, p->pre_iteration);
      VG_(OSetGen_Insert)(p->oset, q);
      tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q);
   }
   /*
    * Combine all vector clocks that were stored in the pre_barrier_wait
    * wrapper with the vector clock of the current thread.
    */
   VG_(OSetGen_ResetIter)(p->oset);
   for ( ; (r = VG_(OSetGen_Next)(p->oset)) != 0; )
   {
      if (r != q)
      {
         tl_assert(r->sg[p->post_iteration]);
         DRD_(thread_combine_vc2)(tid, &r->sg[p->post_iteration]->vc);
      }
   }

   /* Create a new segment and store a pointer to that segment. */
   DRD_(thread_new_segment)(tid);
   DRD_(thread_get_latest_segment)(&q->post_wait_sg, tid);
   s_barrier_segment_creation_count++;

   /*
    * If the same number of threads as the barrier count indicates have
    * called the post *_barrier_wait() wrapper, toggle p->post_iteration and
    * reset the p->post_waiters_left counter.
    */
   if (--p->post_waiters_left <= 0)
   {
      p->post_iteration    = 1 - p->post_iteration;
      p->post_waiters_left = p->count;
   }
}
Ejemplo n.º 5
0
/** Called before pthread_barrier_wait() / gomp_barrier_wait(). */
void DRD_(barrier_pre_wait)(const DrdThreadId tid, const Addr barrier,
                            const BarrierT barrier_type)
{
   struct barrier_info* p;
   struct barrier_thread_info* q;
   const UWord word_tid = tid;

   p = DRD_(barrier_get)(barrier);
   if (p == 0 && barrier_type == gomp_barrier)
   {
      /*
       * gomp_barrier_wait() call has been intercepted but gomp_barrier_init()
       * not. The only cause I know of that can trigger this is that libgomp.so
       * has been compiled with --enable-linux-futex.
       */
      VG_(message)(Vg_UserMsg, "");
      VG_(message)(Vg_UserMsg,
                   "Please verify whether gcc has been configured"
                   " with option --disable-linux-futex.");
      VG_(message)(Vg_UserMsg,
                   "See also the section about OpenMP in the DRD manual.");
      VG_(message)(Vg_UserMsg, "");
   }
   tl_assert(p);

   if (s_trace_barrier)
   {
      VG_(message)(Vg_UserMsg,
                   "[%d/%d] barrier_pre_wait  %s 0x%lx iteration %ld",
                   VG_(get_running_tid)(),
                   DRD_(thread_get_running_tid)(),
                   barrier_get_typename(p),
                   barrier,
                   p->pre_iteration);
   }

   /* 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));
      DRD_(barrier_thread_initialize)(q, tid, p->pre_iteration);
      VG_(OSetGen_Insert)(p->oset, q);
      tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q);
   }

   /* Record *_barrier_wait() call context. */
   q->wait_call_ctxt = VG_(record_ExeContext)(VG_(get_running_tid)(), 0);

   /*
    * 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);

   /*
    * If the same number of threads as the barrier count indicates have
    * called the pre *_barrier_wait() wrapper, toggle p->pre_iteration and
    * reset the p->pre_waiters_left counter.
    */
   if (--p->pre_waiters_left <= 0)
   {
      p->pre_iteration    = 1 - p->pre_iteration;
      p->pre_waiters_left = p->count;
   }
}