Home | History | Annotate | Download | only in drd
      1 /*
      2   This file is part of drd, a thread error detector.
      3 
      4   Copyright (C) 2006-2015 Bart Van Assche <bvanassche (at) acm.org>.
      5 
      6   This program is free software; you can redistribute it and/or
      7   modify it under the terms of the GNU General Public License as
      8   published by the Free Software Foundation; either version 2 of the
      9   License, or (at your option) any later version.
     10 
     11   This program is distributed in the hope that it will be useful, but
     12   WITHOUT ANY WARRANTY; without even the implied warranty of
     13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14   General Public License for more details.
     15 
     16   You should have received a copy of the GNU General Public License
     17   along with this program; if not, write to the Free Software
     18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     19   02111-1307, USA.
     20 
     21   The GNU General Public License is contained in the file COPYING.
     22 */
     23 
     24 
     25 #include "drd_error.h"
     26 #include "drd_barrier.h"
     27 #include "drd_clientobj.h"
     28 #include "drd_cond.h"
     29 #include "drd_mutex.h"
     30 #include "drd_segment.h"
     31 #include "drd_semaphore.h"
     32 #include "drd_suppression.h"
     33 #include "drd_thread.h"
     34 #include "pub_tool_vki.h"
     35 #include "pub_tool_basics.h"      // Addr, SizeT
     36 #include "pub_tool_libcassert.h"  // tl_assert()
     37 #include "pub_tool_libcbase.h"    // VG_(strlen)()
     38 #include "pub_tool_libcprint.h"   // VG_(printf)()
     39 #include "pub_tool_machine.h"
     40 #include "pub_tool_mallocfree.h"  // VG_(malloc)(), VG_(free)()
     41 #include "pub_tool_options.h"     // VG_(clo_backtrace_size)
     42 #include "pub_tool_threadstate.h" // VG_(get_pthread_id)()
     43 
     44 
     45 
     46 /* Local functions. */
     47 
     48 static void thread_append_segment(const DrdThreadId tid, Segment* const sg);
     49 static void thread_discard_segment(const DrdThreadId tid, Segment* const sg);
     50 static void thread_compute_conflict_set(struct bitmap** conflict_set,
     51                                         const DrdThreadId tid);
     52 static Bool thread_conflict_set_up_to_date(const DrdThreadId tid);
     53 
     54 
     55 /* Local variables. */
     56 
     57 static ULong    s_context_switch_count;
     58 static ULong    s_discard_ordered_segments_count;
     59 static ULong    s_compute_conflict_set_count;
     60 static ULong    s_update_conflict_set_count;
     61 static ULong    s_update_conflict_set_new_sg_count;
     62 static ULong    s_update_conflict_set_sync_count;
     63 static ULong    s_update_conflict_set_join_count;
     64 static ULong    s_conflict_set_bitmap_creation_count;
     65 static ULong    s_conflict_set_bitmap2_creation_count;
     66 static ThreadId s_vg_running_tid  = VG_INVALID_THREADID;
     67 DrdThreadId     DRD_(g_drd_running_tid) = DRD_INVALID_THREADID;
     68 ThreadInfo*     DRD_(g_threadinfo);
     69 struct bitmap*  DRD_(g_conflict_set);
     70 Bool DRD_(verify_conflict_set);
     71 static Bool     s_trace_context_switches = False;
     72 static Bool     s_trace_conflict_set = False;
     73 static Bool     s_trace_conflict_set_bm = False;
     74 static Bool     s_trace_fork_join = False;
     75 static Bool     s_segment_merging = True;
     76 static Bool     s_new_segments_since_last_merge;
     77 static int      s_segment_merge_interval = 10;
     78 static unsigned s_join_list_vol = 10;
     79 static unsigned s_deletion_head;
     80 static unsigned s_deletion_tail;
     81 #if defined(VGO_solaris)
     82 Bool DRD_(ignore_thread_creation) = True;
     83 #else
     84 Bool DRD_(ignore_thread_creation) = False;
     85 #endif /* VGO_solaris */
     86 
     87 
     88 /* Function definitions. */
     89 
     90 /** Enables/disables context switch tracing. */
     91 void DRD_(thread_trace_context_switches)(const Bool t)
     92 {
     93    tl_assert(t == False || t == True);
     94    s_trace_context_switches = t;
     95 }
     96 
     97 /** Enables/disables conflict set tracing. */
     98 void DRD_(thread_trace_conflict_set)(const Bool t)
     99 {
    100    tl_assert(t == False || t == True);
    101    s_trace_conflict_set = t;
    102 }
    103 
    104 /** Enables/disables conflict set bitmap tracing. */
    105 void DRD_(thread_trace_conflict_set_bm)(const Bool t)
    106 {
    107    tl_assert(t == False || t == True);
    108    s_trace_conflict_set_bm = t;
    109 }
    110 
    111 /** Report whether fork/join tracing is enabled. */
    112 Bool DRD_(thread_get_trace_fork_join)(void)
    113 {
    114    return s_trace_fork_join;
    115 }
    116 
    117 /** Enables/disables fork/join tracing. */
    118 void DRD_(thread_set_trace_fork_join)(const Bool t)
    119 {
    120    tl_assert(t == False || t == True);
    121    s_trace_fork_join = t;
    122 }
    123 
    124 /** Enables/disables segment merging. */
    125 void DRD_(thread_set_segment_merging)(const Bool m)
    126 {
    127    tl_assert(m == False || m == True);
    128    s_segment_merging = m;
    129 }
    130 
    131 /** Get the segment merging interval. */
    132 int DRD_(thread_get_segment_merge_interval)(void)
    133 {
    134    return s_segment_merge_interval;
    135 }
    136 
    137 /** Set the segment merging interval. */
    138 void DRD_(thread_set_segment_merge_interval)(const int i)
    139 {
    140    s_segment_merge_interval = i;
    141 }
    142 
    143 void DRD_(thread_set_join_list_vol)(const int jlv)
    144 {
    145    s_join_list_vol = jlv;
    146 }
    147 
    148 void DRD_(thread_init)(void)
    149 {
    150    DRD_(g_threadinfo) = VG_(malloc)("drd.main.ti.1",
    151                                 DRD_N_THREADS * sizeof DRD_(g_threadinfo)[0]);
    152    for (UInt i = 0; i < DRD_N_THREADS; ++i) {
    153       static ThreadInfo initval;
    154       DRD_(g_threadinfo)[i] = initval;
    155    }
    156 }
    157 
    158 /**
    159  * Convert Valgrind's ThreadId into a DrdThreadId.
    160  *
    161  * @return DRD thread ID upon success and DRD_INVALID_THREADID if the passed
    162  *         Valgrind ThreadId does not yet exist.
    163  */
    164 DrdThreadId DRD_(VgThreadIdToDrdThreadId)(const ThreadId tid)
    165 {
    166    UInt i;
    167 
    168    if (tid == VG_INVALID_THREADID)
    169       return DRD_INVALID_THREADID;
    170 
    171    for (i = 1; i < DRD_N_THREADS; i++)
    172    {
    173       if (DRD_(g_threadinfo)[i].vg_thread_exists == True
    174           && DRD_(g_threadinfo)[i].vg_threadid == tid)
    175       {
    176          return i;
    177       }
    178    }
    179 
    180    return DRD_INVALID_THREADID;
    181 }
    182 
    183 /** Allocate a new DRD thread ID for the specified Valgrind thread ID. */
    184 static DrdThreadId DRD_(VgThreadIdToNewDrdThreadId)(const ThreadId tid)
    185 {
    186    UInt i;
    187 
    188    tl_assert(DRD_(VgThreadIdToDrdThreadId)(tid) == DRD_INVALID_THREADID);
    189 
    190    for (i = 1; i < DRD_N_THREADS; i++)
    191    {
    192       if (!DRD_(g_threadinfo)[i].valid)
    193       {
    194          tl_assert(! DRD_(IsValidDrdThreadId)(i));
    195 
    196          DRD_(g_threadinfo)[i].valid         = True;
    197          DRD_(g_threadinfo)[i].vg_thread_exists = True;
    198          DRD_(g_threadinfo)[i].vg_threadid   = tid;
    199          DRD_(g_threadinfo)[i].pt_threadid   = INVALID_POSIX_THREADID;
    200          DRD_(g_threadinfo)[i].stack_min     = 0;
    201          DRD_(g_threadinfo)[i].stack_min_min = 0;
    202          DRD_(g_threadinfo)[i].stack_startup = 0;
    203          DRD_(g_threadinfo)[i].stack_max     = 0;
    204          DRD_(thread_set_name)(i, "");
    205          DRD_(g_threadinfo)[i].on_alt_stack        = False;
    206          DRD_(g_threadinfo)[i].is_recording_loads  = True;
    207          DRD_(g_threadinfo)[i].is_recording_stores = True;
    208          DRD_(g_threadinfo)[i].pthread_create_nesting_level = 0;
    209          DRD_(g_threadinfo)[i].synchr_nesting = 0;
    210          DRD_(g_threadinfo)[i].deletion_seq = s_deletion_tail - 1;
    211          DRD_(g_threadinfo)[i].creator_thread = DRD_INVALID_THREADID;
    212 #if defined (VGO_solaris)
    213          DRD_(g_threadinfo)[i].bind_guard_flag = 0;
    214 #endif /* VGO_solaris */
    215 
    216          tl_assert(DRD_(g_threadinfo)[i].sg_first == NULL);
    217          tl_assert(DRD_(g_threadinfo)[i].sg_last == NULL);
    218 
    219          tl_assert(DRD_(IsValidDrdThreadId)(i));
    220 
    221          return i;
    222       }
    223    }
    224 
    225    VG_(printf)(
    226 "\nSorry, but the maximum number of threads supported by DRD has been exceeded."
    227 "Aborting.\n");
    228 
    229    tl_assert(False);
    230 
    231    return DRD_INVALID_THREADID;
    232 }
    233 
    234 /** Convert a POSIX thread ID into a DRD thread ID. */
    235 DrdThreadId DRD_(PtThreadIdToDrdThreadId)(const PThreadId tid)
    236 {
    237    UInt i;
    238 
    239    if (tid != INVALID_POSIX_THREADID)
    240    {
    241       for (i = 1; i < DRD_N_THREADS; i++)
    242       {
    243          if (DRD_(g_threadinfo)[i].posix_thread_exists
    244              && DRD_(g_threadinfo)[i].pt_threadid == tid)
    245          {
    246             return i;
    247          }
    248       }
    249    }
    250    return DRD_INVALID_THREADID;
    251 }
    252 
    253 /** Convert a DRD thread ID into a Valgrind thread ID. */
    254 ThreadId DRD_(DrdThreadIdToVgThreadId)(const DrdThreadId tid)
    255 {
    256    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    257              && tid != DRD_INVALID_THREADID);
    258 
    259    return (DRD_(g_threadinfo)[tid].vg_thread_exists
    260            ? DRD_(g_threadinfo)[tid].vg_threadid
    261            : VG_INVALID_THREADID);
    262 }
    263 
    264 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
    265 /**
    266  * Sanity check of the doubly linked list of segments referenced by a
    267  * ThreadInfo struct.
    268  * @return True if sane, False if not.
    269  */
    270 static Bool DRD_(sane_ThreadInfo)(const ThreadInfo* const ti)
    271 {
    272    Segment* p;
    273 
    274    for (p = ti->sg_first; p; p = p->thr_next) {
    275       if (p->thr_next && p->thr_next->thr_prev != p)
    276          return False;
    277       if (p->thr_next == 0 && p != ti->sg_last)
    278          return False;
    279    }
    280    for (p = ti->sg_last; p; p = p->thr_prev) {
    281       if (p->thr_prev && p->thr_prev->thr_next != p)
    282          return False;
    283       if (p->thr_prev == 0 && p != ti->sg_first)
    284          return False;
    285    }
    286    return True;
    287 }
    288 #endif
    289 
    290 /**
    291  * Create the first segment for a newly started thread.
    292  *
    293  * This function is called from the handler installed via
    294  * VG_(track_pre_thread_ll_create)(). The Valgrind core invokes this handler
    295  * from the context of the creator thread, before the new thread has been
    296  * created.
    297  *
    298  * @param[in] creator    DRD thread ID of the creator thread.
    299  * @param[in] vg_created Valgrind thread ID of the created thread.
    300  *
    301  * @return DRD thread ID of the created thread.
    302  */
    303 DrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator,
    304                                     const ThreadId vg_created)
    305 {
    306    DrdThreadId created;
    307 
    308    tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_created) == DRD_INVALID_THREADID);
    309    created = DRD_(VgThreadIdToNewDrdThreadId)(vg_created);
    310    tl_assert(0 <= (int)created && created < DRD_N_THREADS
    311              && created != DRD_INVALID_THREADID);
    312 
    313    tl_assert(DRD_(g_threadinfo)[created].sg_first == NULL);
    314    tl_assert(DRD_(g_threadinfo)[created].sg_last == NULL);
    315 
    316    if (creator != DRD_INVALID_THREADID) {
    317       if (DRD_(ignore_thread_creation)) {
    318          tl_assert(DRD_(thread_get_synchr_nesting_count)(created) == 0);
    319          DRD_(thread_enter_synchr)(created);
    320          /* Counterpart in DRD_(thread_set_pthreadid)(). */
    321       }
    322    }
    323    DRD_(g_threadinfo)[created].creator_thread = creator;
    324 
    325    /* Create an initial segment for the newly created thread. */
    326    thread_append_segment(created, DRD_(sg_new)(creator, created));
    327 
    328    return created;
    329 }
    330 
    331 /**
    332  * Initialize DRD_(g_threadinfo)[] for a newly created thread. Must be called
    333  * after the thread has been created and before any client instructions are run
    334  * on the newly created thread, e.g. from the handler installed via
    335  * VG_(track_pre_thread_first_insn)().
    336  *
    337  * @param[in] vg_created Valgrind thread ID of the newly created thread.
    338  *
    339  * @return DRD thread ID for the new thread.
    340  */
    341 DrdThreadId DRD_(thread_post_create)(const ThreadId vg_created)
    342 {
    343    const DrdThreadId created = DRD_(VgThreadIdToDrdThreadId)(vg_created);
    344 
    345    tl_assert(0 <= (int)created && created < DRD_N_THREADS
    346              && created != DRD_INVALID_THREADID);
    347 
    348    DRD_(g_threadinfo)[created].stack_max
    349       = VG_(thread_get_stack_max)(vg_created);
    350    DRD_(g_threadinfo)[created].stack_startup
    351       = DRD_(g_threadinfo)[created].stack_max;
    352    DRD_(g_threadinfo)[created].stack_min
    353       = DRD_(g_threadinfo)[created].stack_max;
    354    DRD_(g_threadinfo)[created].stack_min_min
    355       = DRD_(g_threadinfo)[created].stack_max;
    356    DRD_(g_threadinfo)[created].stack_size
    357       = VG_(thread_get_stack_size)(vg_created);
    358    tl_assert(DRD_(g_threadinfo)[created].stack_max != 0);
    359 
    360    return created;
    361 }
    362 
    363 static void DRD_(thread_delayed_delete)(const DrdThreadId tid)
    364 {
    365    UInt j;
    366 
    367    DRD_(g_threadinfo)[tid].vg_thread_exists = False;
    368    DRD_(g_threadinfo)[tid].posix_thread_exists = False;
    369    DRD_(g_threadinfo)[tid].deletion_seq = s_deletion_head++;
    370 #if 0
    371    VG_(message)(Vg_DebugMsg, "Adding thread %d to the deletion list\n", tid);
    372 #endif
    373    if (s_deletion_head - s_deletion_tail >= s_join_list_vol) {
    374       for (j = 0; j < DRD_N_THREADS; ++j) {
    375          if (DRD_(IsValidDrdThreadId)(j)
    376              && DRD_(g_threadinfo)[j].deletion_seq == s_deletion_tail)
    377          {
    378             s_deletion_tail++;
    379 #if 0
    380             VG_(message)(Vg_DebugMsg, "Delayed delete of thread %d\n", j);
    381 #endif
    382             DRD_(thread_delete)(j, False);
    383             break;
    384          }
    385       }
    386    }
    387 }
    388 
    389 /**
    390  * Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just
    391  * after thread drd_joiner joined thread drd_joinee.
    392  */
    393 void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
    394 {
    395    tl_assert(DRD_(IsValidDrdThreadId)(drd_joiner));
    396    tl_assert(DRD_(IsValidDrdThreadId)(drd_joinee));
    397 
    398    DRD_(thread_new_segment)(drd_joiner);
    399    DRD_(thread_combine_vc_join)(drd_joiner, drd_joinee);
    400    DRD_(thread_new_segment)(drd_joinee);
    401 
    402    if (s_trace_fork_join)
    403    {
    404       const ThreadId joiner = DRD_(DrdThreadIdToVgThreadId)(drd_joiner);
    405       const unsigned msg_size = 256;
    406       HChar* msg;
    407 
    408       msg = VG_(malloc)("drd.main.dptj.1", msg_size);
    409 
    410       VG_(snprintf)(msg, msg_size,
    411                     "drd_post_thread_join joiner = %u, joinee = %u",
    412                     drd_joiner, drd_joinee);
    413       if (joiner)
    414       {
    415          HChar* vc;
    416 
    417          vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(drd_joiner));
    418          VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
    419                        ", new vc: %s", vc);
    420          VG_(free)(vc);
    421       }
    422       DRD_(trace_msg)("%pS", msg);
    423       VG_(free)(msg);
    424    }
    425 
    426    if (!  DRD_(get_check_stack_accesses)())
    427    {
    428       DRD_(finish_suppression)(DRD_(thread_get_stack_max)(drd_joinee)
    429                                - DRD_(thread_get_stack_size)(drd_joinee),
    430                                DRD_(thread_get_stack_max)(drd_joinee));
    431    }
    432    DRD_(clientobj_delete_thread)(drd_joinee);
    433    DRD_(thread_delayed_delete)(drd_joinee);
    434 }
    435 
    436 /**
    437  * NPTL hack: NPTL allocates the 'struct pthread' on top of the stack,
    438  * and accesses this data structure from multiple threads without locking.
    439  * Any conflicting accesses in the range stack_startup..stack_max will be
    440  * ignored.
    441  */
    442 void DRD_(thread_set_stack_startup)(const DrdThreadId tid,
    443                                     const Addr stack_startup)
    444 {
    445    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    446              && tid != DRD_INVALID_THREADID);
    447    tl_assert(DRD_(g_threadinfo)[tid].stack_min <= stack_startup);
    448    tl_assert(stack_startup <= DRD_(g_threadinfo)[tid].stack_max);
    449    DRD_(g_threadinfo)[tid].stack_startup = stack_startup;
    450 }
    451 
    452 /** Return the stack pointer for the specified thread. */
    453 Addr DRD_(thread_get_stack_min)(const DrdThreadId tid)
    454 {
    455    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    456              && tid != DRD_INVALID_THREADID);
    457    return DRD_(g_threadinfo)[tid].stack_min;
    458 }
    459 
    460 /**
    461  * Return the lowest value that was ever assigned to the stack pointer
    462  * for the specified thread.
    463  */
    464 Addr DRD_(thread_get_stack_min_min)(const DrdThreadId tid)
    465 {
    466    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    467              && tid != DRD_INVALID_THREADID);
    468    return DRD_(g_threadinfo)[tid].stack_min_min;
    469 }
    470 
    471 /** Return the top address for the stack of the specified thread. */
    472 Addr DRD_(thread_get_stack_max)(const DrdThreadId tid)
    473 {
    474    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    475              && tid != DRD_INVALID_THREADID);
    476    return DRD_(g_threadinfo)[tid].stack_max;
    477 }
    478 
    479 /** Return the maximum stack size for the specified thread. */
    480 SizeT DRD_(thread_get_stack_size)(const DrdThreadId tid)
    481 {
    482    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    483              && tid != DRD_INVALID_THREADID);
    484    return DRD_(g_threadinfo)[tid].stack_size;
    485 }
    486 
    487 Bool DRD_(thread_get_on_alt_stack)(const DrdThreadId tid)
    488 {
    489    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    490              && tid != DRD_INVALID_THREADID);
    491    return DRD_(g_threadinfo)[tid].on_alt_stack;
    492 }
    493 
    494 void DRD_(thread_set_on_alt_stack)(const DrdThreadId tid,
    495                                    const Bool on_alt_stack)
    496 {
    497    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    498              && tid != DRD_INVALID_THREADID);
    499    tl_assert(on_alt_stack == !!on_alt_stack);
    500    DRD_(g_threadinfo)[tid].on_alt_stack = on_alt_stack;
    501 }
    502 
    503 Int DRD_(thread_get_threads_on_alt_stack)(void)
    504 {
    505    int n = 0;
    506 
    507    for (UInt i = 1; i < DRD_N_THREADS; i++)
    508       n += DRD_(g_threadinfo)[i].on_alt_stack;
    509    return n;
    510 }
    511 
    512 /**
    513  * Clean up thread-specific data structures.
    514  */
    515 void DRD_(thread_delete)(const DrdThreadId tid, const Bool detached)
    516 {
    517    Segment* sg;
    518    Segment* sg_prev;
    519 
    520    tl_assert(DRD_(IsValidDrdThreadId)(tid));
    521 
    522    tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 0);
    523    for (sg = DRD_(g_threadinfo)[tid].sg_last; sg; sg = sg_prev) {
    524       sg_prev = sg->thr_prev;
    525       sg->thr_next = NULL;
    526       sg->thr_prev = NULL;
    527       DRD_(sg_put)(sg);
    528    }
    529    DRD_(g_threadinfo)[tid].valid = False;
    530    DRD_(g_threadinfo)[tid].vg_thread_exists = False;
    531    DRD_(g_threadinfo)[tid].posix_thread_exists = False;
    532    if (detached)
    533       DRD_(g_threadinfo)[tid].detached_posix_thread = False;
    534    else
    535       tl_assert(!DRD_(g_threadinfo)[tid].detached_posix_thread);
    536    DRD_(g_threadinfo)[tid].sg_first = NULL;
    537    DRD_(g_threadinfo)[tid].sg_last = NULL;
    538 
    539    tl_assert(!DRD_(IsValidDrdThreadId)(tid));
    540 }
    541 
    542 /**
    543  * Called after a thread performed its last memory access and before
    544  * thread_delete() is called. Note: thread_delete() is only called for
    545  * joinable threads, not for detached threads.
    546  */
    547 void DRD_(thread_finished)(const DrdThreadId tid)
    548 {
    549    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    550              && tid != DRD_INVALID_THREADID);
    551 
    552    DRD_(g_threadinfo)[tid].vg_thread_exists = False;
    553 
    554    if (DRD_(g_threadinfo)[tid].detached_posix_thread)
    555    {
    556       /*
    557        * Once a detached thread has finished, its stack is deallocated and
    558        * should no longer be taken into account when computing the conflict set.
    559        */
    560       DRD_(g_threadinfo)[tid].stack_min = DRD_(g_threadinfo)[tid].stack_max;
    561 
    562       /*
    563        * For a detached thread, calling pthread_exit() invalidates the
    564        * POSIX thread ID associated with the detached thread. For joinable
    565        * POSIX threads however, the POSIX thread ID remains live after the
    566        * pthread_exit() call until pthread_join() is called.
    567        */
    568       DRD_(g_threadinfo)[tid].posix_thread_exists = False;
    569    }
    570 }
    571 
    572 /** Called just after fork() in the child process. */
    573 void DRD_(drd_thread_atfork_child)(const DrdThreadId tid)
    574 {
    575    unsigned i;
    576 
    577    for (i = 1; i < DRD_N_THREADS; i++)
    578    {
    579       if (i == tid)
    580 	 continue;
    581       if (DRD_(IsValidDrdThreadId(i)))
    582 	 DRD_(thread_delete)(i, True);
    583       tl_assert(!DRD_(IsValidDrdThreadId(i)));
    584    }
    585 
    586    DRD_(bm_cleanup)(DRD_(g_conflict_set));
    587    DRD_(bm_init)(DRD_(g_conflict_set));
    588 }
    589 
    590 /** Called just before pthread_cancel(). */
    591 void DRD_(thread_pre_cancel)(const DrdThreadId tid)
    592 {
    593    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    594              && tid != DRD_INVALID_THREADID);
    595    tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
    596 
    597    if (DRD_(thread_get_trace_fork_join)())
    598       DRD_(trace_msg)("[%u] drd_thread_pre_cancel %u",
    599                       DRD_(g_drd_running_tid), tid);
    600 }
    601 
    602 /**
    603  * Store the POSIX thread ID for the specified thread.
    604  *
    605  * @note This function can be called two times for the same thread -- see also
    606  * the comment block preceding the pthread_create() wrapper in
    607  * drd_pthread_intercepts.c.
    608  */
    609 void DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid)
    610 {
    611    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    612              && tid != DRD_INVALID_THREADID);
    613    tl_assert(DRD_(g_threadinfo)[tid].pt_threadid == INVALID_POSIX_THREADID
    614              || DRD_(g_threadinfo)[tid].pt_threadid == ptid);
    615    tl_assert(ptid != INVALID_POSIX_THREADID);
    616    DRD_(g_threadinfo)[tid].posix_thread_exists = True;
    617    DRD_(g_threadinfo)[tid].pt_threadid         = ptid;
    618 
    619    if (DRD_(g_threadinfo)[tid].creator_thread != DRD_INVALID_THREADID) {
    620       if (DRD_(ignore_thread_creation)) {
    621          DRD_(thread_leave_synchr)(tid);
    622          tl_assert(DRD_(thread_get_synchr_nesting_count)(tid) == 0);
    623       }
    624    }
    625 }
    626 
    627 /** Returns true for joinable threads and false for detached threads. */
    628 Bool DRD_(thread_get_joinable)(const DrdThreadId tid)
    629 {
    630    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    631              && tid != DRD_INVALID_THREADID);
    632    return ! DRD_(g_threadinfo)[tid].detached_posix_thread;
    633 }
    634 
    635 /** Store the thread mode: joinable or detached. */
    636 #if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
    637  /* There is a cse related issue in gcc for MIPS. Optimization level
    638     has to be lowered, so cse related optimizations are not
    639     included.*/
    640  __attribute__((optimize("O1")))
    641 #endif
    642 void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable)
    643 {
    644    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    645              && tid != DRD_INVALID_THREADID);
    646    tl_assert((!! joinable) == joinable);
    647    tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
    648 
    649    DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable;
    650 }
    651 
    652 /** Tells DRD that the calling thread is about to enter pthread_create(). */
    653 void DRD_(thread_entering_pthread_create)(const DrdThreadId tid)
    654 {
    655    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    656              && tid != DRD_INVALID_THREADID);
    657    tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
    658    tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level >= 0);
    659 
    660    DRD_(g_threadinfo)[tid].pthread_create_nesting_level++;
    661 
    662    if (DRD_(ignore_thread_creation)) {
    663       tl_assert(DRD_(thread_get_synchr_nesting_count)(tid) == 0);
    664       DRD_(thread_enter_synchr)(tid);
    665    }
    666 }
    667 
    668 /** Tells DRD that the calling thread has left pthread_create(). */
    669 void DRD_(thread_left_pthread_create)(const DrdThreadId tid)
    670 {
    671    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    672              && tid != DRD_INVALID_THREADID);
    673    tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
    674    tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level > 0);
    675 
    676    DRD_(g_threadinfo)[tid].pthread_create_nesting_level--;
    677 
    678    if (DRD_(ignore_thread_creation)) {
    679       DRD_(thread_leave_synchr)(tid);
    680       tl_assert(DRD_(thread_get_synchr_nesting_count)(tid) == 0);
    681    }
    682 }
    683 
    684 #if defined(VGO_solaris)
    685 /** Handles the bind_guard() intercept. */
    686 void DRD_(thread_entering_rtld_bind_guard)(const DrdThreadId tid, int flags)
    687 {
    688    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    689              && tid != DRD_INVALID_THREADID);
    690 
    691    Int bindflag = (flags & VKI_THR_FLG_RTLD);
    692    if ((bindflag & DRD_(g_threadinfo)[tid].bind_guard_flag) == 0) {
    693       DRD_(g_threadinfo)[tid].bind_guard_flag |= bindflag;
    694       DRD_(thread_enter_synchr)(tid);
    695    }
    696 }
    697 
    698 /**
    699  * Handles the bind_clear() intercept.
    700  * Call to bind_clear(0) is typically used to determine value of bind_flags.
    701  */
    702 void DRD_(thread_leaving_rtld_bind_clear)(const DrdThreadId tid, int flags)
    703 {
    704    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    705              && tid != DRD_INVALID_THREADID);
    706 
    707    Int bindflag = (flags & VKI_THR_FLG_RTLD);
    708    if ((DRD_(g_threadinfo)[tid].bind_guard_flag & bindflag) != 0) {
    709       DRD_(g_threadinfo)[tid].bind_guard_flag &= ~bindflag;
    710       DRD_(thread_leave_synchr)(tid);
    711    }
    712 }
    713 #endif /* VGO_solaris */
    714 
    715 /** Obtain the thread number and the user-assigned thread name. */
    716 const HChar* DRD_(thread_get_name)(const DrdThreadId tid)
    717 {
    718    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    719              && tid != DRD_INVALID_THREADID);
    720 
    721    return DRD_(g_threadinfo)[tid].name;
    722 }
    723 
    724 /** Set the name of the specified thread. */
    725 void DRD_(thread_set_name)(const DrdThreadId tid, const HChar* const name)
    726 {
    727    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    728              && tid != DRD_INVALID_THREADID);
    729 
    730    if (name == NULL || name[0] == 0)
    731       VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
    732                     sizeof(DRD_(g_threadinfo)[tid].name),
    733                     "Thread %u",
    734                     tid);
    735    else
    736       VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
    737                     sizeof(DRD_(g_threadinfo)[tid].name),
    738                     "Thread %u (%s)",
    739                     tid, name);
    740    DRD_(g_threadinfo)[tid].name[sizeof(DRD_(g_threadinfo)[tid].name) - 1] = 0;
    741 }
    742 
    743 /**
    744  * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
    745  * conflict set.
    746  */
    747 void DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid)
    748 {
    749    tl_assert(vg_tid != VG_INVALID_THREADID);
    750 
    751    if (vg_tid != s_vg_running_tid)
    752    {
    753       DRD_(thread_set_running_tid)(vg_tid,
    754                                    DRD_(VgThreadIdToDrdThreadId)(vg_tid));
    755    }
    756 
    757    tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
    758    tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
    759 }
    760 
    761 /**
    762  * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
    763  * conflict set.
    764  */
    765 void DRD_(thread_set_running_tid)(const ThreadId vg_tid,
    766                                   const DrdThreadId drd_tid)
    767 {
    768    tl_assert(vg_tid != VG_INVALID_THREADID);
    769    tl_assert(drd_tid != DRD_INVALID_THREADID);
    770 
    771    if (vg_tid != s_vg_running_tid)
    772    {
    773       if (s_trace_context_switches
    774           && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID)
    775       {
    776          VG_(message)(Vg_DebugMsg,
    777                       "Context switch from thread %u to thread %u;"
    778                       " segments: %llu\n",
    779                       DRD_(g_drd_running_tid), drd_tid,
    780                       DRD_(sg_get_segments_alive_count)());
    781       }
    782       s_vg_running_tid = vg_tid;
    783       DRD_(g_drd_running_tid) = drd_tid;
    784       thread_compute_conflict_set(&DRD_(g_conflict_set), drd_tid);
    785       s_context_switch_count++;
    786    }
    787 
    788    tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
    789    tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
    790 }
    791 
    792 /**
    793  * Increase the synchronization nesting counter. Must be called before the
    794  * client calls a synchronization function.
    795  */
    796 int DRD_(thread_enter_synchr)(const DrdThreadId tid)
    797 {
    798    tl_assert(DRD_(IsValidDrdThreadId)(tid));
    799    return DRD_(g_threadinfo)[tid].synchr_nesting++;
    800 }
    801 
    802 /**
    803  * Decrease the synchronization nesting counter. Must be called after the
    804  * client left a synchronization function.
    805  */
    806 int DRD_(thread_leave_synchr)(const DrdThreadId tid)
    807 {
    808    tl_assert(DRD_(IsValidDrdThreadId)(tid));
    809    tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 1);
    810    return --DRD_(g_threadinfo)[tid].synchr_nesting;
    811 }
    812 
    813 /** Returns the synchronization nesting counter. */
    814 int DRD_(thread_get_synchr_nesting_count)(const DrdThreadId tid)
    815 {
    816    tl_assert(DRD_(IsValidDrdThreadId)(tid));
    817    return DRD_(g_threadinfo)[tid].synchr_nesting;
    818 }
    819 
    820 /** Append a new segment at the end of the segment list. */
    821 static
    822 void thread_append_segment(const DrdThreadId tid, Segment* const sg)
    823 {
    824    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    825              && tid != DRD_INVALID_THREADID);
    826 
    827 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
    828    tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
    829 #endif
    830 
    831    // add at tail
    832    sg->thr_prev = DRD_(g_threadinfo)[tid].sg_last;
    833    sg->thr_next = NULL;
    834    if (DRD_(g_threadinfo)[tid].sg_last)
    835       DRD_(g_threadinfo)[tid].sg_last->thr_next = sg;
    836    DRD_(g_threadinfo)[tid].sg_last = sg;
    837    if (DRD_(g_threadinfo)[tid].sg_first == NULL)
    838       DRD_(g_threadinfo)[tid].sg_first = sg;
    839 
    840 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
    841    tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
    842 #endif
    843 }
    844 
    845 /**
    846  * Remove a segment from the segment list of thread threadid, and free the
    847  * associated memory.
    848  */
    849 static
    850 void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
    851 {
    852    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    853              && tid != DRD_INVALID_THREADID);
    854 
    855 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
    856    tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
    857 #endif
    858 
    859    if (sg->thr_prev)
    860       sg->thr_prev->thr_next = sg->thr_next;
    861    if (sg->thr_next)
    862       sg->thr_next->thr_prev = sg->thr_prev;
    863    if (sg == DRD_(g_threadinfo)[tid].sg_first)
    864       DRD_(g_threadinfo)[tid].sg_first = sg->thr_next;
    865    if (sg == DRD_(g_threadinfo)[tid].sg_last)
    866       DRD_(g_threadinfo)[tid].sg_last = sg->thr_prev;
    867    DRD_(sg_put)(sg);
    868 
    869 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
    870    tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
    871 #endif
    872 }
    873 
    874 /**
    875  * Returns a pointer to the vector clock of the most recent segment associated
    876  * with thread 'tid'.
    877  */
    878 VectorClock* DRD_(thread_get_vc)(const DrdThreadId tid)
    879 {
    880    Segment* latest_sg;
    881 
    882    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    883              && tid != DRD_INVALID_THREADID);
    884    latest_sg = DRD_(g_threadinfo)[tid].sg_last;
    885    tl_assert(latest_sg);
    886    return &latest_sg->vc;
    887 }
    888 
    889 /**
    890  * Return the latest segment of thread 'tid' and increment its reference count.
    891  */
    892 void DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid)
    893 {
    894    Segment* latest_sg;
    895 
    896    tl_assert(sg);
    897    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
    898              && tid != DRD_INVALID_THREADID);
    899    latest_sg = DRD_(g_threadinfo)[tid].sg_last;
    900    tl_assert(latest_sg);
    901 
    902    DRD_(sg_put)(*sg);
    903    *sg = DRD_(sg_get)(latest_sg);
    904 }
    905 
    906 /**
    907  * Compute the minimum of all latest vector clocks of all threads
    908  * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
    909  *
    910  * @param vc pointer to a vectorclock, holds result upon return.
    911  */
    912 static void DRD_(thread_compute_minimum_vc)(VectorClock* vc)
    913 {
    914    unsigned i;
    915    Bool first;
    916    Segment* latest_sg;
    917 
    918    first = True;
    919    for (i = 0; i < DRD_N_THREADS; i++)
    920    {
    921       latest_sg = DRD_(g_threadinfo)[i].sg_last;
    922       if (latest_sg) {
    923          if (first)
    924             DRD_(vc_assign)(vc, &latest_sg->vc);
    925          else
    926             DRD_(vc_min)(vc, &latest_sg->vc);
    927          first = False;
    928       }
    929    }
    930 }
    931 
    932 /**
    933  * Compute the maximum of all latest vector clocks of all threads.
    934  *
    935  * @param vc pointer to a vectorclock, holds result upon return.
    936  */
    937 static void DRD_(thread_compute_maximum_vc)(VectorClock* vc)
    938 {
    939    unsigned i;
    940    Bool first;
    941    Segment* latest_sg;
    942 
    943    first = True;
    944    for (i = 0; i < DRD_N_THREADS; i++)
    945    {
    946       latest_sg = DRD_(g_threadinfo)[i].sg_last;
    947       if (latest_sg) {
    948          if (first)
    949             DRD_(vc_assign)(vc, &latest_sg->vc);
    950          else
    951             DRD_(vc_combine)(vc, &latest_sg->vc);
    952          first = False;
    953       }
    954    }
    955 }
    956 
    957 /**
    958  * Discard all segments that have a defined order against the latest vector
    959  * clock of all threads -- these segments can no longer be involved in a
    960  * data race.
    961  */
    962 static void thread_discard_ordered_segments(void)
    963 {
    964    unsigned i;
    965    VectorClock thread_vc_min;
    966 
    967    s_discard_ordered_segments_count++;
    968 
    969    DRD_(vc_init)(&thread_vc_min, 0, 0);
    970    DRD_(thread_compute_minimum_vc)(&thread_vc_min);
    971    if (DRD_(sg_get_trace)())
    972    {
    973       HChar *vc_min, *vc_max;
    974       VectorClock thread_vc_max;
    975 
    976       DRD_(vc_init)(&thread_vc_max, 0, 0);
    977       DRD_(thread_compute_maximum_vc)(&thread_vc_max);
    978       vc_min = DRD_(vc_aprint)(&thread_vc_min);
    979       vc_max = DRD_(vc_aprint)(&thread_vc_max);
    980       VG_(message)(Vg_DebugMsg,
    981                    "Discarding ordered segments -- min vc is %s, max vc is %s\n",
    982                    vc_min, vc_max);
    983       VG_(free)(vc_min);
    984       VG_(free)(vc_max);
    985       DRD_(vc_cleanup)(&thread_vc_max);
    986    }
    987 
    988    for (i = 0; i < DRD_N_THREADS; i++) {
    989       Segment* sg;
    990       Segment* sg_next;
    991 
    992       for (sg = DRD_(g_threadinfo)[i].sg_first;
    993            sg && (sg_next = sg->thr_next)
    994               && DRD_(vc_lte)(&sg->vc, &thread_vc_min);
    995            sg = sg_next)
    996       {
    997          thread_discard_segment(i, sg);
    998       }
    999    }
   1000    DRD_(vc_cleanup)(&thread_vc_min);
   1001 }
   1002 
   1003 /**
   1004  * An implementation of the property 'equiv(sg1, sg2)' as defined in the paper
   1005  * by Mark Christiaens e.a. The property equiv(sg1, sg2) holds if and only if
   1006  * all segments in the set CS are ordered consistently against both sg1 and
   1007  * sg2. The set CS is defined as the set of segments that can immediately
   1008  * precede future segments via inter-thread synchronization operations. In
   1009  * DRD the set CS consists of the latest segment of each thread combined with
   1010  * all segments for which the reference count is strictly greater than one.
   1011  * The code below is an optimized version of the following:
   1012  *
   1013  * for (i = 0; i < DRD_N_THREADS; i++)
   1014  * {
   1015  *    Segment* sg;
   1016  *
   1017  *    for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
   1018  *    {
   1019  *       if (sg == DRD_(g_threadinfo)[i].last || DRD_(sg_get_refcnt)(sg) > 1)
   1020  *       {
   1021  *          if (   DRD_(vc_lte)(&sg1->vc, &sg->vc)
   1022  *              != DRD_(vc_lte)(&sg2->vc, &sg->vc)
   1023  *              || DRD_(vc_lte)(&sg->vc, &sg1->vc)
   1024  *              != DRD_(vc_lte)(&sg->vc, &sg2->vc))
   1025  *          {
   1026  *             return False;
   1027  *          }
   1028  *       }
   1029  *    }
   1030  * }
   1031  */
   1032 static Bool thread_consistent_segment_ordering(const DrdThreadId tid,
   1033                                                Segment* const sg1,
   1034                                                Segment* const sg2)
   1035 {
   1036    unsigned i;
   1037 
   1038    tl_assert(sg1->thr_next);
   1039    tl_assert(sg2->thr_next);
   1040    tl_assert(sg1->thr_next == sg2);
   1041    tl_assert(DRD_(vc_lte)(&sg1->vc, &sg2->vc));
   1042 
   1043    for (i = 0; i < DRD_N_THREADS; i++)
   1044    {
   1045       Segment* sg;
   1046 
   1047       for (sg = DRD_(g_threadinfo)[i].sg_first; sg; sg = sg->thr_next) {
   1048          if (!sg->thr_next || DRD_(sg_get_refcnt)(sg) > 1) {
   1049             if (DRD_(vc_lte)(&sg2->vc, &sg->vc))
   1050                break;
   1051             if (DRD_(vc_lte)(&sg1->vc, &sg->vc))
   1052                return False;
   1053          }
   1054       }
   1055       for (sg = DRD_(g_threadinfo)[i].sg_last; sg; sg = sg->thr_prev) {
   1056          if (!sg->thr_next || DRD_(sg_get_refcnt)(sg) > 1) {
   1057             if (DRD_(vc_lte)(&sg->vc, &sg1->vc))
   1058                break;
   1059             if (DRD_(vc_lte)(&sg->vc, &sg2->vc))
   1060                return False;
   1061          }
   1062       }
   1063    }
   1064    return True;
   1065 }
   1066 
   1067 /**
   1068  * Merge all segments that may be merged without triggering false positives
   1069  * or discarding real data races. For the theoretical background of segment
   1070  * merging, see also the following paper: Mark Christiaens, Michiel Ronsse
   1071  * and Koen De Bosschere. Bounding the number of segment histories during
   1072  * data race detection. Parallel Computing archive, Volume 28, Issue 9,
   1073  * pp 1221-1238, September 2002. This paper contains a proof that merging
   1074  * consecutive segments for which the property equiv(s1,s2) holds can be
   1075  * merged without reducing the accuracy of datarace detection. Furthermore
   1076  * it is also proven that the total number of all segments will never grow
   1077  * unbounded if all segments s1, s2 for which equiv(s1, s2) holds are merged
   1078  * every time a new segment is created. The property equiv(s1, s2) is defined
   1079  * as follows: equiv(s1, s2) <=> for all segments in the set CS, the vector
   1080  * clocks of segments s and s1 are ordered in the same way as those of segments
   1081  * s and s2. The set CS is defined as the set of existing segments s that have
   1082  * the potential to conflict with not yet created segments, either because the
   1083  * segment s is the latest segment of a thread or because it can become the
   1084  * immediate predecessor of a new segment due to a synchronization operation.
   1085  */
   1086 static void thread_merge_segments(void)
   1087 {
   1088    unsigned i;
   1089 
   1090    s_new_segments_since_last_merge = 0;
   1091 
   1092    for (i = 0; i < DRD_N_THREADS; i++)
   1093    {
   1094       Segment* sg;
   1095 
   1096 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
   1097       tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
   1098 #endif
   1099 
   1100       for (sg = DRD_(g_threadinfo)[i].sg_first; sg; sg = sg->thr_next) {
   1101          if (DRD_(sg_get_refcnt)(sg) == 1 && sg->thr_next) {
   1102             Segment* const sg_next = sg->thr_next;
   1103             if (DRD_(sg_get_refcnt)(sg_next) == 1
   1104                 && sg_next->thr_next
   1105                 && thread_consistent_segment_ordering(i, sg, sg_next))
   1106             {
   1107                /* Merge sg and sg_next into sg. */
   1108                DRD_(sg_merge)(sg, sg_next);
   1109                thread_discard_segment(i, sg_next);
   1110             }
   1111          }
   1112       }
   1113 
   1114 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
   1115       tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
   1116 #endif
   1117    }
   1118 }
   1119 
   1120 /**
   1121  * Create a new segment for the specified thread, and discard any segments
   1122  * that cannot cause races anymore.
   1123  */
   1124 void DRD_(thread_new_segment)(const DrdThreadId tid)
   1125 {
   1126    Segment* last_sg;
   1127    Segment* new_sg;
   1128 
   1129    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
   1130              && tid != DRD_INVALID_THREADID);
   1131    tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
   1132 
   1133    last_sg = DRD_(g_threadinfo)[tid].sg_last;
   1134    new_sg = DRD_(sg_new)(tid, tid);
   1135    thread_append_segment(tid, new_sg);
   1136    if (tid == DRD_(g_drd_running_tid) && last_sg)
   1137    {
   1138       DRD_(thread_update_conflict_set)(tid, &last_sg->vc);
   1139       s_update_conflict_set_new_sg_count++;
   1140    }
   1141 
   1142    tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
   1143 
   1144    if (s_segment_merging
   1145        && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
   1146    {
   1147       thread_discard_ordered_segments();
   1148       thread_merge_segments();
   1149    }
   1150 }
   1151 
   1152 /** Call this function after thread 'joiner' joined thread 'joinee'. */
   1153 void DRD_(thread_combine_vc_join)(DrdThreadId joiner, DrdThreadId joinee)
   1154 {
   1155    tl_assert(joiner != joinee);
   1156    tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
   1157              && joiner != DRD_INVALID_THREADID);
   1158    tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
   1159              && joinee != DRD_INVALID_THREADID);
   1160    tl_assert(DRD_(g_threadinfo)[joiner].sg_first);
   1161    tl_assert(DRD_(g_threadinfo)[joiner].sg_last);
   1162    tl_assert(DRD_(g_threadinfo)[joinee].sg_first);
   1163    tl_assert(DRD_(g_threadinfo)[joinee].sg_last);
   1164 
   1165    if (DRD_(sg_get_trace)())
   1166    {
   1167       HChar *str1, *str2;
   1168       str1 = DRD_(vc_aprint)(DRD_(thread_get_vc)(joiner));
   1169       str2 = DRD_(vc_aprint)(DRD_(thread_get_vc)(joinee));
   1170       VG_(message)(Vg_DebugMsg, "Before join: joiner %s, joinee %s\n",
   1171                    str1, str2);
   1172       VG_(free)(str1);
   1173       VG_(free)(str2);
   1174    }
   1175    if (joiner == DRD_(g_drd_running_tid)) {
   1176       VectorClock old_vc;
   1177 
   1178       DRD_(vc_copy)(&old_vc, DRD_(thread_get_vc)(joiner));
   1179       DRD_(vc_combine)(DRD_(thread_get_vc)(joiner),
   1180                        DRD_(thread_get_vc)(joinee));
   1181       DRD_(thread_update_conflict_set)(joiner, &old_vc);
   1182       s_update_conflict_set_join_count++;
   1183       DRD_(vc_cleanup)(&old_vc);
   1184    } else {
   1185       DRD_(vc_combine)(DRD_(thread_get_vc)(joiner),
   1186                        DRD_(thread_get_vc)(joinee));
   1187    }
   1188 
   1189    thread_discard_ordered_segments();
   1190 
   1191    if (DRD_(sg_get_trace)()) {
   1192       HChar* str;
   1193 
   1194       str = DRD_(vc_aprint)(DRD_(thread_get_vc)(joiner));
   1195       VG_(message)(Vg_DebugMsg, "After join: %s\n", str);
   1196       VG_(free)(str);
   1197    }
   1198 }
   1199 
   1200 /**
   1201  * Update the vector clock of the last segment of thread tid with the
   1202  * the vector clock of segment sg.
   1203  */
   1204 static void thread_combine_vc_sync(DrdThreadId tid, const Segment* sg)
   1205 {
   1206    const VectorClock* const vc = &sg->vc;
   1207 
   1208    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
   1209              && tid != DRD_INVALID_THREADID);
   1210    tl_assert(DRD_(g_threadinfo)[tid].sg_first);
   1211    tl_assert(DRD_(g_threadinfo)[tid].sg_last);
   1212    tl_assert(sg);
   1213    tl_assert(vc);
   1214 
   1215    if (tid != sg->tid) {
   1216       VectorClock old_vc;
   1217 
   1218       DRD_(vc_copy)(&old_vc, DRD_(thread_get_vc)(tid));
   1219       DRD_(vc_combine)(DRD_(thread_get_vc)(tid), vc);
   1220       if (DRD_(sg_get_trace)()) {
   1221          HChar *str1, *str2;
   1222          str1 = DRD_(vc_aprint)(&old_vc);
   1223          str2 = DRD_(vc_aprint)(DRD_(thread_get_vc)(tid));
   1224          VG_(message)(Vg_DebugMsg, "thread %u: vc %s -> %s\n", tid, str1, str2);
   1225          VG_(free)(str1);
   1226          VG_(free)(str2);
   1227       }
   1228 
   1229       thread_discard_ordered_segments();
   1230 
   1231       DRD_(thread_update_conflict_set)(tid, &old_vc);
   1232       s_update_conflict_set_sync_count++;
   1233 
   1234       DRD_(vc_cleanup)(&old_vc);
   1235    } else {
   1236       tl_assert(DRD_(vc_lte)(vc, DRD_(thread_get_vc)(tid)));
   1237    }
   1238 }
   1239 
   1240 /**
   1241  * Create a new segment for thread tid and update the vector clock of the last
   1242  * segment of this thread with the vector clock of segment sg. Call this
   1243  * function after thread tid had to wait because of thread synchronization
   1244  * until the memory accesses in the segment sg finished.
   1245  */
   1246 void DRD_(thread_new_segment_and_combine_vc)(DrdThreadId tid, const Segment* sg)
   1247 {
   1248    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
   1249              && tid != DRD_INVALID_THREADID);
   1250    tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
   1251    tl_assert(sg);
   1252 
   1253    thread_append_segment(tid, DRD_(sg_new)(tid, tid));
   1254 
   1255    thread_combine_vc_sync(tid, sg);
   1256 
   1257    if (s_segment_merging
   1258        && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
   1259    {
   1260       thread_discard_ordered_segments();
   1261       thread_merge_segments();
   1262    }
   1263 }
   1264 
   1265 /**
   1266  * Call this function whenever a thread is no longer using the memory
   1267  * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
   1268  * increase.
   1269  */
   1270 void DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2)
   1271 {
   1272    Segment* p;
   1273 
   1274    for (p = DRD_(g_sg_list); p; p = p->g_next)
   1275       DRD_(bm_clear)(DRD_(sg_bm)(p), a1, a2);
   1276 
   1277    DRD_(bm_clear)(DRD_(g_conflict_set), a1, a2);
   1278 }
   1279 
   1280 /** Specify whether memory loads should be recorded. */
   1281 void DRD_(thread_set_record_loads)(const DrdThreadId tid, const Bool enabled)
   1282 {
   1283    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
   1284              && tid != DRD_INVALID_THREADID);
   1285    tl_assert(enabled == !! enabled);
   1286 
   1287    DRD_(g_threadinfo)[tid].is_recording_loads = enabled;
   1288 }
   1289 
   1290 /** Specify whether memory stores should be recorded. */
   1291 void DRD_(thread_set_record_stores)(const DrdThreadId tid, const Bool enabled)
   1292 {
   1293    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
   1294              && tid != DRD_INVALID_THREADID);
   1295    tl_assert(enabled == !! enabled);
   1296 
   1297    DRD_(g_threadinfo)[tid].is_recording_stores = enabled;
   1298 }
   1299 
   1300 /**
   1301  * Print the segment information for all threads.
   1302  *
   1303  * This function is only used for debugging purposes.
   1304  */
   1305 void DRD_(thread_print_all)(void)
   1306 {
   1307    UInt i;
   1308    Segment* p;
   1309 
   1310    for (i = 0; i < DRD_N_THREADS; i++)
   1311    {
   1312       p = DRD_(g_threadinfo)[i].sg_first;
   1313       if (p) {
   1314          VG_(printf)("**************\n"
   1315                      "* thread %3u (%d/%u/%u/%u/0x%lx/%d) *\n"
   1316                      "**************\n",
   1317                      i,
   1318                      DRD_(g_threadinfo)[i].valid,
   1319                      DRD_(g_threadinfo)[i].vg_thread_exists,
   1320                      DRD_(g_threadinfo)[i].vg_threadid,
   1321                      DRD_(g_threadinfo)[i].posix_thread_exists,
   1322                      DRD_(g_threadinfo)[i].pt_threadid,
   1323                      DRD_(g_threadinfo)[i].detached_posix_thread);
   1324          for ( ; p; p = p->thr_next)
   1325             DRD_(sg_print)(p);
   1326       }
   1327    }
   1328 }
   1329 
   1330 /** Show a call stack involved in a data race. */
   1331 static void show_call_stack(const DrdThreadId tid, ExeContext* const callstack)
   1332 {
   1333    const ThreadId vg_tid = DRD_(DrdThreadIdToVgThreadId)(tid);
   1334 
   1335    if (vg_tid != VG_INVALID_THREADID) {
   1336       if (callstack)
   1337          VG_(pp_ExeContext)(callstack);
   1338       else
   1339          VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
   1340    } else {
   1341       if (!VG_(clo_xml))
   1342          VG_(message)(Vg_UserMsg,
   1343                       "   (thread finished, call stack no longer available)\n");
   1344    }
   1345 }
   1346 
   1347 /** Print information about the segments involved in a data race. */
   1348 static void
   1349 thread_report_conflicting_segments_segment(const DrdThreadId tid,
   1350                                            const Addr addr,
   1351                                            const SizeT size,
   1352                                            const BmAccessTypeT access_type,
   1353                                            const Segment* const p)
   1354 {
   1355    unsigned i;
   1356 
   1357    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
   1358              && tid != DRD_INVALID_THREADID);
   1359    tl_assert(p);
   1360 
   1361    for (i = 0; i < DRD_N_THREADS; i++) {
   1362       if (i != tid) {
   1363          Segment* q;
   1364 
   1365          for (q = DRD_(g_threadinfo)[i].sg_last; q; q = q->thr_prev) {
   1366             /*
   1367              * Since q iterates over the segments of thread i in order of
   1368              * decreasing vector clocks, if q->vc <= p->vc, then
   1369              * q->next->vc <= p->vc will also hold. Hence, break out of the
   1370              * loop once this condition is met.
   1371              */
   1372             if (DRD_(vc_lte)(&q->vc, &p->vc))
   1373                break;
   1374             if (!DRD_(vc_lte)(&p->vc, &q->vc)) {
   1375                if (DRD_(bm_has_conflict_with)(DRD_(sg_bm)(q), addr, addr + size,
   1376                                               access_type)) {
   1377                   Segment* q_next;
   1378 
   1379                   tl_assert(q->stacktrace);
   1380                   if (VG_(clo_xml))
   1381                      VG_(printf_xml)("  <other_segment_start>\n");
   1382                   else
   1383                      VG_(message)(Vg_UserMsg,
   1384                                   "Other segment start (thread %u)\n", i);
   1385                   show_call_stack(i, q->stacktrace);
   1386                   if (VG_(clo_xml))
   1387                      VG_(printf_xml)("  </other_segment_start>\n"
   1388                                      "  <other_segment_end>\n");
   1389                   else
   1390                      VG_(message)(Vg_UserMsg,
   1391                                   "Other segment end (thread %u)\n", i);
   1392                   q_next = q->thr_next;
   1393                   show_call_stack(i, q_next ? q_next->stacktrace : 0);
   1394                   if (VG_(clo_xml))
   1395                      VG_(printf_xml)("  </other_segment_end>\n");
   1396                }
   1397             }
   1398          }
   1399       }
   1400    }
   1401 }
   1402 
   1403 /** Print information about all segments involved in a data race. */
   1404 void DRD_(thread_report_conflicting_segments)(const DrdThreadId tid,
   1405                                               const Addr addr,
   1406                                               const SizeT size,
   1407                                               const BmAccessTypeT access_type)
   1408 {
   1409    Segment* p;
   1410 
   1411    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
   1412              && tid != DRD_INVALID_THREADID);
   1413 
   1414    for (p = DRD_(g_threadinfo)[tid].sg_first; p; p = p->thr_next) {
   1415       if (DRD_(bm_has)(DRD_(sg_bm)(p), addr, addr + size, access_type))
   1416          thread_report_conflicting_segments_segment(tid, addr, size,
   1417                                                     access_type, p);
   1418    }
   1419 }
   1420 
   1421 /**
   1422  * Verify whether the conflict set for thread tid is up to date. Only perform
   1423  * the check if the environment variable DRD_VERIFY_CONFLICT_SET has been set.
   1424  */
   1425 static Bool thread_conflict_set_up_to_date(const DrdThreadId tid)
   1426 {
   1427    Bool result;
   1428    struct bitmap* computed_conflict_set = 0;
   1429 
   1430    if (!DRD_(verify_conflict_set))
   1431       return True;
   1432 
   1433    thread_compute_conflict_set(&computed_conflict_set, tid);
   1434    result = DRD_(bm_equal)(DRD_(g_conflict_set), computed_conflict_set);
   1435    if (! result)
   1436    {
   1437       VG_(printf)("actual conflict set:\n");
   1438       DRD_(bm_print)(DRD_(g_conflict_set));
   1439       VG_(printf)("\n");
   1440       VG_(printf)("computed conflict set:\n");
   1441       DRD_(bm_print)(computed_conflict_set);
   1442       VG_(printf)("\n");
   1443    }
   1444    DRD_(bm_delete)(computed_conflict_set);
   1445    return result;
   1446 }
   1447 
   1448 /**
   1449  * Compute the conflict set: a bitmap that represents the union of all memory
   1450  * accesses of all segments that are unordered to the current segment of the
   1451  * thread tid.
   1452  */
   1453 static void thread_compute_conflict_set(struct bitmap** conflict_set,
   1454                                         const DrdThreadId tid)
   1455 {
   1456    Segment* p;
   1457 
   1458    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
   1459              && tid != DRD_INVALID_THREADID);
   1460    tl_assert(tid == DRD_(g_drd_running_tid));
   1461 
   1462    s_compute_conflict_set_count++;
   1463    s_conflict_set_bitmap_creation_count
   1464       -= DRD_(bm_get_bitmap_creation_count)();
   1465    s_conflict_set_bitmap2_creation_count
   1466       -= DRD_(bm_get_bitmap2_creation_count)();
   1467 
   1468    if (*conflict_set) {
   1469       DRD_(bm_cleanup)(*conflict_set);
   1470       DRD_(bm_init)(*conflict_set);
   1471    } else {
   1472       *conflict_set = DRD_(bm_new)();
   1473    }
   1474 
   1475    if (s_trace_conflict_set) {
   1476       HChar* str;
   1477 
   1478       str = DRD_(vc_aprint)(DRD_(thread_get_vc)(tid));
   1479       VG_(message)(Vg_DebugMsg,
   1480                    "computing conflict set for thread %u with vc %s\n",
   1481                    tid, str);
   1482       VG_(free)(str);
   1483    }
   1484 
   1485    p = DRD_(g_threadinfo)[tid].sg_last;
   1486    {
   1487       unsigned j;
   1488 
   1489       if (s_trace_conflict_set) {
   1490          HChar* vc;
   1491 
   1492          vc = DRD_(vc_aprint)(&p->vc);
   1493          VG_(message)(Vg_DebugMsg, "conflict set: thread [%u] at vc %s\n",
   1494                       tid, vc);
   1495          VG_(free)(vc);
   1496       }
   1497 
   1498       for (j = 0; j < DRD_N_THREADS; j++) {
   1499          if (j != tid && DRD_(IsValidDrdThreadId)(j)) {
   1500             Segment* q;
   1501 
   1502             for (q = DRD_(g_threadinfo)[j].sg_last; q; q = q->thr_prev) {
   1503                if (!DRD_(vc_lte)(&q->vc, &p->vc)
   1504                    && !DRD_(vc_lte)(&p->vc, &q->vc)) {
   1505                   if (s_trace_conflict_set) {
   1506                      HChar* str;
   1507 
   1508                      str = DRD_(vc_aprint)(&q->vc);
   1509                      VG_(message)(Vg_DebugMsg,
   1510                                   "conflict set: [%u] merging segment %s\n",
   1511                                   j, str);
   1512                      VG_(free)(str);
   1513                   }
   1514                   DRD_(bm_merge2)(*conflict_set, DRD_(sg_bm)(q));
   1515                } else {
   1516                   if (s_trace_conflict_set) {
   1517                      HChar* str;
   1518 
   1519                      str = DRD_(vc_aprint)(&q->vc);
   1520                      VG_(message)(Vg_DebugMsg,
   1521                                   "conflict set: [%u] ignoring segment %s\n",
   1522                                   j, str);
   1523                      VG_(free)(str);
   1524                   }
   1525                }
   1526             }
   1527          }
   1528       }
   1529    }
   1530 
   1531    s_conflict_set_bitmap_creation_count
   1532       += DRD_(bm_get_bitmap_creation_count)();
   1533    s_conflict_set_bitmap2_creation_count
   1534       += DRD_(bm_get_bitmap2_creation_count)();
   1535 
   1536    if (s_trace_conflict_set_bm) {
   1537       VG_(message)(Vg_DebugMsg, "[%u] new conflict set:\n", tid);
   1538       DRD_(bm_print)(*conflict_set);
   1539       VG_(message)(Vg_DebugMsg, "[%u] end of new conflict set.\n", tid);
   1540    }
   1541 }
   1542 
   1543 /**
   1544  * Update the conflict set after the vector clock of thread tid has been
   1545  * updated from old_vc to its current value, either because a new segment has
   1546  * been created or because of a synchronization operation.
   1547  */
   1548 void DRD_(thread_update_conflict_set)(const DrdThreadId tid,
   1549                                       const VectorClock* const old_vc)
   1550 {
   1551    const VectorClock* new_vc;
   1552    Segment* p;
   1553    unsigned j;
   1554 
   1555    tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
   1556              && tid != DRD_INVALID_THREADID);
   1557    tl_assert(old_vc);
   1558    tl_assert(tid == DRD_(g_drd_running_tid));
   1559    tl_assert(DRD_(g_conflict_set));
   1560 
   1561    if (s_trace_conflict_set) {
   1562       HChar* str;
   1563 
   1564       str = DRD_(vc_aprint)(DRD_(thread_get_vc)(tid));
   1565       VG_(message)(Vg_DebugMsg,
   1566                    "updating conflict set for thread %u with vc %s\n",
   1567                    tid, str);
   1568       VG_(free)(str);
   1569    }
   1570 
   1571    new_vc = DRD_(thread_get_vc)(tid);
   1572    tl_assert(DRD_(vc_lte)(old_vc, new_vc));
   1573 
   1574    DRD_(bm_unmark)(DRD_(g_conflict_set));
   1575 
   1576    for (j = 0; j < DRD_N_THREADS; j++)
   1577    {
   1578       Segment* q;
   1579 
   1580       if (j == tid || ! DRD_(IsValidDrdThreadId)(j))
   1581          continue;
   1582 
   1583       for (q = DRD_(g_threadinfo)[j].sg_last;
   1584            q && !DRD_(vc_lte)(&q->vc, new_vc);
   1585            q = q->thr_prev) {
   1586          const Bool included_in_old_conflict_set
   1587             = !DRD_(vc_lte)(old_vc, &q->vc);
   1588          const Bool included_in_new_conflict_set
   1589             = !DRD_(vc_lte)(new_vc, &q->vc);
   1590 
   1591          if (UNLIKELY(s_trace_conflict_set)) {
   1592             HChar* str;
   1593 
   1594             str = DRD_(vc_aprint)(&q->vc);
   1595             VG_(message)(Vg_DebugMsg,
   1596                          "conflict set: [%u] %s segment %s\n", j,
   1597                          included_in_old_conflict_set
   1598                          != included_in_new_conflict_set
   1599                          ? "merging" : "ignoring", str);
   1600             VG_(free)(str);
   1601          }
   1602          if (included_in_old_conflict_set != included_in_new_conflict_set)
   1603             DRD_(bm_mark)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
   1604       }
   1605 
   1606       for ( ; q && !DRD_(vc_lte)(&q->vc, old_vc); q = q->thr_prev) {
   1607          const Bool included_in_old_conflict_set
   1608             = !DRD_(vc_lte)(old_vc, &q->vc);
   1609          const Bool included_in_new_conflict_set
   1610             = !DRD_(vc_lte)(&q->vc, new_vc)
   1611             && !DRD_(vc_lte)(new_vc, &q->vc);
   1612 
   1613          if (UNLIKELY(s_trace_conflict_set)) {
   1614             HChar* str;
   1615 
   1616             str = DRD_(vc_aprint)(&q->vc);
   1617             VG_(message)(Vg_DebugMsg,
   1618                          "conflict set: [%u] %s segment %s\n", j,
   1619                          included_in_old_conflict_set
   1620                          != included_in_new_conflict_set
   1621                          ? "merging" : "ignoring", str);
   1622             VG_(free)(str);
   1623          }
   1624          if (included_in_old_conflict_set != included_in_new_conflict_set)
   1625             DRD_(bm_mark)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
   1626       }
   1627    }
   1628 
   1629    DRD_(bm_clear_marked)(DRD_(g_conflict_set));
   1630 
   1631    p = DRD_(g_threadinfo)[tid].sg_last;
   1632    for (j = 0; j < DRD_N_THREADS; j++) {
   1633       if (j != tid && DRD_(IsValidDrdThreadId)(j)) {
   1634          Segment* q;
   1635          for (q = DRD_(g_threadinfo)[j].sg_last;
   1636               q && !DRD_(vc_lte)(&q->vc, &p->vc);
   1637               q = q->thr_prev) {
   1638             if (!DRD_(vc_lte)(&p->vc, &q->vc))
   1639                DRD_(bm_merge2_marked)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
   1640          }
   1641       }
   1642    }
   1643 
   1644    DRD_(bm_remove_cleared_marked)(DRD_(g_conflict_set));
   1645 
   1646    s_update_conflict_set_count++;
   1647 
   1648    if (s_trace_conflict_set_bm)
   1649    {
   1650       VG_(message)(Vg_DebugMsg, "[%u] updated conflict set:\n", tid);
   1651       DRD_(bm_print)(DRD_(g_conflict_set));
   1652       VG_(message)(Vg_DebugMsg, "[%u] end of updated conflict set.\n", tid);
   1653    }
   1654 
   1655    tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
   1656 }
   1657 
   1658 /** Report the number of context switches performed. */
   1659 ULong DRD_(thread_get_context_switch_count)(void)
   1660 {
   1661    return s_context_switch_count;
   1662 }
   1663 
   1664 /** Report the number of ordered segments that have been discarded. */
   1665 ULong DRD_(thread_get_discard_ordered_segments_count)(void)
   1666 {
   1667    return s_discard_ordered_segments_count;
   1668 }
   1669 
   1670 /** Return how many times the conflict set has been updated entirely. */
   1671 ULong DRD_(thread_get_compute_conflict_set_count)()
   1672 {
   1673    return s_compute_conflict_set_count;
   1674 }
   1675 
   1676 /** Return how many times the conflict set has been updated partially. */
   1677 ULong DRD_(thread_get_update_conflict_set_count)(void)
   1678 {
   1679    return s_update_conflict_set_count;
   1680 }
   1681 
   1682 /**
   1683  * Return how many times the conflict set has been updated partially
   1684  * because a new segment has been created.
   1685  */
   1686 ULong DRD_(thread_get_update_conflict_set_new_sg_count)(void)
   1687 {
   1688    return s_update_conflict_set_new_sg_count;
   1689 }
   1690 
   1691 /**
   1692  * Return how many times the conflict set has been updated partially
   1693  * because of combining vector clocks due to synchronization operations
   1694  * other than reader/writer lock or barrier operations.
   1695  */
   1696 ULong DRD_(thread_get_update_conflict_set_sync_count)(void)
   1697 {
   1698    return s_update_conflict_set_sync_count;
   1699 }
   1700 
   1701 /**
   1702  * Return how many times the conflict set has been updated partially
   1703  * because of thread joins.
   1704  */
   1705 ULong DRD_(thread_get_update_conflict_set_join_count)(void)
   1706 {
   1707    return s_update_conflict_set_join_count;
   1708 }
   1709 
   1710 /**
   1711  * Return the number of first-level bitmaps that have been created during
   1712  * conflict set updates.
   1713  */
   1714 ULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void)
   1715 {
   1716    return s_conflict_set_bitmap_creation_count;
   1717 }
   1718 
   1719 /**
   1720  * Return the number of second-level bitmaps that have been created during
   1721  * conflict set updates.
   1722  */
   1723 ULong DRD_(thread_get_conflict_set_bitmap2_creation_count)(void)
   1724 {
   1725    return s_conflict_set_bitmap2_creation_count;
   1726 }
   1727