1af44c8236f7a73e71b16b707bba56f33af4d01cesewardj/*
286562bd89ac23ce795d19c71fabcb9d1c8f956d3bart  This file is part of drd, a thread error detector.
3af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
4d4bab99f83dbc53665c5769c3f6b50ffcd2a9a7dbart  Copyright (C) 2006-2013 Bart Van Assche <bvanassche@acm.org>.
5af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
6af44c8236f7a73e71b16b707bba56f33af4d01cesewardj  This program is free software; you can redistribute it and/or
7af44c8236f7a73e71b16b707bba56f33af4d01cesewardj  modify it under the terms of the GNU General Public License as
8af44c8236f7a73e71b16b707bba56f33af4d01cesewardj  published by the Free Software Foundation; either version 2 of the
9af44c8236f7a73e71b16b707bba56f33af4d01cesewardj  License, or (at your option) any later version.
10af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
11af44c8236f7a73e71b16b707bba56f33af4d01cesewardj  This program is distributed in the hope that it will be useful, but
12af44c8236f7a73e71b16b707bba56f33af4d01cesewardj  WITHOUT ANY WARRANTY; without even the implied warranty of
13af44c8236f7a73e71b16b707bba56f33af4d01cesewardj  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14af44c8236f7a73e71b16b707bba56f33af4d01cesewardj  General Public License for more details.
15af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
16af44c8236f7a73e71b16b707bba56f33af4d01cesewardj  You should have received a copy of the GNU General Public License
17af44c8236f7a73e71b16b707bba56f33af4d01cesewardj  along with this program; if not, write to the Free Software
18af44c8236f7a73e71b16b707bba56f33af4d01cesewardj  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19af44c8236f7a73e71b16b707bba56f33af4d01cesewardj  02111-1307, USA.
20af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
21af44c8236f7a73e71b16b707bba56f33af4d01cesewardj  The GNU General Public License is contained in the file COPYING.
22af44c8236f7a73e71b16b707bba56f33af4d01cesewardj*/
23af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
24af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
25af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "drd_error.h"
2609dc13f324a19f1bebf58c7f197a581dc8fb528bbart#include "drd_barrier.h"
27d2c5eae561040706a7eb45c0f3988dcd538c8d7ebart#include "drd_clientobj.h"
2809dc13f324a19f1bebf58c7f197a581dc8fb528bbart#include "drd_cond.h"
2909dc13f324a19f1bebf58c7f197a581dc8fb528bbart#include "drd_mutex.h"
30af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "drd_segment.h"
3109dc13f324a19f1bebf58c7f197a581dc8fb528bbart#include "drd_semaphore.h"
32af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "drd_suppression.h"
33af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "drd_thread.h"
3482195c18d79b2e8c0e33d3c9e1b73cfa2e33c6c1bart#include "pub_tool_vki.h"
35af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "pub_tool_basics.h"      // Addr, SizeT
36af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "pub_tool_libcassert.h"  // tl_assert()
37af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "pub_tool_libcbase.h"    // VG_(strlen)()
38af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "pub_tool_libcprint.h"   // VG_(printf)()
39af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "pub_tool_machine.h"
40af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "pub_tool_mallocfree.h"  // VG_(malloc)(), VG_(free)()
418564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_options.h"     // VG_(clo_backtrace_size)
42af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "pub_tool_threadstate.h" // VG_(get_pthread_id)()
43af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
4432ba208a4ad813d2045a75e813ac8658390595f7bart
45af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
46324a23bea57e0bfc27d9442ec00a8eee8294f01abart/* Local functions. */
47af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
4886a87df5949beb1f89ebbed923068faed08d048cbartstatic void thread_append_segment(const DrdThreadId tid, Segment* const sg);
4986a87df5949beb1f89ebbed923068faed08d048cbartstatic void thread_discard_segment(const DrdThreadId tid, Segment* const sg);
5086a87df5949beb1f89ebbed923068faed08d048cbartstatic void thread_compute_conflict_set(struct bitmap** conflict_set,
5186a87df5949beb1f89ebbed923068faed08d048cbart                                        const DrdThreadId tid);
528f822af9b234e7c553c408eba65a641c4773457fbartstatic Bool thread_conflict_set_up_to_date(const DrdThreadId tid);
53af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
54af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
55324a23bea57e0bfc27d9442ec00a8eee8294f01abart/* Local variables. */
56af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
5786a87df5949beb1f89ebbed923068faed08d048cbartstatic ULong    s_context_switch_count;
5886a87df5949beb1f89ebbed923068faed08d048cbartstatic ULong    s_discard_ordered_segments_count;
5954803feb0b92e4708d3cee92e7449f802be70197bartstatic ULong    s_compute_conflict_set_count;
6086a87df5949beb1f89ebbed923068faed08d048cbartstatic ULong    s_update_conflict_set_count;
61e5214666ead5aebb79ad662deacff0a952cba70dbartstatic ULong    s_update_conflict_set_new_sg_count;
62e5214666ead5aebb79ad662deacff0a952cba70dbartstatic ULong    s_update_conflict_set_sync_count;
63e5214666ead5aebb79ad662deacff0a952cba70dbartstatic ULong    s_update_conflict_set_join_count;
6486a87df5949beb1f89ebbed923068faed08d048cbartstatic ULong    s_conflict_set_bitmap_creation_count;
6586a87df5949beb1f89ebbed923068faed08d048cbartstatic ULong    s_conflict_set_bitmap2_creation_count;
6686a87df5949beb1f89ebbed923068faed08d048cbartstatic ThreadId s_vg_running_tid  = VG_INVALID_THREADID;
67324a23bea57e0bfc27d9442ec00a8eee8294f01abartDrdThreadId     DRD_(g_drd_running_tid) = DRD_INVALID_THREADID;
681e802b6a8d0d4b7b630d2a1dd9683c7c889b01a3florianThreadInfo*     DRD_(g_threadinfo);
69324a23bea57e0bfc27d9442ec00a8eee8294f01abartstruct bitmap*  DRD_(g_conflict_set);
709cdc08368068d746e42d40c8f3a3dca5db5caee4bartBool DRD_(verify_conflict_set);
7186a87df5949beb1f89ebbed923068faed08d048cbartstatic Bool     s_trace_context_switches = False;
7286a87df5949beb1f89ebbed923068faed08d048cbartstatic Bool     s_trace_conflict_set = False;
738f822af9b234e7c553c408eba65a641c4773457fbartstatic Bool     s_trace_conflict_set_bm = False;
7486a87df5949beb1f89ebbed923068faed08d048cbartstatic Bool     s_trace_fork_join = False;
7586a87df5949beb1f89ebbed923068faed08d048cbartstatic Bool     s_segment_merging = True;
768f822af9b234e7c553c408eba65a641c4773457fbartstatic Bool     s_new_segments_since_last_merge;
776f1d7165e418f1d8d255b5d4e93a5df3c1e5e659bartstatic int      s_segment_merge_interval = 10;
786d956dc21b6a81f0c67ad18ac61867da0d5922a3bartstatic unsigned s_join_list_vol = 10;
796d956dc21b6a81f0c67ad18ac61867da0d5922a3bartstatic unsigned s_deletion_head;
806d956dc21b6a81f0c67ad18ac61867da0d5922a3bartstatic unsigned s_deletion_tail;
81af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
82af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
83324a23bea57e0bfc27d9442ec00a8eee8294f01abart/* Function definitions. */
84af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
8586a87df5949beb1f89ebbed923068faed08d048cbart/** Enables/disables context switch tracing. */
8662a784c9382fdf7184065ad76ae8d3b905605f21bartvoid DRD_(thread_trace_context_switches)(const Bool t)
8726f73e12ef03bb04ebee5cccd8da08cddb426341bart{
88bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(t == False || t == True);
89bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   s_trace_context_switches = t;
9026f73e12ef03bb04ebee5cccd8da08cddb426341bart}
9126f73e12ef03bb04ebee5cccd8da08cddb426341bart
9286a87df5949beb1f89ebbed923068faed08d048cbart/** Enables/disables conflict set tracing. */
9362a784c9382fdf7184065ad76ae8d3b905605f21bartvoid DRD_(thread_trace_conflict_set)(const Bool t)
9426f73e12ef03bb04ebee5cccd8da08cddb426341bart{
95bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(t == False || t == True);
96bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   s_trace_conflict_set = t;
9726f73e12ef03bb04ebee5cccd8da08cddb426341bart}
9826f73e12ef03bb04ebee5cccd8da08cddb426341bart
998f822af9b234e7c553c408eba65a641c4773457fbart/** Enables/disables conflict set bitmap tracing. */
1008f822af9b234e7c553c408eba65a641c4773457fbartvoid DRD_(thread_trace_conflict_set_bm)(const Bool t)
1018f822af9b234e7c553c408eba65a641c4773457fbart{
1028f822af9b234e7c553c408eba65a641c4773457fbart   tl_assert(t == False || t == True);
1038f822af9b234e7c553c408eba65a641c4773457fbart   s_trace_conflict_set_bm = t;
1048f822af9b234e7c553c408eba65a641c4773457fbart}
1058f822af9b234e7c553c408eba65a641c4773457fbart
10686a87df5949beb1f89ebbed923068faed08d048cbart/** Report whether fork/join tracing is enabled. */
10709dc13f324a19f1bebf58c7f197a581dc8fb528bbartBool DRD_(thread_get_trace_fork_join)(void)
10809dc13f324a19f1bebf58c7f197a581dc8fb528bbart{
109bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return s_trace_fork_join;
11009dc13f324a19f1bebf58c7f197a581dc8fb528bbart}
11109dc13f324a19f1bebf58c7f197a581dc8fb528bbart
11286a87df5949beb1f89ebbed923068faed08d048cbart/** Enables/disables fork/join tracing. */
11309dc13f324a19f1bebf58c7f197a581dc8fb528bbartvoid DRD_(thread_set_trace_fork_join)(const Bool t)
11409dc13f324a19f1bebf58c7f197a581dc8fb528bbart{
115bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(t == False || t == True);
116bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   s_trace_fork_join = t;
11709dc13f324a19f1bebf58c7f197a581dc8fb528bbart}
11809dc13f324a19f1bebf58c7f197a581dc8fb528bbart
11986a87df5949beb1f89ebbed923068faed08d048cbart/** Enables/disables segment merging. */
12062a784c9382fdf7184065ad76ae8d3b905605f21bartvoid DRD_(thread_set_segment_merging)(const Bool m)
121a9c37398e4565280266ce663a6c38c3518af2812bart{
122bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(m == False || m == True);
123bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   s_segment_merging = m;
124a9c37398e4565280266ce663a6c38c3518af2812bart}
125a9c37398e4565280266ce663a6c38c3518af2812bart
1268f822af9b234e7c553c408eba65a641c4773457fbart/** Get the segment merging interval. */
1278f822af9b234e7c553c408eba65a641c4773457fbartint DRD_(thread_get_segment_merge_interval)(void)
1288f822af9b234e7c553c408eba65a641c4773457fbart{
1298f822af9b234e7c553c408eba65a641c4773457fbart   return s_segment_merge_interval;
1308f822af9b234e7c553c408eba65a641c4773457fbart}
1318f822af9b234e7c553c408eba65a641c4773457fbart
1328f822af9b234e7c553c408eba65a641c4773457fbart/** Set the segment merging interval. */
1338f822af9b234e7c553c408eba65a641c4773457fbartvoid DRD_(thread_set_segment_merge_interval)(const int i)
1348f822af9b234e7c553c408eba65a641c4773457fbart{
1358f822af9b234e7c553c408eba65a641c4773457fbart   s_segment_merge_interval = i;
1368f822af9b234e7c553c408eba65a641c4773457fbart}
1378f822af9b234e7c553c408eba65a641c4773457fbart
1386d956dc21b6a81f0c67ad18ac61867da0d5922a3bartvoid DRD_(thread_set_join_list_vol)(const int jlv)
1396d956dc21b6a81f0c67ad18ac61867da0d5922a3bart{
1406d956dc21b6a81f0c67ad18ac61867da0d5922a3bart   s_join_list_vol = jlv;
1416d956dc21b6a81f0c67ad18ac61867da0d5922a3bart}
1426d956dc21b6a81f0c67ad18ac61867da0d5922a3bart
143e278ab506b9a73ef1c17a17077546b2de9a11d7cbartvoid DRD_(thread_init)(void)
144e278ab506b9a73ef1c17a17077546b2de9a11d7cbart{
1451e802b6a8d0d4b7b630d2a1dd9683c7c889b01a3florian   DRD_(g_threadinfo) = VG_(malloc)("drd.main.ti.1",
1461e802b6a8d0d4b7b630d2a1dd9683c7c889b01a3florian                                DRD_N_THREADS * sizeof DRD_(g_threadinfo)[0]);
1471e802b6a8d0d4b7b630d2a1dd9683c7c889b01a3florian   for (UInt i = 0; i < DRD_N_THREADS; ++i) {
1481e802b6a8d0d4b7b630d2a1dd9683c7c889b01a3florian      static ThreadInfo initval;
1491e802b6a8d0d4b7b630d2a1dd9683c7c889b01a3florian      DRD_(g_threadinfo)[i] = initval;
1501e802b6a8d0d4b7b630d2a1dd9683c7c889b01a3florian   }
151e278ab506b9a73ef1c17a17077546b2de9a11d7cbart}
152e278ab506b9a73ef1c17a17077546b2de9a11d7cbart
153af44c8236f7a73e71b16b707bba56f33af4d01cesewardj/**
15486a87df5949beb1f89ebbed923068faed08d048cbart * Convert Valgrind's ThreadId into a DrdThreadId.
15586a87df5949beb1f89ebbed923068faed08d048cbart *
15686a87df5949beb1f89ebbed923068faed08d048cbart * @return DRD thread ID upon success and DRD_INVALID_THREADID if the passed
15786a87df5949beb1f89ebbed923068faed08d048cbart *         Valgrind ThreadId does not yet exist.
158324a23bea57e0bfc27d9442ec00a8eee8294f01abart */
15962a784c9382fdf7184065ad76ae8d3b905605f21bartDrdThreadId DRD_(VgThreadIdToDrdThreadId)(const ThreadId tid)
160af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
1611e802b6a8d0d4b7b630d2a1dd9683c7c889b01a3florian   UInt i;
162af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
163bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (tid == VG_INVALID_THREADID)
164bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      return DRD_INVALID_THREADID;
165af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
166bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   for (i = 1; i < DRD_N_THREADS; i++)
167bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
168bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      if (DRD_(g_threadinfo)[i].vg_thread_exists == True
169bedfd237fbdc80d0c917cfcb85a94b5561c92633bart          && DRD_(g_threadinfo)[i].vg_threadid == tid)
170bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      {
171bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         return i;
172bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      }
173bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
174af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
175bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return DRD_INVALID_THREADID;
176af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
177af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
17886a87df5949beb1f89ebbed923068faed08d048cbart/** Allocate a new DRD thread ID for the specified Valgrind thread ID. */
17962a784c9382fdf7184065ad76ae8d3b905605f21bartstatic DrdThreadId DRD_(VgThreadIdToNewDrdThreadId)(const ThreadId tid)
180af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
1811e802b6a8d0d4b7b630d2a1dd9683c7c889b01a3florian   UInt i;
182bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
183bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(DRD_(VgThreadIdToDrdThreadId)(tid) == DRD_INVALID_THREADID);
184bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
185bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   for (i = 1; i < DRD_N_THREADS; i++)
186bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
1876d956dc21b6a81f0c67ad18ac61867da0d5922a3bart      if (!DRD_(g_threadinfo)[i].valid)
188bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      {
189bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         tl_assert(! DRD_(IsValidDrdThreadId)(i));
190bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
1916d956dc21b6a81f0c67ad18ac61867da0d5922a3bart         DRD_(g_threadinfo)[i].valid         = True;
192bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         DRD_(g_threadinfo)[i].vg_thread_exists = True;
193bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         DRD_(g_threadinfo)[i].vg_threadid   = tid;
194bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         DRD_(g_threadinfo)[i].pt_threadid   = INVALID_POSIX_THREADID;
195bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         DRD_(g_threadinfo)[i].stack_min     = 0;
196bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         DRD_(g_threadinfo)[i].stack_min_min = 0;
197bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         DRD_(g_threadinfo)[i].stack_startup = 0;
198bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         DRD_(g_threadinfo)[i].stack_max     = 0;
199d45d99553c15a361bb797d21ec6afb9bad22d2d4bart         DRD_(thread_set_name)(i, "");
200383d613d286501412f1760c8eaafaeb8c518b344bart         DRD_(g_threadinfo)[i].on_alt_stack        = False;
201d45d99553c15a361bb797d21ec6afb9bad22d2d4bart         DRD_(g_threadinfo)[i].is_recording_loads  = True;
202d45d99553c15a361bb797d21ec6afb9bad22d2d4bart         DRD_(g_threadinfo)[i].is_recording_stores = True;
203dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart         DRD_(g_threadinfo)[i].pthread_create_nesting_level = 0;
204bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         DRD_(g_threadinfo)[i].synchr_nesting = 0;
2056d956dc21b6a81f0c67ad18ac61867da0d5922a3bart         DRD_(g_threadinfo)[i].deletion_seq = s_deletion_tail - 1;
20691b7ec3660efe16790bc337190a1c948beaab0a5bart         tl_assert(DRD_(g_threadinfo)[i].sg_first == NULL);
20791b7ec3660efe16790bc337190a1c948beaab0a5bart         tl_assert(DRD_(g_threadinfo)[i].sg_last == NULL);
208bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
209bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         tl_assert(DRD_(IsValidDrdThreadId)(i));
210bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
211bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         return i;
212bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      }
213bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
214bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
2153c9afb10ad9854fd81d20b3a4b4aba3e230ec196bart   VG_(printf)(
2163c9afb10ad9854fd81d20b3a4b4aba3e230ec196bart"\nSorry, but the maximum number of threads supported by DRD has been exceeded."
2173c9afb10ad9854fd81d20b3a4b4aba3e230ec196bart"Aborting.\n");
2183c9afb10ad9854fd81d20b3a4b4aba3e230ec196bart
219bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(False);
220bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
221bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return DRD_INVALID_THREADID;
222af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
223af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
22486a87df5949beb1f89ebbed923068faed08d048cbart/** Convert a POSIX thread ID into a DRD thread ID. */
22562a784c9382fdf7184065ad76ae8d3b905605f21bartDrdThreadId DRD_(PtThreadIdToDrdThreadId)(const PThreadId tid)
226af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
2271e802b6a8d0d4b7b630d2a1dd9683c7c889b01a3florian   UInt i;
228bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
229b48bde21f5107f74335b88cacee76c556ae22aa7bart   if (tid != INVALID_POSIX_THREADID)
230bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
231b48bde21f5107f74335b88cacee76c556ae22aa7bart      for (i = 1; i < DRD_N_THREADS; i++)
232bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      {
233b48bde21f5107f74335b88cacee76c556ae22aa7bart         if (DRD_(g_threadinfo)[i].posix_thread_exists
234b48bde21f5107f74335b88cacee76c556ae22aa7bart             && DRD_(g_threadinfo)[i].pt_threadid == tid)
235b48bde21f5107f74335b88cacee76c556ae22aa7bart         {
236b48bde21f5107f74335b88cacee76c556ae22aa7bart            return i;
237b48bde21f5107f74335b88cacee76c556ae22aa7bart         }
238bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      }
239bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
240bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return DRD_INVALID_THREADID;
241af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
242af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
24386a87df5949beb1f89ebbed923068faed08d048cbart/** Convert a DRD thread ID into a Valgrind thread ID. */
24462a784c9382fdf7184065ad76ae8d3b905605f21bartThreadId DRD_(DrdThreadIdToVgThreadId)(const DrdThreadId tid)
245af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
246bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
247bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
2488f822af9b234e7c553c408eba65a641c4773457fbart
249bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return (DRD_(g_threadinfo)[tid].vg_thread_exists
250bedfd237fbdc80d0c917cfcb85a94b5561c92633bart           ? DRD_(g_threadinfo)[tid].vg_threadid
251bedfd237fbdc80d0c917cfcb85a94b5561c92633bart           : VG_INVALID_THREADID);
252af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
253af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
2548f822af9b234e7c553c408eba65a641c4773457fbart#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
255324a23bea57e0bfc27d9442ec00a8eee8294f01abart/**
256324a23bea57e0bfc27d9442ec00a8eee8294f01abart * Sanity check of the doubly linked list of segments referenced by a
257324a23bea57e0bfc27d9442ec00a8eee8294f01abart * ThreadInfo struct.
258324a23bea57e0bfc27d9442ec00a8eee8294f01abart * @return True if sane, False if not.
259af44c8236f7a73e71b16b707bba56f33af4d01cesewardj */
26062a784c9382fdf7184065ad76ae8d3b905605f21bartstatic Bool DRD_(sane_ThreadInfo)(const ThreadInfo* const ti)
261af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
262bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   Segment* p;
2638f822af9b234e7c553c408eba65a641c4773457fbart
2642bf4bb9d10c2a6d034226a6270c4249d5502325ebart   for (p = ti->sg_first; p; p = p->thr_next) {
2652bf4bb9d10c2a6d034226a6270c4249d5502325ebart      if (p->thr_next && p->thr_next->thr_prev != p)
266bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         return False;
2672bf4bb9d10c2a6d034226a6270c4249d5502325ebart      if (p->thr_next == 0 && p != ti->sg_last)
268bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         return False;
269bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
2702bf4bb9d10c2a6d034226a6270c4249d5502325ebart   for (p = ti->sg_last; p; p = p->thr_prev) {
2712bf4bb9d10c2a6d034226a6270c4249d5502325ebart      if (p->thr_prev && p->thr_prev->thr_next != p)
272bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         return False;
2732bf4bb9d10c2a6d034226a6270c4249d5502325ebart      if (p->thr_prev == 0 && p != ti->sg_first)
274bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         return False;
275bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
276bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return True;
277af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
27823d3a4ee2197365501050264eb55dddcd39034d5bart#endif
279af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
280439c55fe48f6b3d0e2622b45d0ad8d8acc383398bart/**
281439c55fe48f6b3d0e2622b45d0ad8d8acc383398bart * Create the first segment for a newly started thread.
282439c55fe48f6b3d0e2622b45d0ad8d8acc383398bart *
283439c55fe48f6b3d0e2622b45d0ad8d8acc383398bart * This function is called from the handler installed via
284439c55fe48f6b3d0e2622b45d0ad8d8acc383398bart * VG_(track_pre_thread_ll_create)(). The Valgrind core invokes this handler
285439c55fe48f6b3d0e2622b45d0ad8d8acc383398bart * from the context of the creator thread, before the new thread has been
286439c55fe48f6b3d0e2622b45d0ad8d8acc383398bart * created.
28786a87df5949beb1f89ebbed923068faed08d048cbart *
28886a87df5949beb1f89ebbed923068faed08d048cbart * @param[in] creator    DRD thread ID of the creator thread.
28986a87df5949beb1f89ebbed923068faed08d048cbart * @param[in] vg_created Valgrind thread ID of the created thread.
29086a87df5949beb1f89ebbed923068faed08d048cbart *
29186a87df5949beb1f89ebbed923068faed08d048cbart * @return DRD thread ID of the created thread.
292439c55fe48f6b3d0e2622b45d0ad8d8acc383398bart */
29362a784c9382fdf7184065ad76ae8d3b905605f21bartDrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator,
29462a784c9382fdf7184065ad76ae8d3b905605f21bart                                    const ThreadId vg_created)
295af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
296bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DrdThreadId created;
297af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
298bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_created) == DRD_INVALID_THREADID);
299bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   created = DRD_(VgThreadIdToNewDrdThreadId)(vg_created);
300bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)created && created < DRD_N_THREADS
301bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && created != DRD_INVALID_THREADID);
302af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
30391b7ec3660efe16790bc337190a1c948beaab0a5bart   tl_assert(DRD_(g_threadinfo)[created].sg_first == NULL);
30491b7ec3660efe16790bc337190a1c948beaab0a5bart   tl_assert(DRD_(g_threadinfo)[created].sg_last == NULL);
3058f822af9b234e7c553c408eba65a641c4773457fbart   /* Create an initial segment for the newly created thread. */
306bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   thread_append_segment(created, DRD_(sg_new)(creator, created));
307af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
308bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return created;
309af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
310af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
311439c55fe48f6b3d0e2622b45d0ad8d8acc383398bart/**
31286a87df5949beb1f89ebbed923068faed08d048cbart * Initialize DRD_(g_threadinfo)[] for a newly created thread. Must be called
31386a87df5949beb1f89ebbed923068faed08d048cbart * after the thread has been created and before any client instructions are run
314439c55fe48f6b3d0e2622b45d0ad8d8acc383398bart * on the newly created thread, e.g. from the handler installed via
315439c55fe48f6b3d0e2622b45d0ad8d8acc383398bart * VG_(track_pre_thread_first_insn)().
31686a87df5949beb1f89ebbed923068faed08d048cbart *
31786a87df5949beb1f89ebbed923068faed08d048cbart * @param[in] vg_created Valgrind thread ID of the newly created thread.
31886a87df5949beb1f89ebbed923068faed08d048cbart *
31986a87df5949beb1f89ebbed923068faed08d048cbart * @return DRD thread ID for the new thread.
320439c55fe48f6b3d0e2622b45d0ad8d8acc383398bart */
32162a784c9382fdf7184065ad76ae8d3b905605f21bartDrdThreadId DRD_(thread_post_create)(const ThreadId vg_created)
322439c55fe48f6b3d0e2622b45d0ad8d8acc383398bart{
323bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   const DrdThreadId created = DRD_(VgThreadIdToDrdThreadId)(vg_created);
324bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
325bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)created && created < DRD_N_THREADS
326bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && created != DRD_INVALID_THREADID);
327bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
328bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(g_threadinfo)[created].stack_max
329bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      = VG_(thread_get_stack_max)(vg_created);
330bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(g_threadinfo)[created].stack_startup
331bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      = DRD_(g_threadinfo)[created].stack_max;
332bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(g_threadinfo)[created].stack_min
333bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      = DRD_(g_threadinfo)[created].stack_max;
334bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(g_threadinfo)[created].stack_min_min
335bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      = DRD_(g_threadinfo)[created].stack_max;
336bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(g_threadinfo)[created].stack_size
337bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      = VG_(thread_get_stack_size)(vg_created);
338bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(DRD_(g_threadinfo)[created].stack_max != 0);
339bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
340bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return created;
341439c55fe48f6b3d0e2622b45d0ad8d8acc383398bart}
34209dc13f324a19f1bebf58c7f197a581dc8fb528bbart
3436d956dc21b6a81f0c67ad18ac61867da0d5922a3bartstatic void DRD_(thread_delayed_delete)(const DrdThreadId tid)
3446d956dc21b6a81f0c67ad18ac61867da0d5922a3bart{
3451e802b6a8d0d4b7b630d2a1dd9683c7c889b01a3florian   UInt j;
3466d956dc21b6a81f0c67ad18ac61867da0d5922a3bart
3476d956dc21b6a81f0c67ad18ac61867da0d5922a3bart   DRD_(g_threadinfo)[tid].vg_thread_exists = False;
3486d956dc21b6a81f0c67ad18ac61867da0d5922a3bart   DRD_(g_threadinfo)[tid].posix_thread_exists = False;
3496d956dc21b6a81f0c67ad18ac61867da0d5922a3bart   DRD_(g_threadinfo)[tid].deletion_seq = s_deletion_head++;
3506d956dc21b6a81f0c67ad18ac61867da0d5922a3bart#if 0
3516d956dc21b6a81f0c67ad18ac61867da0d5922a3bart   VG_(message)(Vg_DebugMsg, "Adding thread %d to the deletion list\n", tid);
3526d956dc21b6a81f0c67ad18ac61867da0d5922a3bart#endif
3536d956dc21b6a81f0c67ad18ac61867da0d5922a3bart   if (s_deletion_head - s_deletion_tail >= s_join_list_vol) {
3546d956dc21b6a81f0c67ad18ac61867da0d5922a3bart      for (j = 0; j < DRD_N_THREADS; ++j) {
3556d956dc21b6a81f0c67ad18ac61867da0d5922a3bart         if (DRD_(IsValidDrdThreadId)(j)
3566d956dc21b6a81f0c67ad18ac61867da0d5922a3bart             && DRD_(g_threadinfo)[j].deletion_seq == s_deletion_tail)
3576d956dc21b6a81f0c67ad18ac61867da0d5922a3bart         {
3586d956dc21b6a81f0c67ad18ac61867da0d5922a3bart            s_deletion_tail++;
3596d956dc21b6a81f0c67ad18ac61867da0d5922a3bart#if 0
3606d956dc21b6a81f0c67ad18ac61867da0d5922a3bart            VG_(message)(Vg_DebugMsg, "Delayed delete of thread %d\n", j);
3616d956dc21b6a81f0c67ad18ac61867da0d5922a3bart#endif
3626d956dc21b6a81f0c67ad18ac61867da0d5922a3bart            DRD_(thread_delete)(j, False);
3636d956dc21b6a81f0c67ad18ac61867da0d5922a3bart            break;
3646d956dc21b6a81f0c67ad18ac61867da0d5922a3bart         }
3656d956dc21b6a81f0c67ad18ac61867da0d5922a3bart      }
3666d956dc21b6a81f0c67ad18ac61867da0d5922a3bart   }
3676d956dc21b6a81f0c67ad18ac61867da0d5922a3bart}
3686d956dc21b6a81f0c67ad18ac61867da0d5922a3bart
369324a23bea57e0bfc27d9442ec00a8eee8294f01abart/**
370324a23bea57e0bfc27d9442ec00a8eee8294f01abart * Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just
371324a23bea57e0bfc27d9442ec00a8eee8294f01abart * after thread drd_joiner joined thread drd_joinee.
372324a23bea57e0bfc27d9442ec00a8eee8294f01abart */
37309dc13f324a19f1bebf58c7f197a581dc8fb528bbartvoid DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
37409dc13f324a19f1bebf58c7f197a581dc8fb528bbart{
375bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(DRD_(IsValidDrdThreadId)(drd_joiner));
376bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(DRD_(IsValidDrdThreadId)(drd_joinee));
3777627be3e26162e4f59ccfd35eaf31495ddefdf9bbart
378bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(thread_new_segment)(drd_joiner);
3798f822af9b234e7c553c408eba65a641c4773457fbart   DRD_(thread_combine_vc_join)(drd_joiner, drd_joinee);
3807627be3e26162e4f59ccfd35eaf31495ddefdf9bbart   DRD_(thread_new_segment)(drd_joinee);
381bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
382bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (s_trace_fork_join)
383bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
384bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      const ThreadId joiner = DRD_(DrdThreadIdToVgThreadId)(drd_joiner);
385bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      const unsigned msg_size = 256;
38619f91bbaedb4caef8a60ce94b0f507193cc0bc10florian      HChar* msg;
387bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
388bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      msg = VG_(malloc)("drd.main.dptj.1", msg_size);
389f5d8e65f2c61c399420cde0afd70204e0c0f7c4cflorian
390bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      VG_(snprintf)(msg, msg_size,
39163c92ea799549976957f5b4d54ede744f762c56fbart                    "drd_post_thread_join joiner = %d, joinee = %d",
39263c92ea799549976957f5b4d54ede744f762c56fbart                    drd_joiner, drd_joinee);
393bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      if (joiner)
394bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      {
39519f91bbaedb4caef8a60ce94b0f507193cc0bc10florian         HChar* vc;
3968f822af9b234e7c553c408eba65a641c4773457fbart
3978f822af9b234e7c553c408eba65a641c4773457fbart         vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(drd_joiner));
398bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
3998f822af9b234e7c553c408eba65a641c4773457fbart                       ", new vc: %s", vc);
4008f822af9b234e7c553c408eba65a641c4773457fbart         VG_(free)(vc);
401bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      }
402ad994e885caeb5241cbedf4e47e7821cf164f4e7bart      DRD_(trace_msg)("%pS", msg);
403bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      VG_(free)(msg);
404bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
405bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
406bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (!  DRD_(get_check_stack_accesses)())
407bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
408bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      DRD_(finish_suppression)(DRD_(thread_get_stack_max)(drd_joinee)
409bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                               - DRD_(thread_get_stack_size)(drd_joinee),
410bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                               DRD_(thread_get_stack_max)(drd_joinee));
411bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
412bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(clientobj_delete_thread)(drd_joinee);
4136d956dc21b6a81f0c67ad18ac61867da0d5922a3bart   DRD_(thread_delayed_delete)(drd_joinee);
41409dc13f324a19f1bebf58c7f197a581dc8fb528bbart}
41509dc13f324a19f1bebf58c7f197a581dc8fb528bbart
416324a23bea57e0bfc27d9442ec00a8eee8294f01abart/**
417324a23bea57e0bfc27d9442ec00a8eee8294f01abart * NPTL hack: NPTL allocates the 'struct pthread' on top of the stack,
418324a23bea57e0bfc27d9442ec00a8eee8294f01abart * and accesses this data structure from multiple threads without locking.
419324a23bea57e0bfc27d9442ec00a8eee8294f01abart * Any conflicting accesses in the range stack_startup..stack_max will be
420324a23bea57e0bfc27d9442ec00a8eee8294f01abart * ignored.
421324a23bea57e0bfc27d9442ec00a8eee8294f01abart */
42262a784c9382fdf7184065ad76ae8d3b905605f21bartvoid DRD_(thread_set_stack_startup)(const DrdThreadId tid,
42362a784c9382fdf7184065ad76ae8d3b905605f21bart                                    const Addr stack_startup)
424af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
425bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
426bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
427bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(DRD_(g_threadinfo)[tid].stack_min <= stack_startup);
428bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(stack_startup <= DRD_(g_threadinfo)[tid].stack_max);
429bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(g_threadinfo)[tid].stack_startup = stack_startup;
430af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
431af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
43286a87df5949beb1f89ebbed923068faed08d048cbart/** Return the stack pointer for the specified thread. */
43362a784c9382fdf7184065ad76ae8d3b905605f21bartAddr DRD_(thread_get_stack_min)(const DrdThreadId tid)
434af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
435bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
436bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
437bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return DRD_(g_threadinfo)[tid].stack_min;
438af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
439af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
44086a87df5949beb1f89ebbed923068faed08d048cbart/**
44186a87df5949beb1f89ebbed923068faed08d048cbart * Return the lowest value that was ever assigned to the stack pointer
44286a87df5949beb1f89ebbed923068faed08d048cbart * for the specified thread.
44386a87df5949beb1f89ebbed923068faed08d048cbart */
44462a784c9382fdf7184065ad76ae8d3b905605f21bartAddr DRD_(thread_get_stack_min_min)(const DrdThreadId tid)
445cac5346ef470359941b12d879608e5f3386b44febart{
446bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
447bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
448bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return DRD_(g_threadinfo)[tid].stack_min_min;
449cac5346ef470359941b12d879608e5f3386b44febart}
450cac5346ef470359941b12d879608e5f3386b44febart
45186a87df5949beb1f89ebbed923068faed08d048cbart/** Return the top address for the stack of the specified thread. */
45262a784c9382fdf7184065ad76ae8d3b905605f21bartAddr DRD_(thread_get_stack_max)(const DrdThreadId tid)
453af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
454bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
455bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
456bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return DRD_(g_threadinfo)[tid].stack_max;
457af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
458af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
45986a87df5949beb1f89ebbed923068faed08d048cbart/** Return the maximum stack size for the specified thread. */
46062a784c9382fdf7184065ad76ae8d3b905605f21bartSizeT DRD_(thread_get_stack_size)(const DrdThreadId tid)
461cac5346ef470359941b12d879608e5f3386b44febart{
462bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
463bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
464bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return DRD_(g_threadinfo)[tid].stack_size;
465cac5346ef470359941b12d879608e5f3386b44febart}
466cac5346ef470359941b12d879608e5f3386b44febart
467383d613d286501412f1760c8eaafaeb8c518b344bartBool DRD_(thread_get_on_alt_stack)(const DrdThreadId tid)
468383d613d286501412f1760c8eaafaeb8c518b344bart{
469383d613d286501412f1760c8eaafaeb8c518b344bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
470383d613d286501412f1760c8eaafaeb8c518b344bart             && tid != DRD_INVALID_THREADID);
471383d613d286501412f1760c8eaafaeb8c518b344bart   return DRD_(g_threadinfo)[tid].on_alt_stack;
472383d613d286501412f1760c8eaafaeb8c518b344bart}
473383d613d286501412f1760c8eaafaeb8c518b344bart
474383d613d286501412f1760c8eaafaeb8c518b344bartvoid DRD_(thread_set_on_alt_stack)(const DrdThreadId tid,
475383d613d286501412f1760c8eaafaeb8c518b344bart                                   const Bool on_alt_stack)
476383d613d286501412f1760c8eaafaeb8c518b344bart{
477383d613d286501412f1760c8eaafaeb8c518b344bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
478383d613d286501412f1760c8eaafaeb8c518b344bart             && tid != DRD_INVALID_THREADID);
479383d613d286501412f1760c8eaafaeb8c518b344bart   tl_assert(on_alt_stack == !!on_alt_stack);
480383d613d286501412f1760c8eaafaeb8c518b344bart   DRD_(g_threadinfo)[tid].on_alt_stack = on_alt_stack;
481383d613d286501412f1760c8eaafaeb8c518b344bart}
482383d613d286501412f1760c8eaafaeb8c518b344bart
483383d613d286501412f1760c8eaafaeb8c518b344bartInt DRD_(thread_get_threads_on_alt_stack)(void)
484383d613d286501412f1760c8eaafaeb8c518b344bart{
4851e802b6a8d0d4b7b630d2a1dd9683c7c889b01a3florian   int n = 0;
486383d613d286501412f1760c8eaafaeb8c518b344bart
4871e802b6a8d0d4b7b630d2a1dd9683c7c889b01a3florian   for (UInt i = 1; i < DRD_N_THREADS; i++)
488383d613d286501412f1760c8eaafaeb8c518b344bart      n += DRD_(g_threadinfo)[i].on_alt_stack;
489383d613d286501412f1760c8eaafaeb8c518b344bart   return n;
490383d613d286501412f1760c8eaafaeb8c518b344bart}
491383d613d286501412f1760c8eaafaeb8c518b344bart
49209dc13f324a19f1bebf58c7f197a581dc8fb528bbart/**
4936d956dc21b6a81f0c67ad18ac61867da0d5922a3bart * Clean up thread-specific data structures.
494af44c8236f7a73e71b16b707bba56f33af4d01cesewardj */
4959194e93ab737439d653498ee43df4bae7989ad3dbartvoid DRD_(thread_delete)(const DrdThreadId tid, const Bool detached)
496af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
497bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   Segment* sg;
498bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   Segment* sg_prev;
499bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
500bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(DRD_(IsValidDrdThreadId)(tid));
501bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
502bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 0);
50391b7ec3660efe16790bc337190a1c948beaab0a5bart   for (sg = DRD_(g_threadinfo)[tid].sg_last; sg; sg = sg_prev) {
50491b7ec3660efe16790bc337190a1c948beaab0a5bart      sg_prev = sg->thr_prev;
50591b7ec3660efe16790bc337190a1c948beaab0a5bart      sg->thr_next = NULL;
50691b7ec3660efe16790bc337190a1c948beaab0a5bart      sg->thr_prev = NULL;
507bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      DRD_(sg_put)(sg);
508bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
5096d956dc21b6a81f0c67ad18ac61867da0d5922a3bart   DRD_(g_threadinfo)[tid].valid = False;
510bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(g_threadinfo)[tid].vg_thread_exists = False;
511bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(g_threadinfo)[tid].posix_thread_exists = False;
5129194e93ab737439d653498ee43df4bae7989ad3dbart   if (detached)
5139194e93ab737439d653498ee43df4bae7989ad3dbart      DRD_(g_threadinfo)[tid].detached_posix_thread = False;
5149194e93ab737439d653498ee43df4bae7989ad3dbart   else
5159194e93ab737439d653498ee43df4bae7989ad3dbart      tl_assert(!DRD_(g_threadinfo)[tid].detached_posix_thread);
51691b7ec3660efe16790bc337190a1c948beaab0a5bart   DRD_(g_threadinfo)[tid].sg_first = NULL;
51791b7ec3660efe16790bc337190a1c948beaab0a5bart   DRD_(g_threadinfo)[tid].sg_last = NULL;
518bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
51991b7ec3660efe16790bc337190a1c948beaab0a5bart   tl_assert(!DRD_(IsValidDrdThreadId)(tid));
520af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
521af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
522324a23bea57e0bfc27d9442ec00a8eee8294f01abart/**
523324a23bea57e0bfc27d9442ec00a8eee8294f01abart * Called after a thread performed its last memory access and before
524324a23bea57e0bfc27d9442ec00a8eee8294f01abart * thread_delete() is called. Note: thread_delete() is only called for
525324a23bea57e0bfc27d9442ec00a8eee8294f01abart * joinable threads, not for detached threads.
526324a23bea57e0bfc27d9442ec00a8eee8294f01abart */
52762a784c9382fdf7184065ad76ae8d3b905605f21bartvoid DRD_(thread_finished)(const DrdThreadId tid)
528af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
529bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
530bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
531bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
532bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(g_threadinfo)[tid].vg_thread_exists = False;
533bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
534bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (DRD_(g_threadinfo)[tid].detached_posix_thread)
535bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
536bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      /*
537bedfd237fbdc80d0c917cfcb85a94b5561c92633bart       * Once a detached thread has finished, its stack is deallocated and
538bedfd237fbdc80d0c917cfcb85a94b5561c92633bart       * should no longer be taken into account when computing the conflict set.
539bedfd237fbdc80d0c917cfcb85a94b5561c92633bart       */
540bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      DRD_(g_threadinfo)[tid].stack_min = DRD_(g_threadinfo)[tid].stack_max;
541bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
542bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      /*
543bedfd237fbdc80d0c917cfcb85a94b5561c92633bart       * For a detached thread, calling pthread_exit() invalidates the
544bedfd237fbdc80d0c917cfcb85a94b5561c92633bart       * POSIX thread ID associated with the detached thread. For joinable
545bedfd237fbdc80d0c917cfcb85a94b5561c92633bart       * POSIX threads however, the POSIX thread ID remains live after the
546bedfd237fbdc80d0c917cfcb85a94b5561c92633bart       * pthread_exit() call until pthread_join() is called.
547bedfd237fbdc80d0c917cfcb85a94b5561c92633bart       */
548bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      DRD_(g_threadinfo)[tid].posix_thread_exists = False;
549bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
550af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
551af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
5525c7e6b69ccaecc32ff43d7f3cb9573f3901d19f0bart/** Called just after fork() in the child process. */
5535c7e6b69ccaecc32ff43d7f3cb9573f3901d19f0bartvoid DRD_(drd_thread_atfork_child)(const DrdThreadId tid)
5545c7e6b69ccaecc32ff43d7f3cb9573f3901d19f0bart{
5555c7e6b69ccaecc32ff43d7f3cb9573f3901d19f0bart   unsigned i;
5565c7e6b69ccaecc32ff43d7f3cb9573f3901d19f0bart
5575c7e6b69ccaecc32ff43d7f3cb9573f3901d19f0bart   for (i = 1; i < DRD_N_THREADS; i++)
5585c7e6b69ccaecc32ff43d7f3cb9573f3901d19f0bart   {
5595c7e6b69ccaecc32ff43d7f3cb9573f3901d19f0bart      if (i == tid)
5605c7e6b69ccaecc32ff43d7f3cb9573f3901d19f0bart	 continue;
5615c7e6b69ccaecc32ff43d7f3cb9573f3901d19f0bart      if (DRD_(IsValidDrdThreadId(i)))
5629194e93ab737439d653498ee43df4bae7989ad3dbart	 DRD_(thread_delete)(i, True);
5635c7e6b69ccaecc32ff43d7f3cb9573f3901d19f0bart      tl_assert(!DRD_(IsValidDrdThreadId(i)));
564f7a5b3fb7545645c47e3ee5d8fc1d66ea09f679cbart   }
5657692f169aa556ea177b8e949abff2d3e224580e1bart
5667692f169aa556ea177b8e949abff2d3e224580e1bart   DRD_(bm_cleanup)(DRD_(g_conflict_set));
5677692f169aa556ea177b8e949abff2d3e224580e1bart   DRD_(bm_init)(DRD_(g_conflict_set));
5685c7e6b69ccaecc32ff43d7f3cb9573f3901d19f0bart}
5695c7e6b69ccaecc32ff43d7f3cb9573f3901d19f0bart
5709b2974ad8c14abb2a0cbcbc66e43f9d97d3deaccbart/** Called just before pthread_cancel(). */
57162a784c9382fdf7184065ad76ae8d3b905605f21bartvoid DRD_(thread_pre_cancel)(const DrdThreadId tid)
572af0691b41efd73639efbeaddf9c6238a77089f77bart{
573bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
574bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
575bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
576af0691b41efd73639efbeaddf9c6238a77089f77bart
5770c0cd77a6ffda2fd1abf4877ef125889c2e07f9ebart   if (DRD_(thread_get_trace_fork_join)())
578ad994e885caeb5241cbedf4e47e7821cf164f4e7bart      DRD_(trace_msg)("[%d] drd_thread_pre_cancel %d",
579b92ff0fd192dd05700f7d20db00795965e20b5c5bart                      DRD_(g_drd_running_tid), tid);
580af0691b41efd73639efbeaddf9c6238a77089f77bart}
581af0691b41efd73639efbeaddf9c6238a77089f77bart
582e7dff2479d4d1e0024f0889c54c4578d427ab0a2bart/**
583e7dff2479d4d1e0024f0889c54c4578d427ab0a2bart * Store the POSIX thread ID for the specified thread.
584e7dff2479d4d1e0024f0889c54c4578d427ab0a2bart *
585e7dff2479d4d1e0024f0889c54c4578d427ab0a2bart * @note This function can be called two times for the same thread -- see also
586e7dff2479d4d1e0024f0889c54c4578d427ab0a2bart * the comment block preceding the pthread_create() wrapper in
587e7dff2479d4d1e0024f0889c54c4578d427ab0a2bart * drd_pthread_intercepts.c.
588e7dff2479d4d1e0024f0889c54c4578d427ab0a2bart */
58962a784c9382fdf7184065ad76ae8d3b905605f21bartvoid DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid)
590af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
591bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
592bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
593e7dff2479d4d1e0024f0889c54c4578d427ab0a2bart   tl_assert(DRD_(g_threadinfo)[tid].pt_threadid == INVALID_POSIX_THREADID
594e7dff2479d4d1e0024f0889c54c4578d427ab0a2bart             || DRD_(g_threadinfo)[tid].pt_threadid == ptid);
595bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(ptid != INVALID_POSIX_THREADID);
596bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(g_threadinfo)[tid].posix_thread_exists = True;
597bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(g_threadinfo)[tid].pt_threadid         = ptid;
598af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
599af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
60086a87df5949beb1f89ebbed923068faed08d048cbart/** Returns true for joinable threads and false for detached threads. */
60162a784c9382fdf7184065ad76ae8d3b905605f21bartBool DRD_(thread_get_joinable)(const DrdThreadId tid)
602af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
603bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
604bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
605bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return ! DRD_(g_threadinfo)[tid].detached_posix_thread;
606af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
607af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
60886a87df5949beb1f89ebbed923068faed08d048cbart/** Store the thread mode: joinable or detached. */
6094df0bfc0614379192c780c944415dc420d9cfe8epetarj#if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
6105db15403e889d4db339b342bc2a824ef0bfaa654sewardj /* There is a cse related issue in gcc for MIPS. Optimization level
6115db15403e889d4db339b342bc2a824ef0bfaa654sewardj    has to be lowered, so cse related optimizations are not
6125db15403e889d4db339b342bc2a824ef0bfaa654sewardj    included.*/
6135db15403e889d4db339b342bc2a824ef0bfaa654sewardj __attribute__((optimize("O1")))
6145db15403e889d4db339b342bc2a824ef0bfaa654sewardj#endif
61562a784c9382fdf7184065ad76ae8d3b905605f21bartvoid DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable)
616af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
617bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
618bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
619d56b7e2bd0e7b56f99c0e2805e6c1cd57bd31427sewardj   tl_assert((!! joinable) == joinable);
620bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
6218f822af9b234e7c553c408eba65a641c4773457fbart
622bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable;
623af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
624af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
625dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart/** Tells DRD that the calling thread is about to enter pthread_create(). */
626dd75cdfe7612f58bdba8e3a16d34ee32eef85980bartvoid DRD_(thread_entering_pthread_create)(const DrdThreadId tid)
627dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart{
628dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
629dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart             && tid != DRD_INVALID_THREADID);
630dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart   tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
631dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart   tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level >= 0);
632dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart
633dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart   DRD_(g_threadinfo)[tid].pthread_create_nesting_level++;
634dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart}
635dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart
636dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart/** Tells DRD that the calling thread has left pthread_create(). */
637dd75cdfe7612f58bdba8e3a16d34ee32eef85980bartvoid DRD_(thread_left_pthread_create)(const DrdThreadId tid)
638dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart{
639dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
640dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart             && tid != DRD_INVALID_THREADID);
641dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart   tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
642dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart   tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level > 0);
643dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart
644dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart   DRD_(g_threadinfo)[tid].pthread_create_nesting_level--;
645dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart}
646dd75cdfe7612f58bdba8e3a16d34ee32eef85980bart
647d45d99553c15a361bb797d21ec6afb9bad22d2d4bart/** Obtain the thread number and the user-assigned thread name. */
64819f91bbaedb4caef8a60ce94b0f507193cc0bc10florianconst HChar* DRD_(thread_get_name)(const DrdThreadId tid)
649d45d99553c15a361bb797d21ec6afb9bad22d2d4bart{
650d45d99553c15a361bb797d21ec6afb9bad22d2d4bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
651d45d99553c15a361bb797d21ec6afb9bad22d2d4bart             && tid != DRD_INVALID_THREADID);
652d45d99553c15a361bb797d21ec6afb9bad22d2d4bart
653d45d99553c15a361bb797d21ec6afb9bad22d2d4bart   return DRD_(g_threadinfo)[tid].name;
654d45d99553c15a361bb797d21ec6afb9bad22d2d4bart}
655d45d99553c15a361bb797d21ec6afb9bad22d2d4bart
656d45d99553c15a361bb797d21ec6afb9bad22d2d4bart/** Set the name of the specified thread. */
65719f91bbaedb4caef8a60ce94b0f507193cc0bc10florianvoid DRD_(thread_set_name)(const DrdThreadId tid, const HChar* const name)
658d45d99553c15a361bb797d21ec6afb9bad22d2d4bart{
659d45d99553c15a361bb797d21ec6afb9bad22d2d4bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
660d45d99553c15a361bb797d21ec6afb9bad22d2d4bart             && tid != DRD_INVALID_THREADID);
66131b983d29affe6c30a2283be8824c6d75c74d848bart
662d45d99553c15a361bb797d21ec6afb9bad22d2d4bart   if (name == NULL || name[0] == 0)
663d45d99553c15a361bb797d21ec6afb9bad22d2d4bart      VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
664d45d99553c15a361bb797d21ec6afb9bad22d2d4bart                    sizeof(DRD_(g_threadinfo)[tid].name),
665d45d99553c15a361bb797d21ec6afb9bad22d2d4bart                    "Thread %d",
666d45d99553c15a361bb797d21ec6afb9bad22d2d4bart                    tid);
667d45d99553c15a361bb797d21ec6afb9bad22d2d4bart   else
668d45d99553c15a361bb797d21ec6afb9bad22d2d4bart      VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
669d45d99553c15a361bb797d21ec6afb9bad22d2d4bart                    sizeof(DRD_(g_threadinfo)[tid].name),
670d45d99553c15a361bb797d21ec6afb9bad22d2d4bart                    "Thread %d (%s)",
671d45d99553c15a361bb797d21ec6afb9bad22d2d4bart                    tid, name);
672d45d99553c15a361bb797d21ec6afb9bad22d2d4bart   DRD_(g_threadinfo)[tid].name[sizeof(DRD_(g_threadinfo)[tid].name) - 1] = 0;
673d45d99553c15a361bb797d21ec6afb9bad22d2d4bart}
674d45d99553c15a361bb797d21ec6afb9bad22d2d4bart
67586a87df5949beb1f89ebbed923068faed08d048cbart/**
67686a87df5949beb1f89ebbed923068faed08d048cbart * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
67786a87df5949beb1f89ebbed923068faed08d048cbart * conflict set.
67886a87df5949beb1f89ebbed923068faed08d048cbart */
67962a784c9382fdf7184065ad76ae8d3b905605f21bartvoid DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid)
6808b09d4f037c6399658b610228c7bbc0c6133d9dasewardj{
681bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(vg_tid != VG_INVALID_THREADID);
6828b09d4f037c6399658b610228c7bbc0c6133d9dasewardj
683bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (vg_tid != s_vg_running_tid)
684bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
685bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      DRD_(thread_set_running_tid)(vg_tid,
686bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                                   DRD_(VgThreadIdToDrdThreadId)(vg_tid));
687bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
6888b09d4f037c6399658b610228c7bbc0c6133d9dasewardj
689bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
690bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
691af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
692af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
69386a87df5949beb1f89ebbed923068faed08d048cbart/**
69486a87df5949beb1f89ebbed923068faed08d048cbart * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
69586a87df5949beb1f89ebbed923068faed08d048cbart * conflict set.
69686a87df5949beb1f89ebbed923068faed08d048cbart */
69762a784c9382fdf7184065ad76ae8d3b905605f21bartvoid DRD_(thread_set_running_tid)(const ThreadId vg_tid,
69862a784c9382fdf7184065ad76ae8d3b905605f21bart                                  const DrdThreadId drd_tid)
699af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
700bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(vg_tid != VG_INVALID_THREADID);
701bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(drd_tid != DRD_INVALID_THREADID);
70231b983d29affe6c30a2283be8824c6d75c74d848bart
703bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (vg_tid != s_vg_running_tid)
704bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
705bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      if (s_trace_context_switches
706bedfd237fbdc80d0c917cfcb85a94b5561c92633bart          && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID)
707bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      {
708bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         VG_(message)(Vg_DebugMsg,
70963c92ea799549976957f5b4d54ede744f762c56fbart                      "Context switch from thread %d to thread %d;"
7101e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj                      " segments: %llu\n",
71163c92ea799549976957f5b4d54ede744f762c56fbart                      DRD_(g_drd_running_tid), drd_tid,
712bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                      DRD_(sg_get_segments_alive_count)());
713bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      }
714bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      s_vg_running_tid = vg_tid;
715bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      DRD_(g_drd_running_tid) = drd_tid;
716bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      thread_compute_conflict_set(&DRD_(g_conflict_set), drd_tid);
717bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      s_context_switch_count++;
718bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
719bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
720bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
721bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
722af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
723af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
72486a87df5949beb1f89ebbed923068faed08d048cbart/**
72586a87df5949beb1f89ebbed923068faed08d048cbart * Increase the synchronization nesting counter. Must be called before the
72686a87df5949beb1f89ebbed923068faed08d048cbart * client calls a synchronization function.
72786a87df5949beb1f89ebbed923068faed08d048cbart */
72862a784c9382fdf7184065ad76ae8d3b905605f21bartint DRD_(thread_enter_synchr)(const DrdThreadId tid)
7290268dfacec38138a01a58d05a038826e26b6c436bart{
730bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(DRD_(IsValidDrdThreadId)(tid));
731bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return DRD_(g_threadinfo)[tid].synchr_nesting++;
7320268dfacec38138a01a58d05a038826e26b6c436bart}
7330268dfacec38138a01a58d05a038826e26b6c436bart
73486a87df5949beb1f89ebbed923068faed08d048cbart/**
73586a87df5949beb1f89ebbed923068faed08d048cbart * Decrease the synchronization nesting counter. Must be called after the
73686a87df5949beb1f89ebbed923068faed08d048cbart * client left a synchronization function.
73786a87df5949beb1f89ebbed923068faed08d048cbart */
73862a784c9382fdf7184065ad76ae8d3b905605f21bartint DRD_(thread_leave_synchr)(const DrdThreadId tid)
7390268dfacec38138a01a58d05a038826e26b6c436bart{
740bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(DRD_(IsValidDrdThreadId)(tid));
741bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 1);
742bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return --DRD_(g_threadinfo)[tid].synchr_nesting;
7430268dfacec38138a01a58d05a038826e26b6c436bart}
7440268dfacec38138a01a58d05a038826e26b6c436bart
74586a87df5949beb1f89ebbed923068faed08d048cbart/** Returns the synchronization nesting counter. */
74662a784c9382fdf7184065ad76ae8d3b905605f21bartint DRD_(thread_get_synchr_nesting_count)(const DrdThreadId tid)
7470268dfacec38138a01a58d05a038826e26b6c436bart{
748bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(DRD_(IsValidDrdThreadId)(tid));
749bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return DRD_(g_threadinfo)[tid].synchr_nesting;
7500268dfacec38138a01a58d05a038826e26b6c436bart}
7510268dfacec38138a01a58d05a038826e26b6c436bart
7521a473c757cae99f11477440d5473be6e5c95e0cebart/** Append a new segment at the end of the segment list. */
75362a784c9382fdf7184065ad76ae8d3b905605f21bartstatic
75486a87df5949beb1f89ebbed923068faed08d048cbartvoid thread_append_segment(const DrdThreadId tid, Segment* const sg)
755af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
756bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
757bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
7588f822af9b234e7c553c408eba65a641c4773457fbart
7598f822af9b234e7c553c408eba65a641c4773457fbart#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
7608f822af9b234e7c553c408eba65a641c4773457fbart   tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
7618f822af9b234e7c553c408eba65a641c4773457fbart#endif
7628f822af9b234e7c553c408eba65a641c4773457fbart
76391b7ec3660efe16790bc337190a1c948beaab0a5bart   // add at tail
76491b7ec3660efe16790bc337190a1c948beaab0a5bart   sg->thr_prev = DRD_(g_threadinfo)[tid].sg_last;
76591b7ec3660efe16790bc337190a1c948beaab0a5bart   sg->thr_next = NULL;
76691b7ec3660efe16790bc337190a1c948beaab0a5bart   if (DRD_(g_threadinfo)[tid].sg_last)
76791b7ec3660efe16790bc337190a1c948beaab0a5bart      DRD_(g_threadinfo)[tid].sg_last->thr_next = sg;
76891b7ec3660efe16790bc337190a1c948beaab0a5bart   DRD_(g_threadinfo)[tid].sg_last = sg;
76991b7ec3660efe16790bc337190a1c948beaab0a5bart   if (DRD_(g_threadinfo)[tid].sg_first == NULL)
77091b7ec3660efe16790bc337190a1c948beaab0a5bart      DRD_(g_threadinfo)[tid].sg_first = sg;
7718f822af9b234e7c553c408eba65a641c4773457fbart
7728f822af9b234e7c553c408eba65a641c4773457fbart#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
7738f822af9b234e7c553c408eba65a641c4773457fbart   tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
7748f822af9b234e7c553c408eba65a641c4773457fbart#endif
775af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
776af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
777324a23bea57e0bfc27d9442ec00a8eee8294f01abart/**
778324a23bea57e0bfc27d9442ec00a8eee8294f01abart * Remove a segment from the segment list of thread threadid, and free the
779324a23bea57e0bfc27d9442ec00a8eee8294f01abart * associated memory.
780af44c8236f7a73e71b16b707bba56f33af4d01cesewardj */
78162a784c9382fdf7184065ad76ae8d3b905605f21bartstatic
78286a87df5949beb1f89ebbed923068faed08d048cbartvoid thread_discard_segment(const DrdThreadId tid, Segment* const sg)
783af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
784bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
785bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
7868f822af9b234e7c553c408eba65a641c4773457fbart
7878f822af9b234e7c553c408eba65a641c4773457fbart#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
7888f822af9b234e7c553c408eba65a641c4773457fbart   tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
7898f822af9b234e7c553c408eba65a641c4773457fbart#endif
790bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
79191b7ec3660efe16790bc337190a1c948beaab0a5bart   if (sg->thr_prev)
79291b7ec3660efe16790bc337190a1c948beaab0a5bart      sg->thr_prev->thr_next = sg->thr_next;
79391b7ec3660efe16790bc337190a1c948beaab0a5bart   if (sg->thr_next)
79491b7ec3660efe16790bc337190a1c948beaab0a5bart      sg->thr_next->thr_prev = sg->thr_prev;
79591b7ec3660efe16790bc337190a1c948beaab0a5bart   if (sg == DRD_(g_threadinfo)[tid].sg_first)
79691b7ec3660efe16790bc337190a1c948beaab0a5bart      DRD_(g_threadinfo)[tid].sg_first = sg->thr_next;
79791b7ec3660efe16790bc337190a1c948beaab0a5bart   if (sg == DRD_(g_threadinfo)[tid].sg_last)
79891b7ec3660efe16790bc337190a1c948beaab0a5bart      DRD_(g_threadinfo)[tid].sg_last = sg->thr_prev;
799bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(sg_put)(sg);
800bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
8018f822af9b234e7c553c408eba65a641c4773457fbart#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
8028f822af9b234e7c553c408eba65a641c4773457fbart   tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
8038f822af9b234e7c553c408eba65a641c4773457fbart#endif
804af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
805af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
80686a87df5949beb1f89ebbed923068faed08d048cbart/**
80786a87df5949beb1f89ebbed923068faed08d048cbart * Returns a pointer to the vector clock of the most recent segment associated
80886a87df5949beb1f89ebbed923068faed08d048cbart * with thread 'tid'.
80986a87df5949beb1f89ebbed923068faed08d048cbart */
81062a784c9382fdf7184065ad76ae8d3b905605f21bartVectorClock* DRD_(thread_get_vc)(const DrdThreadId tid)
811af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
81291b7ec3660efe16790bc337190a1c948beaab0a5bart   Segment* latest_sg;
813e278ab506b9a73ef1c17a17077546b2de9a11d7cbart
814bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
815bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
81691b7ec3660efe16790bc337190a1c948beaab0a5bart   latest_sg = DRD_(g_threadinfo)[tid].sg_last;
81791b7ec3660efe16790bc337190a1c948beaab0a5bart   tl_assert(latest_sg);
81891b7ec3660efe16790bc337190a1c948beaab0a5bart   return &latest_sg->vc;
819af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
820af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
821324a23bea57e0bfc27d9442ec00a8eee8294f01abart/**
822324a23bea57e0bfc27d9442ec00a8eee8294f01abart * Return the latest segment of thread 'tid' and increment its reference count.
823a2b6e1bbcc45fcb42ac0441a2e5b4d40c3671ec6bart */
82462a784c9382fdf7184065ad76ae8d3b905605f21bartvoid DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid)
825a2b6e1bbcc45fcb42ac0441a2e5b4d40c3671ec6bart{
82691b7ec3660efe16790bc337190a1c948beaab0a5bart   Segment* latest_sg;
827e278ab506b9a73ef1c17a17077546b2de9a11d7cbart
828bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(sg);
829bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
830bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
83191b7ec3660efe16790bc337190a1c948beaab0a5bart   latest_sg = DRD_(g_threadinfo)[tid].sg_last;
83291b7ec3660efe16790bc337190a1c948beaab0a5bart   tl_assert(latest_sg);
833a2b6e1bbcc45fcb42ac0441a2e5b4d40c3671ec6bart
834bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(sg_put)(*sg);
83591b7ec3660efe16790bc337190a1c948beaab0a5bart   *sg = DRD_(sg_get)(latest_sg);
836a2b6e1bbcc45fcb42ac0441a2e5b4d40c3671ec6bart}
837a2b6e1bbcc45fcb42ac0441a2e5b4d40c3671ec6bart
838af44c8236f7a73e71b16b707bba56f33af4d01cesewardj/**
839af44c8236f7a73e71b16b707bba56f33af4d01cesewardj * Compute the minimum of all latest vector clocks of all threads
840af44c8236f7a73e71b16b707bba56f33af4d01cesewardj * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
84186a87df5949beb1f89ebbed923068faed08d048cbart *
842af44c8236f7a73e71b16b707bba56f33af4d01cesewardj * @param vc pointer to a vectorclock, holds result upon return.
843af44c8236f7a73e71b16b707bba56f33af4d01cesewardj */
84462a784c9382fdf7184065ad76ae8d3b905605f21bartstatic void DRD_(thread_compute_minimum_vc)(VectorClock* vc)
845af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
846bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   unsigned i;
847bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   Bool first;
848bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   Segment* latest_sg;
849bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
850bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   first = True;
8518f822af9b234e7c553c408eba65a641c4773457fbart   for (i = 0; i < DRD_N_THREADS; i++)
852bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
85391b7ec3660efe16790bc337190a1c948beaab0a5bart      latest_sg = DRD_(g_threadinfo)[i].sg_last;
85491b7ec3660efe16790bc337190a1c948beaab0a5bart      if (latest_sg) {
855bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         if (first)
856bedfd237fbdc80d0c917cfcb85a94b5561c92633bart            DRD_(vc_assign)(vc, &latest_sg->vc);
857bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         else
858bedfd237fbdc80d0c917cfcb85a94b5561c92633bart            DRD_(vc_min)(vc, &latest_sg->vc);
859bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         first = False;
860bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      }
861bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
862af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
863af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
86486a87df5949beb1f89ebbed923068faed08d048cbart/**
86586a87df5949beb1f89ebbed923068faed08d048cbart * Compute the maximum of all latest vector clocks of all threads.
86686a87df5949beb1f89ebbed923068faed08d048cbart *
86786a87df5949beb1f89ebbed923068faed08d048cbart * @param vc pointer to a vectorclock, holds result upon return.
86886a87df5949beb1f89ebbed923068faed08d048cbart */
86962a784c9382fdf7184065ad76ae8d3b905605f21bartstatic void DRD_(thread_compute_maximum_vc)(VectorClock* vc)
870af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
871bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   unsigned i;
872bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   Bool first;
873bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   Segment* latest_sg;
874bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
875bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   first = True;
8768f822af9b234e7c553c408eba65a641c4773457fbart   for (i = 0; i < DRD_N_THREADS; i++)
877bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
87891b7ec3660efe16790bc337190a1c948beaab0a5bart      latest_sg = DRD_(g_threadinfo)[i].sg_last;
87991b7ec3660efe16790bc337190a1c948beaab0a5bart      if (latest_sg) {
880bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         if (first)
881bedfd237fbdc80d0c917cfcb85a94b5561c92633bart            DRD_(vc_assign)(vc, &latest_sg->vc);
882bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         else
883bedfd237fbdc80d0c917cfcb85a94b5561c92633bart            DRD_(vc_combine)(vc, &latest_sg->vc);
884bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         first = False;
885bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      }
886bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
887af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
888af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
889af44c8236f7a73e71b16b707bba56f33af4d01cesewardj/**
8905bd9f2d42ba9440b528b1f926dd57b4652cb0583bart * Discard all segments that have a defined order against the latest vector
89186a87df5949beb1f89ebbed923068faed08d048cbart * clock of all threads -- these segments can no longer be involved in a
892af44c8236f7a73e71b16b707bba56f33af4d01cesewardj * data race.
893af44c8236f7a73e71b16b707bba56f33af4d01cesewardj */
8948f822af9b234e7c553c408eba65a641c4773457fbartstatic void thread_discard_ordered_segments(void)
895af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
896bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   unsigned i;
897bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   VectorClock thread_vc_min;
898bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
899bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   s_discard_ordered_segments_count++;
900bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
901bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(vc_init)(&thread_vc_min, 0, 0);
902bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(thread_compute_minimum_vc)(&thread_vc_min);
903bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   if (DRD_(sg_get_trace)())
904bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
90519f91bbaedb4caef8a60ce94b0f507193cc0bc10florian      HChar *vc_min, *vc_max;
906bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      VectorClock thread_vc_max;
907bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
908bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      DRD_(vc_init)(&thread_vc_max, 0, 0);
909bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      DRD_(thread_compute_maximum_vc)(&thread_vc_max);
9108f822af9b234e7c553c408eba65a641c4773457fbart      vc_min = DRD_(vc_aprint)(&thread_vc_min);
9118f822af9b234e7c553c408eba65a641c4773457fbart      vc_max = DRD_(vc_aprint)(&thread_vc_max);
9128f822af9b234e7c553c408eba65a641c4773457fbart      VG_(message)(Vg_DebugMsg,
9131e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj                   "Discarding ordered segments -- min vc is %s, max vc is %s\n",
9148f822af9b234e7c553c408eba65a641c4773457fbart                   vc_min, vc_max);
9158f822af9b234e7c553c408eba65a641c4773457fbart      VG_(free)(vc_min);
9168f822af9b234e7c553c408eba65a641c4773457fbart      VG_(free)(vc_max);
917bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      DRD_(vc_cleanup)(&thread_vc_max);
918bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
919bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
92091b7ec3660efe16790bc337190a1c948beaab0a5bart   for (i = 0; i < DRD_N_THREADS; i++) {
921bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      Segment* sg;
922bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      Segment* sg_next;
923e278ab506b9a73ef1c17a17077546b2de9a11d7cbart
92491b7ec3660efe16790bc337190a1c948beaab0a5bart      for (sg = DRD_(g_threadinfo)[i].sg_first;
92591b7ec3660efe16790bc337190a1c948beaab0a5bart           sg && (sg_next = sg->thr_next)
92691b7ec3660efe16790bc337190a1c948beaab0a5bart              && DRD_(vc_lte)(&sg->vc, &thread_vc_min);
92791b7ec3660efe16790bc337190a1c948beaab0a5bart           sg = sg_next)
92891b7ec3660efe16790bc337190a1c948beaab0a5bart      {
929bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         thread_discard_segment(i, sg);
930bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      }
931bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
932bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   DRD_(vc_cleanup)(&thread_vc_min);
933af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
934af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
935324a23bea57e0bfc27d9442ec00a8eee8294f01abart/**
9368f822af9b234e7c553c408eba65a641c4773457fbart * An implementation of the property 'equiv(sg1, sg2)' as defined in the paper
9378f822af9b234e7c553c408eba65a641c4773457fbart * by Mark Christiaens e.a. The property equiv(sg1, sg2) holds if and only if
9388f822af9b234e7c553c408eba65a641c4773457fbart * all segments in the set CS are ordered consistently against both sg1 and
9398f822af9b234e7c553c408eba65a641c4773457fbart * sg2. The set CS is defined as the set of segments that can immediately
9408f822af9b234e7c553c408eba65a641c4773457fbart * precede future segments via inter-thread synchronization operations. In
9418f822af9b234e7c553c408eba65a641c4773457fbart * DRD the set CS consists of the latest segment of each thread combined with
9428f822af9b234e7c553c408eba65a641c4773457fbart * all segments for which the reference count is strictly greater than one.
9438f822af9b234e7c553c408eba65a641c4773457fbart * The code below is an optimized version of the following:
9448f822af9b234e7c553c408eba65a641c4773457fbart *
9458f822af9b234e7c553c408eba65a641c4773457fbart * for (i = 0; i < DRD_N_THREADS; i++)
9468f822af9b234e7c553c408eba65a641c4773457fbart * {
9478f822af9b234e7c553c408eba65a641c4773457fbart *    Segment* sg;
9488f822af9b234e7c553c408eba65a641c4773457fbart *
9498f822af9b234e7c553c408eba65a641c4773457fbart *    for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
9508f822af9b234e7c553c408eba65a641c4773457fbart *    {
9518f822af9b234e7c553c408eba65a641c4773457fbart *       if (sg == DRD_(g_threadinfo)[i].last || DRD_(sg_get_refcnt)(sg) > 1)
9528f822af9b234e7c553c408eba65a641c4773457fbart *       {
9538f822af9b234e7c553c408eba65a641c4773457fbart *          if (   DRD_(vc_lte)(&sg1->vc, &sg->vc)
9548f822af9b234e7c553c408eba65a641c4773457fbart *              != DRD_(vc_lte)(&sg2->vc, &sg->vc)
9558f822af9b234e7c553c408eba65a641c4773457fbart *              || DRD_(vc_lte)(&sg->vc, &sg1->vc)
9568f822af9b234e7c553c408eba65a641c4773457fbart *              != DRD_(vc_lte)(&sg->vc, &sg2->vc))
9578f822af9b234e7c553c408eba65a641c4773457fbart *          {
9588f822af9b234e7c553c408eba65a641c4773457fbart *             return False;
9598f822af9b234e7c553c408eba65a641c4773457fbart *          }
9608f822af9b234e7c553c408eba65a641c4773457fbart *       }
9618f822af9b234e7c553c408eba65a641c4773457fbart *    }
9628f822af9b234e7c553c408eba65a641c4773457fbart * }
9638f822af9b234e7c553c408eba65a641c4773457fbart */
9648f822af9b234e7c553c408eba65a641c4773457fbartstatic Bool thread_consistent_segment_ordering(const DrdThreadId tid,
9658f822af9b234e7c553c408eba65a641c4773457fbart                                               Segment* const sg1,
9668f822af9b234e7c553c408eba65a641c4773457fbart                                               Segment* const sg2)
9678f822af9b234e7c553c408eba65a641c4773457fbart{
9688f822af9b234e7c553c408eba65a641c4773457fbart   unsigned i;
9698f822af9b234e7c553c408eba65a641c4773457fbart
97091b7ec3660efe16790bc337190a1c948beaab0a5bart   tl_assert(sg1->thr_next);
97191b7ec3660efe16790bc337190a1c948beaab0a5bart   tl_assert(sg2->thr_next);
97291b7ec3660efe16790bc337190a1c948beaab0a5bart   tl_assert(sg1->thr_next == sg2);
9738f822af9b234e7c553c408eba65a641c4773457fbart   tl_assert(DRD_(vc_lte)(&sg1->vc, &sg2->vc));
9748f822af9b234e7c553c408eba65a641c4773457fbart
9758f822af9b234e7c553c408eba65a641c4773457fbart   for (i = 0; i < DRD_N_THREADS; i++)
9768f822af9b234e7c553c408eba65a641c4773457fbart   {
9778f822af9b234e7c553c408eba65a641c4773457fbart      Segment* sg;
9788f822af9b234e7c553c408eba65a641c4773457fbart
97991b7ec3660efe16790bc337190a1c948beaab0a5bart      for (sg = DRD_(g_threadinfo)[i].sg_first; sg; sg = sg->thr_next) {
98091b7ec3660efe16790bc337190a1c948beaab0a5bart         if (!sg->thr_next || DRD_(sg_get_refcnt)(sg) > 1) {
9818f822af9b234e7c553c408eba65a641c4773457fbart            if (DRD_(vc_lte)(&sg2->vc, &sg->vc))
9828f822af9b234e7c553c408eba65a641c4773457fbart               break;
9838f822af9b234e7c553c408eba65a641c4773457fbart            if (DRD_(vc_lte)(&sg1->vc, &sg->vc))
9848f822af9b234e7c553c408eba65a641c4773457fbart               return False;
9858f822af9b234e7c553c408eba65a641c4773457fbart         }
9868f822af9b234e7c553c408eba65a641c4773457fbart      }
98791b7ec3660efe16790bc337190a1c948beaab0a5bart      for (sg = DRD_(g_threadinfo)[i].sg_last; sg; sg = sg->thr_prev) {
98891b7ec3660efe16790bc337190a1c948beaab0a5bart         if (!sg->thr_next || DRD_(sg_get_refcnt)(sg) > 1) {
9898f822af9b234e7c553c408eba65a641c4773457fbart            if (DRD_(vc_lte)(&sg->vc, &sg1->vc))
9908f822af9b234e7c553c408eba65a641c4773457fbart               break;
9918f822af9b234e7c553c408eba65a641c4773457fbart            if (DRD_(vc_lte)(&sg->vc, &sg2->vc))
9928f822af9b234e7c553c408eba65a641c4773457fbart               return False;
9938f822af9b234e7c553c408eba65a641c4773457fbart         }
9948f822af9b234e7c553c408eba65a641c4773457fbart      }
9958f822af9b234e7c553c408eba65a641c4773457fbart   }
9968f822af9b234e7c553c408eba65a641c4773457fbart   return True;
9978f822af9b234e7c553c408eba65a641c4773457fbart}
9988f822af9b234e7c553c408eba65a641c4773457fbart
9998f822af9b234e7c553c408eba65a641c4773457fbart/**
1000324a23bea57e0bfc27d9442ec00a8eee8294f01abart * Merge all segments that may be merged without triggering false positives
1001324a23bea57e0bfc27d9442ec00a8eee8294f01abart * or discarding real data races. For the theoretical background of segment
10028f822af9b234e7c553c408eba65a641c4773457fbart * merging, see also the following paper: Mark Christiaens, Michiel Ronsse
10038f822af9b234e7c553c408eba65a641c4773457fbart * and Koen De Bosschere. Bounding the number of segment histories during
10048f822af9b234e7c553c408eba65a641c4773457fbart * data race detection. Parallel Computing archive, Volume 28, Issue 9,
10058f822af9b234e7c553c408eba65a641c4773457fbart * pp 1221-1238, September 2002. This paper contains a proof that merging
10068f822af9b234e7c553c408eba65a641c4773457fbart * consecutive segments for which the property equiv(s1,s2) holds can be
10078f822af9b234e7c553c408eba65a641c4773457fbart * merged without reducing the accuracy of datarace detection. Furthermore
10088f822af9b234e7c553c408eba65a641c4773457fbart * it is also proven that the total number of all segments will never grow
10098f822af9b234e7c553c408eba65a641c4773457fbart * unbounded if all segments s1, s2 for which equiv(s1, s2) holds are merged
10108f822af9b234e7c553c408eba65a641c4773457fbart * every time a new segment is created. The property equiv(s1, s2) is defined
10118f822af9b234e7c553c408eba65a641c4773457fbart * as follows: equiv(s1, s2) <=> for all segments in the set CS, the vector
10128f822af9b234e7c553c408eba65a641c4773457fbart * clocks of segments s and s1 are ordered in the same way as those of segments
10138f822af9b234e7c553c408eba65a641c4773457fbart * s and s2. The set CS is defined as the set of existing segments s that have
10148f822af9b234e7c553c408eba65a641c4773457fbart * the potential to conflict with not yet created segments, either because the
10158f822af9b234e7c553c408eba65a641c4773457fbart * segment s is the latest segment of a thread or because it can become the
10168f822af9b234e7c553c408eba65a641c4773457fbart * immediate predecessor of a new segment due to a synchronization operation.
1017a9c37398e4565280266ce663a6c38c3518af2812bart */
1018a9c37398e4565280266ce663a6c38c3518af2812bartstatic void thread_merge_segments(void)
1019a9c37398e4565280266ce663a6c38c3518af2812bart{
1020bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   unsigned i;
1021a9c37398e4565280266ce663a6c38c3518af2812bart
10228f822af9b234e7c553c408eba65a641c4773457fbart   s_new_segments_since_last_merge = 0;
10238f822af9b234e7c553c408eba65a641c4773457fbart
10248f822af9b234e7c553c408eba65a641c4773457fbart   for (i = 0; i < DRD_N_THREADS; i++)
1025bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
1026bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      Segment* sg;
1027a9c37398e4565280266ce663a6c38c3518af2812bart
10288f822af9b234e7c553c408eba65a641c4773457fbart#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
10298f822af9b234e7c553c408eba65a641c4773457fbart      tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
10308f822af9b234e7c553c408eba65a641c4773457fbart#endif
1031a9c37398e4565280266ce663a6c38c3518af2812bart
103291b7ec3660efe16790bc337190a1c948beaab0a5bart      for (sg = DRD_(g_threadinfo)[i].sg_first; sg; sg = sg->thr_next) {
103391b7ec3660efe16790bc337190a1c948beaab0a5bart         if (DRD_(sg_get_refcnt)(sg) == 1 && sg->thr_next) {
103491b7ec3660efe16790bc337190a1c948beaab0a5bart            Segment* const sg_next = sg->thr_next;
1035e278ab506b9a73ef1c17a17077546b2de9a11d7cbart            if (DRD_(sg_get_refcnt)(sg_next) == 1
103691b7ec3660efe16790bc337190a1c948beaab0a5bart                && sg_next->thr_next
1037e278ab506b9a73ef1c17a17077546b2de9a11d7cbart                && thread_consistent_segment_ordering(i, sg, sg_next))
1038e278ab506b9a73ef1c17a17077546b2de9a11d7cbart            {
1039e278ab506b9a73ef1c17a17077546b2de9a11d7cbart               /* Merge sg and sg_next into sg. */
1040e278ab506b9a73ef1c17a17077546b2de9a11d7cbart               DRD_(sg_merge)(sg, sg_next);
1041e278ab506b9a73ef1c17a17077546b2de9a11d7cbart               thread_discard_segment(i, sg_next);
1042e278ab506b9a73ef1c17a17077546b2de9a11d7cbart            }
1043bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         }
1044a9c37398e4565280266ce663a6c38c3518af2812bart      }
1045a9c37398e4565280266ce663a6c38c3518af2812bart
10468f822af9b234e7c553c408eba65a641c4773457fbart#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
10478f822af9b234e7c553c408eba65a641c4773457fbart      tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
10488f822af9b234e7c553c408eba65a641c4773457fbart#endif
1049bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
1050a9c37398e4565280266ce663a6c38c3518af2812bart}
1051a9c37398e4565280266ce663a6c38c3518af2812bart
1052324a23bea57e0bfc27d9442ec00a8eee8294f01abart/**
1053324a23bea57e0bfc27d9442ec00a8eee8294f01abart * Create a new segment for the specified thread, and discard any segments
1054324a23bea57e0bfc27d9442ec00a8eee8294f01abart * that cannot cause races anymore.
1055af44c8236f7a73e71b16b707bba56f33af4d01cesewardj */
105662a784c9382fdf7184065ad76ae8d3b905605f21bartvoid DRD_(thread_new_segment)(const DrdThreadId tid)
1057af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
10588f822af9b234e7c553c408eba65a641c4773457fbart   Segment* last_sg;
1059bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   Segment* new_sg;
1060d66e3a8e8c42b7c933c5e6ea0d9a9b4c8ac4cf49bart
1061bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1062bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
10638f822af9b234e7c553c408eba65a641c4773457fbart   tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1064af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
106591b7ec3660efe16790bc337190a1c948beaab0a5bart   last_sg = DRD_(g_threadinfo)[tid].sg_last;
1066bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   new_sg = DRD_(sg_new)(tid, tid);
1067bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   thread_append_segment(tid, new_sg);
10688f822af9b234e7c553c408eba65a641c4773457fbart   if (tid == DRD_(g_drd_running_tid) && last_sg)
1069e5214666ead5aebb79ad662deacff0a952cba70dbart   {
10708f822af9b234e7c553c408eba65a641c4773457fbart      DRD_(thread_update_conflict_set)(tid, &last_sg->vc);
1071e5214666ead5aebb79ad662deacff0a952cba70dbart      s_update_conflict_set_new_sg_count++;
1072e5214666ead5aebb79ad662deacff0a952cba70dbart   }
1073d66e3a8e8c42b7c933c5e6ea0d9a9b4c8ac4cf49bart
10748f822af9b234e7c553c408eba65a641c4773457fbart   tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
107526f73e12ef03bb04ebee5cccd8da08cddb426341bart
10768f822af9b234e7c553c408eba65a641c4773457fbart   if (s_segment_merging
10778f822af9b234e7c553c408eba65a641c4773457fbart       && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
1078bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
10798f822af9b234e7c553c408eba65a641c4773457fbart      thread_discard_ordered_segments();
1080bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      thread_merge_segments();
1081bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
1082af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
1083af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
108426f73e12ef03bb04ebee5cccd8da08cddb426341bart/** Call this function after thread 'joiner' joined thread 'joinee'. */
10858f822af9b234e7c553c408eba65a641c4773457fbartvoid DRD_(thread_combine_vc_join)(DrdThreadId joiner, DrdThreadId joinee)
1086af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
1087bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(joiner != joinee);
1088bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
1089bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && joiner != DRD_INVALID_THREADID);
1090bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
1091bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && joinee != DRD_INVALID_THREADID);
109291b7ec3660efe16790bc337190a1c948beaab0a5bart   tl_assert(DRD_(g_threadinfo)[joiner].sg_first);
109391b7ec3660efe16790bc337190a1c948beaab0a5bart   tl_assert(DRD_(g_threadinfo)[joiner].sg_last);
109491b7ec3660efe16790bc337190a1c948beaab0a5bart   tl_assert(DRD_(g_threadinfo)[joinee].sg_first);
109591b7ec3660efe16790bc337190a1c948beaab0a5bart   tl_assert(DRD_(g_threadinfo)[joinee].sg_last);
10968f822af9b234e7c553c408eba65a641c4773457fbart
10978f822af9b234e7c553c408eba65a641c4773457fbart   if (DRD_(sg_get_trace)())
10988f822af9b234e7c553c408eba65a641c4773457fbart   {
109919f91bbaedb4caef8a60ce94b0f507193cc0bc10florian      HChar *str1, *str2;
1100c6bf1846c7604390f777f88b63710702686086d9bart      str1 = DRD_(vc_aprint)(DRD_(thread_get_vc)(joiner));
1101c6bf1846c7604390f777f88b63710702686086d9bart      str2 = DRD_(vc_aprint)(DRD_(thread_get_vc)(joinee));
11021e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj      VG_(message)(Vg_DebugMsg, "Before join: joiner %s, joinee %s\n",
11038f822af9b234e7c553c408eba65a641c4773457fbart                   str1, str2);
11048f822af9b234e7c553c408eba65a641c4773457fbart      VG_(free)(str1);
11058f822af9b234e7c553c408eba65a641c4773457fbart      VG_(free)(str2);
11068f822af9b234e7c553c408eba65a641c4773457fbart   }
1107ae37e6d4c9ca1f400ef4c1636319be60f969b2afbart   if (joiner == DRD_(g_drd_running_tid)) {
1108e5214666ead5aebb79ad662deacff0a952cba70dbart      VectorClock old_vc;
1109e5214666ead5aebb79ad662deacff0a952cba70dbart
1110c6bf1846c7604390f777f88b63710702686086d9bart      DRD_(vc_copy)(&old_vc, DRD_(thread_get_vc)(joiner));
1111c6bf1846c7604390f777f88b63710702686086d9bart      DRD_(vc_combine)(DRD_(thread_get_vc)(joiner),
1112c6bf1846c7604390f777f88b63710702686086d9bart                       DRD_(thread_get_vc)(joinee));
1113e5214666ead5aebb79ad662deacff0a952cba70dbart      DRD_(thread_update_conflict_set)(joiner, &old_vc);
1114e5214666ead5aebb79ad662deacff0a952cba70dbart      s_update_conflict_set_join_count++;
1115e5214666ead5aebb79ad662deacff0a952cba70dbart      DRD_(vc_cleanup)(&old_vc);
1116ae37e6d4c9ca1f400ef4c1636319be60f969b2afbart   } else {
1117c6bf1846c7604390f777f88b63710702686086d9bart      DRD_(vc_combine)(DRD_(thread_get_vc)(joiner),
1118c6bf1846c7604390f777f88b63710702686086d9bart                       DRD_(thread_get_vc)(joinee));
1119e5214666ead5aebb79ad662deacff0a952cba70dbart   }
1120e5214666ead5aebb79ad662deacff0a952cba70dbart
1121e5214666ead5aebb79ad662deacff0a952cba70dbart   thread_discard_ordered_segments();
1122e5214666ead5aebb79ad662deacff0a952cba70dbart
1123ae37e6d4c9ca1f400ef4c1636319be60f969b2afbart   if (DRD_(sg_get_trace)()) {
112419f91bbaedb4caef8a60ce94b0f507193cc0bc10florian      HChar* str;
1125ae37e6d4c9ca1f400ef4c1636319be60f969b2afbart
1126c6bf1846c7604390f777f88b63710702686086d9bart      str = DRD_(vc_aprint)(DRD_(thread_get_vc)(joiner));
11271e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj      VG_(message)(Vg_DebugMsg, "After join: %s\n", str);
11288f822af9b234e7c553c408eba65a641c4773457fbart      VG_(free)(str);
11298f822af9b234e7c553c408eba65a641c4773457fbart   }
1130af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
1131af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
1132324a23bea57e0bfc27d9442ec00a8eee8294f01abart/**
11338f822af9b234e7c553c408eba65a641c4773457fbart * Update the vector clock of the last segment of thread tid with the
1134f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart * the vector clock of segment sg.
113526f73e12ef03bb04ebee5cccd8da08cddb426341bart */
1136f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bartstatic void thread_combine_vc_sync(DrdThreadId tid, const Segment* sg)
1137af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
11388f822af9b234e7c553c408eba65a641c4773457fbart   const VectorClock* const vc = &sg->vc;
11398f822af9b234e7c553c408eba65a641c4773457fbart
1140bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1141bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
114291b7ec3660efe16790bc337190a1c948beaab0a5bart   tl_assert(DRD_(g_threadinfo)[tid].sg_first);
114391b7ec3660efe16790bc337190a1c948beaab0a5bart   tl_assert(DRD_(g_threadinfo)[tid].sg_last);
11448f822af9b234e7c553c408eba65a641c4773457fbart   tl_assert(sg);
1145bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(vc);
11468f822af9b234e7c553c408eba65a641c4773457fbart
1147ae37e6d4c9ca1f400ef4c1636319be60f969b2afbart   if (tid != sg->tid) {
11488f822af9b234e7c553c408eba65a641c4773457fbart      VectorClock old_vc;
11498f822af9b234e7c553c408eba65a641c4773457fbart
1150c6bf1846c7604390f777f88b63710702686086d9bart      DRD_(vc_copy)(&old_vc, DRD_(thread_get_vc)(tid));
1151c6bf1846c7604390f777f88b63710702686086d9bart      DRD_(vc_combine)(DRD_(thread_get_vc)(tid), vc);
1152ae37e6d4c9ca1f400ef4c1636319be60f969b2afbart      if (DRD_(sg_get_trace)()) {
115319f91bbaedb4caef8a60ce94b0f507193cc0bc10florian         HChar *str1, *str2;
11548f822af9b234e7c553c408eba65a641c4773457fbart         str1 = DRD_(vc_aprint)(&old_vc);
1155c6bf1846c7604390f777f88b63710702686086d9bart         str2 = DRD_(vc_aprint)(DRD_(thread_get_vc)(tid));
11561e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj         VG_(message)(Vg_DebugMsg, "thread %d: vc %s -> %s\n", tid, str1, str2);
11578f822af9b234e7c553c408eba65a641c4773457fbart         VG_(free)(str1);
11588f822af9b234e7c553c408eba65a641c4773457fbart         VG_(free)(str2);
11598f822af9b234e7c553c408eba65a641c4773457fbart      }
1160e5214666ead5aebb79ad662deacff0a952cba70dbart
11618f822af9b234e7c553c408eba65a641c4773457fbart      thread_discard_ordered_segments();
1162e5214666ead5aebb79ad662deacff0a952cba70dbart
11638f822af9b234e7c553c408eba65a641c4773457fbart      DRD_(thread_update_conflict_set)(tid, &old_vc);
1164e5214666ead5aebb79ad662deacff0a952cba70dbart      s_update_conflict_set_sync_count++;
1165e5214666ead5aebb79ad662deacff0a952cba70dbart
11668f822af9b234e7c553c408eba65a641c4773457fbart      DRD_(vc_cleanup)(&old_vc);
1167ae37e6d4c9ca1f400ef4c1636319be60f969b2afbart   } else {
1168c6bf1846c7604390f777f88b63710702686086d9bart      tl_assert(DRD_(vc_lte)(vc, DRD_(thread_get_vc)(tid)));
11698f822af9b234e7c553c408eba65a641c4773457fbart   }
1170af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
1171af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
1172324a23bea57e0bfc27d9442ec00a8eee8294f01abart/**
1173f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart * Create a new segment for thread tid and update the vector clock of the last
1174f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart * segment of this thread with the the vector clock of segment sg. Call this
1175f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart * function after thread tid had to wait because of thread synchronization
1176f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart * until the memory accesses in the segment sg finished.
1177f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart */
1178f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bartvoid DRD_(thread_new_segment_and_combine_vc)(DrdThreadId tid, const Segment* sg)
1179f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart{
1180f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1181f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart             && tid != DRD_INVALID_THREADID);
1182f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart   tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1183f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart   tl_assert(sg);
1184f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart
1185f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart   thread_append_segment(tid, DRD_(sg_new)(tid, tid));
1186f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart
1187f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart   thread_combine_vc_sync(tid, sg);
1188f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart
1189f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart   if (s_segment_merging
1190f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart       && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
1191f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart   {
1192f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart      thread_discard_ordered_segments();
1193f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart      thread_merge_segments();
1194f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart   }
1195f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart}
1196f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart
1197f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart/**
1198324a23bea57e0bfc27d9442ec00a8eee8294f01abart * Call this function whenever a thread is no longer using the memory
1199324a23bea57e0bfc27d9442ec00a8eee8294f01abart * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
1200324a23bea57e0bfc27d9442ec00a8eee8294f01abart * increase.
120126f73e12ef03bb04ebee5cccd8da08cddb426341bart */
120223ef19de837854c360809e59833513360dc1cce2bartvoid DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2)
1203af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
1204178b686b4886b7c196df3b5fdd1187113c4e547dbart   Segment* p;
1205bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
120691b7ec3660efe16790bc337190a1c948beaab0a5bart   for (p = DRD_(g_sg_list); p; p = p->g_next)
1207e278ab506b9a73ef1c17a17077546b2de9a11d7cbart      DRD_(bm_clear)(DRD_(sg_bm)(p), a1, a2);
1208bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
1209178b686b4886b7c196df3b5fdd1187113c4e547dbart   DRD_(bm_clear)(DRD_(g_conflict_set), a1, a2);
1210af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
1211af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
1212d45d99553c15a361bb797d21ec6afb9bad22d2d4bart/** Specify whether memory loads should be recorded. */
1213d45d99553c15a361bb797d21ec6afb9bad22d2d4bartvoid DRD_(thread_set_record_loads)(const DrdThreadId tid, const Bool enabled)
12140268dfacec38138a01a58d05a038826e26b6c436bart{
1215bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1216bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
1217d45d99553c15a361bb797d21ec6afb9bad22d2d4bart   tl_assert(enabled == !! enabled);
1218d45d99553c15a361bb797d21ec6afb9bad22d2d4bart
1219d45d99553c15a361bb797d21ec6afb9bad22d2d4bart   DRD_(g_threadinfo)[tid].is_recording_loads = enabled;
12200268dfacec38138a01a58d05a038826e26b6c436bart}
12210268dfacec38138a01a58d05a038826e26b6c436bart
1222d45d99553c15a361bb797d21ec6afb9bad22d2d4bart/** Specify whether memory stores should be recorded. */
1223d45d99553c15a361bb797d21ec6afb9bad22d2d4bartvoid DRD_(thread_set_record_stores)(const DrdThreadId tid, const Bool enabled)
12240268dfacec38138a01a58d05a038826e26b6c436bart{
1225bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1226bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
1227d45d99553c15a361bb797d21ec6afb9bad22d2d4bart   tl_assert(enabled == !! enabled);
1228d45d99553c15a361bb797d21ec6afb9bad22d2d4bart
1229d45d99553c15a361bb797d21ec6afb9bad22d2d4bart   DRD_(g_threadinfo)[tid].is_recording_stores = enabled;
12300268dfacec38138a01a58d05a038826e26b6c436bart}
12310268dfacec38138a01a58d05a038826e26b6c436bart
123286a87df5949beb1f89ebbed923068faed08d048cbart/**
123386a87df5949beb1f89ebbed923068faed08d048cbart * Print the segment information for all threads.
123486a87df5949beb1f89ebbed923068faed08d048cbart *
123586a87df5949beb1f89ebbed923068faed08d048cbart * This function is only used for debugging purposes.
123686a87df5949beb1f89ebbed923068faed08d048cbart */
123762a784c9382fdf7184065ad76ae8d3b905605f21bartvoid DRD_(thread_print_all)(void)
1238af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
1239bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   unsigned i;
1240bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   Segment* p;
1241bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
12428f822af9b234e7c553c408eba65a641c4773457fbart   for (i = 0; i < DRD_N_THREADS; i++)
1243bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
124491b7ec3660efe16790bc337190a1c948beaab0a5bart      p = DRD_(g_threadinfo)[i].sg_first;
124591b7ec3660efe16790bc337190a1c948beaab0a5bart      if (p) {
1246bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         VG_(printf)("**************\n"
12476d956dc21b6a81f0c67ad18ac61867da0d5922a3bart                     "* thread %3d (%d/%d/%d/%d/0x%lx/%d) *\n"
1248bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                     "**************\n",
1249bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                     i,
12506d956dc21b6a81f0c67ad18ac61867da0d5922a3bart                     DRD_(g_threadinfo)[i].valid,
1251bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                     DRD_(g_threadinfo)[i].vg_thread_exists,
1252bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                     DRD_(g_threadinfo)[i].vg_threadid,
1253bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                     DRD_(g_threadinfo)[i].posix_thread_exists,
1254bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                     DRD_(g_threadinfo)[i].pt_threadid,
1255bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                     DRD_(g_threadinfo)[i].detached_posix_thread);
125691b7ec3660efe16790bc337190a1c948beaab0a5bart         for ( ; p; p = p->thr_next)
1257bedfd237fbdc80d0c917cfcb85a94b5561c92633bart            DRD_(sg_print)(p);
1258af44c8236f7a73e71b16b707bba56f33af4d01cesewardj      }
1259bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
1260af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
1261af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
126286a87df5949beb1f89ebbed923068faed08d048cbart/** Show a call stack involved in a data race. */
1263e7086000dc09e5486e42206ad524fefe09f7cc72bartstatic void show_call_stack(const DrdThreadId tid, ExeContext* const callstack)
1264af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
1265bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   const ThreadId vg_tid = DRD_(DrdThreadIdToVgThreadId)(tid);
1266bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
1267e7086000dc09e5486e42206ad524fefe09f7cc72bart   if (vg_tid != VG_INVALID_THREADID) {
1268bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      if (callstack)
1269bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         VG_(pp_ExeContext)(callstack);
1270bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      else
1271bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
1272e7086000dc09e5486e42206ad524fefe09f7cc72bart   } else {
1273e7086000dc09e5486e42206ad524fefe09f7cc72bart      if (!VG_(clo_xml))
1274e7086000dc09e5486e42206ad524fefe09f7cc72bart         VG_(message)(Vg_UserMsg,
1275e7086000dc09e5486e42206ad524fefe09f7cc72bart                      "   (thread finished, call stack no longer available)\n");
1276bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
1277af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
1278af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
127986a87df5949beb1f89ebbed923068faed08d048cbart/** Print information about the segments involved in a data race. */
1280af44c8236f7a73e71b16b707bba56f33af4d01cesewardjstatic void
1281af44c8236f7a73e71b16b707bba56f33af4d01cesewardjthread_report_conflicting_segments_segment(const DrdThreadId tid,
1282af44c8236f7a73e71b16b707bba56f33af4d01cesewardj                                           const Addr addr,
1283af44c8236f7a73e71b16b707bba56f33af4d01cesewardj                                           const SizeT size,
1284af44c8236f7a73e71b16b707bba56f33af4d01cesewardj                                           const BmAccessTypeT access_type,
1285af44c8236f7a73e71b16b707bba56f33af4d01cesewardj                                           const Segment* const p)
1286af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
1287bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   unsigned i;
1288bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
1289bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1290bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
1291bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(p);
1292bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
129391b7ec3660efe16790bc337190a1c948beaab0a5bart   for (i = 0; i < DRD_N_THREADS; i++) {
129491b7ec3660efe16790bc337190a1c948beaab0a5bart      if (i != tid) {
1295bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         Segment* q;
1296e278ab506b9a73ef1c17a17077546b2de9a11d7cbart
129791b7ec3660efe16790bc337190a1c948beaab0a5bart         for (q = DRD_(g_threadinfo)[i].sg_last; q; q = q->thr_prev) {
1298bedfd237fbdc80d0c917cfcb85a94b5561c92633bart            /*
129931b983d29affe6c30a2283be8824c6d75c74d848bart             * Since q iterates over the segments of thread i in order of
130031b983d29affe6c30a2283be8824c6d75c74d848bart             * decreasing vector clocks, if q->vc <= p->vc, then
1301bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             * q->next->vc <= p->vc will also hold. Hence, break out of the
1302bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             * loop once this condition is met.
1303bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             */
1304bedfd237fbdc80d0c917cfcb85a94b5561c92633bart            if (DRD_(vc_lte)(&q->vc, &p->vc))
1305bedfd237fbdc80d0c917cfcb85a94b5561c92633bart               break;
130691b7ec3660efe16790bc337190a1c948beaab0a5bart            if (!DRD_(vc_lte)(&p->vc, &q->vc)) {
13078f822af9b234e7c553c408eba65a641c4773457fbart               if (DRD_(bm_has_conflict_with)(DRD_(sg_bm)(q), addr, addr + size,
130891b7ec3660efe16790bc337190a1c948beaab0a5bart                                              access_type)) {
1309e278ab506b9a73ef1c17a17077546b2de9a11d7cbart                  Segment* q_next;
1310e278ab506b9a73ef1c17a17077546b2de9a11d7cbart
1311bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                  tl_assert(q->stacktrace);
1312e7086000dc09e5486e42206ad524fefe09f7cc72bart                  if (VG_(clo_xml))
1313e7086000dc09e5486e42206ad524fefe09f7cc72bart                     VG_(printf_xml)("  <other_segment_start>\n");
1314e7086000dc09e5486e42206ad524fefe09f7cc72bart                  else
1315e7086000dc09e5486e42206ad524fefe09f7cc72bart                     VG_(message)(Vg_UserMsg,
1316e7086000dc09e5486e42206ad524fefe09f7cc72bart                                  "Other segment start (thread %d)\n", i);
1317e7086000dc09e5486e42206ad524fefe09f7cc72bart                  show_call_stack(i, q->stacktrace);
1318e7086000dc09e5486e42206ad524fefe09f7cc72bart                  if (VG_(clo_xml))
1319e7086000dc09e5486e42206ad524fefe09f7cc72bart                     VG_(printf_xml)("  </other_segment_start>\n"
1320e7086000dc09e5486e42206ad524fefe09f7cc72bart                                     "  <other_segment_end>\n");
1321e7086000dc09e5486e42206ad524fefe09f7cc72bart                  else
1322e7086000dc09e5486e42206ad524fefe09f7cc72bart                     VG_(message)(Vg_UserMsg,
1323e7086000dc09e5486e42206ad524fefe09f7cc72bart                                  "Other segment end (thread %d)\n", i);
132491b7ec3660efe16790bc337190a1c948beaab0a5bart                  q_next = q->thr_next;
1325e278ab506b9a73ef1c17a17077546b2de9a11d7cbart                  show_call_stack(i, q_next ? q_next->stacktrace : 0);
1326e7086000dc09e5486e42206ad524fefe09f7cc72bart                  if (VG_(clo_xml))
1327e7086000dc09e5486e42206ad524fefe09f7cc72bart                     VG_(printf_xml)("  </other_segment_end>\n");
1328bedfd237fbdc80d0c917cfcb85a94b5561c92633bart               }
1329bedfd237fbdc80d0c917cfcb85a94b5561c92633bart            }
1330bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         }
1331af44c8236f7a73e71b16b707bba56f33af4d01cesewardj      }
1332bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
1333af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
1334af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
133586a87df5949beb1f89ebbed923068faed08d048cbart/** Print information about all segments involved in a data race. */
133662a784c9382fdf7184065ad76ae8d3b905605f21bartvoid DRD_(thread_report_conflicting_segments)(const DrdThreadId tid,
133762a784c9382fdf7184065ad76ae8d3b905605f21bart                                              const Addr addr,
133862a784c9382fdf7184065ad76ae8d3b905605f21bart                                              const SizeT size,
133962a784c9382fdf7184065ad76ae8d3b905605f21bart                                              const BmAccessTypeT access_type)
1340af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
1341bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   Segment* p;
1342bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
1343bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1344bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
1345bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
134691b7ec3660efe16790bc337190a1c948beaab0a5bart   for (p = DRD_(g_threadinfo)[tid].sg_first; p; p = p->thr_next) {
13478f822af9b234e7c553c408eba65a641c4773457fbart      if (DRD_(bm_has)(DRD_(sg_bm)(p), addr, addr + size, access_type))
1348bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         thread_report_conflicting_segments_segment(tid, addr, size,
1349bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                                                    access_type, p);
1350bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
1351af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
1352af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
1353324a23bea57e0bfc27d9442ec00a8eee8294f01abart/**
13548f822af9b234e7c553c408eba65a641c4773457fbart * Verify whether the conflict set for thread tid is up to date. Only perform
13558f822af9b234e7c553c408eba65a641c4773457fbart * the check if the environment variable DRD_VERIFY_CONFLICT_SET has been set.
13568f822af9b234e7c553c408eba65a641c4773457fbart */
13578f822af9b234e7c553c408eba65a641c4773457fbartstatic Bool thread_conflict_set_up_to_date(const DrdThreadId tid)
13588f822af9b234e7c553c408eba65a641c4773457fbart{
13598f822af9b234e7c553c408eba65a641c4773457fbart   Bool result;
13608f822af9b234e7c553c408eba65a641c4773457fbart   struct bitmap* computed_conflict_set = 0;
13618f822af9b234e7c553c408eba65a641c4773457fbart
13629cdc08368068d746e42d40c8f3a3dca5db5caee4bart   if (!DRD_(verify_conflict_set))
13638f822af9b234e7c553c408eba65a641c4773457fbart      return True;
13648f822af9b234e7c553c408eba65a641c4773457fbart
13658f822af9b234e7c553c408eba65a641c4773457fbart   thread_compute_conflict_set(&computed_conflict_set, tid);
13668f822af9b234e7c553c408eba65a641c4773457fbart   result = DRD_(bm_equal)(DRD_(g_conflict_set), computed_conflict_set);
13678f822af9b234e7c553c408eba65a641c4773457fbart   if (! result)
13688f822af9b234e7c553c408eba65a641c4773457fbart   {
13698f822af9b234e7c553c408eba65a641c4773457fbart      VG_(printf)("actual conflict set:\n");
13708f822af9b234e7c553c408eba65a641c4773457fbart      DRD_(bm_print)(DRD_(g_conflict_set));
13718f822af9b234e7c553c408eba65a641c4773457fbart      VG_(printf)("\n");
13728f822af9b234e7c553c408eba65a641c4773457fbart      VG_(printf)("computed conflict set:\n");
13738f822af9b234e7c553c408eba65a641c4773457fbart      DRD_(bm_print)(computed_conflict_set);
13748f822af9b234e7c553c408eba65a641c4773457fbart      VG_(printf)("\n");
13758f822af9b234e7c553c408eba65a641c4773457fbart   }
13768f822af9b234e7c553c408eba65a641c4773457fbart   DRD_(bm_delete)(computed_conflict_set);
13778f822af9b234e7c553c408eba65a641c4773457fbart   return result;
13788f822af9b234e7c553c408eba65a641c4773457fbart}
13798f822af9b234e7c553c408eba65a641c4773457fbart
13808f822af9b234e7c553c408eba65a641c4773457fbart/**
13818f822af9b234e7c553c408eba65a641c4773457fbart * Compute the conflict set: a bitmap that represents the union of all memory
13828f822af9b234e7c553c408eba65a641c4773457fbart * accesses of all segments that are unordered to the current segment of the
13838f822af9b234e7c553c408eba65a641c4773457fbart * thread tid.
1384af44c8236f7a73e71b16b707bba56f33af4d01cesewardj */
138586a87df5949beb1f89ebbed923068faed08d048cbartstatic void thread_compute_conflict_set(struct bitmap** conflict_set,
138686a87df5949beb1f89ebbed923068faed08d048cbart                                        const DrdThreadId tid)
1387af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
1388bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   Segment* p;
1389bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
1390bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
1391bedfd237fbdc80d0c917cfcb85a94b5561c92633bart             && tid != DRD_INVALID_THREADID);
1392bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   tl_assert(tid == DRD_(g_drd_running_tid));
1393bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
139454803feb0b92e4708d3cee92e7449f802be70197bart   s_compute_conflict_set_count++;
1395bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   s_conflict_set_bitmap_creation_count
1396bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      -= DRD_(bm_get_bitmap_creation_count)();
1397bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   s_conflict_set_bitmap2_creation_count
1398bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      -= DRD_(bm_get_bitmap2_creation_count)();
1399bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
1400ae37e6d4c9ca1f400ef4c1636319be60f969b2afbart   if (*conflict_set) {
1401f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart      DRD_(bm_cleanup)(*conflict_set);
1402f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart      DRD_(bm_init)(*conflict_set);
1403ae37e6d4c9ca1f400ef4c1636319be60f969b2afbart   } else {
1404f6ec1fe18f1fc1222fb274d7dfd4343c16048fb1bart      *conflict_set = DRD_(bm_new)();
1405bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
1406bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
1407ae37e6d4c9ca1f400ef4c1636319be60f969b2afbart   if (s_trace_conflict_set) {
140819f91bbaedb4caef8a60ce94b0f507193cc0bc10florian      HChar* str;
14098f822af9b234e7c553c408eba65a641c4773457fbart
1410c6bf1846c7604390f777f88b63710702686086d9bart      str = DRD_(vc_aprint)(DRD_(thread_get_vc)(tid));
14118f822af9b234e7c553c408eba65a641c4773457fbart      VG_(message)(Vg_DebugMsg,
141263c92ea799549976957f5b4d54ede744f762c56fbart                   "computing conflict set for thread %d with vc %s\n",
141363c92ea799549976957f5b4d54ede744f762c56fbart                   tid, str);
14148f822af9b234e7c553c408eba65a641c4773457fbart      VG_(free)(str);
1415bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
1416bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
141791b7ec3660efe16790bc337190a1c948beaab0a5bart   p = DRD_(g_threadinfo)[tid].sg_last;
1418bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   {
1419bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      unsigned j;
1420af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
142191b7ec3660efe16790bc337190a1c948beaab0a5bart      if (s_trace_conflict_set) {
142219f91bbaedb4caef8a60ce94b0f507193cc0bc10florian         HChar* vc;
14238f822af9b234e7c553c408eba65a641c4773457fbart
14248f822af9b234e7c553c408eba65a641c4773457fbart         vc = DRD_(vc_aprint)(&p->vc);
14251e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj         VG_(message)(Vg_DebugMsg, "conflict set: thread [%d] at vc %s\n",
14268f822af9b234e7c553c408eba65a641c4773457fbart                      tid, vc);
14278f822af9b234e7c553c408eba65a641c4773457fbart         VG_(free)(vc);
1428bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      }
1429bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
143091b7ec3660efe16790bc337190a1c948beaab0a5bart      for (j = 0; j < DRD_N_THREADS; j++) {
143191b7ec3660efe16790bc337190a1c948beaab0a5bart         if (j != tid && DRD_(IsValidDrdThreadId)(j)) {
14328f822af9b234e7c553c408eba65a641c4773457fbart            Segment* q;
143391b7ec3660efe16790bc337190a1c948beaab0a5bart
143491b7ec3660efe16790bc337190a1c948beaab0a5bart            for (q = DRD_(g_threadinfo)[j].sg_last; q; q = q->thr_prev) {
143591b7ec3660efe16790bc337190a1c948beaab0a5bart               if (!DRD_(vc_lte)(&q->vc, &p->vc)
143691b7ec3660efe16790bc337190a1c948beaab0a5bart                   && !DRD_(vc_lte)(&p->vc, &q->vc)) {
143791b7ec3660efe16790bc337190a1c948beaab0a5bart                  if (s_trace_conflict_set) {
143819f91bbaedb4caef8a60ce94b0f507193cc0bc10florian                     HChar* str;
14398f822af9b234e7c553c408eba65a641c4773457fbart
14408f822af9b234e7c553c408eba65a641c4773457fbart                     str = DRD_(vc_aprint)(&q->vc);
14418f822af9b234e7c553c408eba65a641c4773457fbart                     VG_(message)(Vg_DebugMsg,
14421e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj                                  "conflict set: [%d] merging segment %s\n",
14438f822af9b234e7c553c408eba65a641c4773457fbart                                  j, str);
14448f822af9b234e7c553c408eba65a641c4773457fbart                     VG_(free)(str);
1445bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                  }
14468f822af9b234e7c553c408eba65a641c4773457fbart                  DRD_(bm_merge2)(*conflict_set, DRD_(sg_bm)(q));
144791b7ec3660efe16790bc337190a1c948beaab0a5bart               } else {
144891b7ec3660efe16790bc337190a1c948beaab0a5bart                  if (s_trace_conflict_set) {
144919f91bbaedb4caef8a60ce94b0f507193cc0bc10florian                     HChar* str;
14508f822af9b234e7c553c408eba65a641c4773457fbart
14518f822af9b234e7c553c408eba65a641c4773457fbart                     str = DRD_(vc_aprint)(&q->vc);
14528f822af9b234e7c553c408eba65a641c4773457fbart                     VG_(message)(Vg_DebugMsg,
14531e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj                                  "conflict set: [%d] ignoring segment %s\n",
14548f822af9b234e7c553c408eba65a641c4773457fbart                                  j, str);
14558f822af9b234e7c553c408eba65a641c4773457fbart                     VG_(free)(str);
1456bedfd237fbdc80d0c917cfcb85a94b5561c92633bart                  }
1457bedfd237fbdc80d0c917cfcb85a94b5561c92633bart               }
145826f73e12ef03bb04ebee5cccd8da08cddb426341bart            }
1459bedfd237fbdc80d0c917cfcb85a94b5561c92633bart         }
1460af44c8236f7a73e71b16b707bba56f33af4d01cesewardj      }
1461bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
1462bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
1463bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   s_conflict_set_bitmap_creation_count
1464bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      += DRD_(bm_get_bitmap_creation_count)();
1465bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   s_conflict_set_bitmap2_creation_count
1466bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      += DRD_(bm_get_bitmap2_creation_count)();
1467bedfd237fbdc80d0c917cfcb85a94b5561c92633bart
146891b7ec3660efe16790bc337190a1c948beaab0a5bart   if (s_trace_conflict_set_bm) {
14691e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj      VG_(message)(Vg_DebugMsg, "[%d] new conflict set:\n", tid);
1470bedfd237fbdc80d0c917cfcb85a94b5561c92633bart      DRD_(bm_print)(*conflict_set);
14711e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj      VG_(message)(Vg_DebugMsg, "[%d] end of new conflict set.\n", tid);
14728f822af9b234e7c553c408eba65a641c4773457fbart   }
14738f822af9b234e7c553c408eba65a641c4773457fbart}
14748f822af9b234e7c553c408eba65a641c4773457fbart
14758f822af9b234e7c553c408eba65a641c4773457fbart/**
14768f822af9b234e7c553c408eba65a641c4773457fbart * Update the conflict set after the vector clock of thread tid has been
14778f822af9b234e7c553c408eba65a641c4773457fbart * updated from old_vc to its current value, either because a new segment has
14788f822af9b234e7c553c408eba65a641c4773457fbart * been created or because of a synchronization operation.
14798f822af9b234e7c553c408eba65a641c4773457fbart */
14808f822af9b234e7c553c408eba65a641c4773457fbartvoid DRD_(thread_update_conflict_set)(const DrdThreadId tid,
14818f822af9b234e7c553c408eba65a641c4773457fbart                                      const VectorClock* const old_vc)
14828f822af9b234e7c553c408eba65a641c4773457fbart{
14838f822af9b234e7c553c408eba65a641c4773457fbart   const VectorClock* new_vc;
14848f822af9b234e7c553c408eba65a641c4773457fbart   Segment* p;
14858f822af9b234e7c553c408eba65a641c4773457fbart   unsigned j;
14868f822af9b234e7c553c408eba65a641c4773457fbart
14878f822af9b234e7c553c408eba65a641c4773457fbart   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
14888f822af9b234e7c553c408eba65a641c4773457fbart             && tid != DRD_INVALID_THREADID);
14898f822af9b234e7c553c408eba65a641c4773457fbart   tl_assert(old_vc);
14908f822af9b234e7c553c408eba65a641c4773457fbart   tl_assert(tid == DRD_(g_drd_running_tid));
14918f822af9b234e7c553c408eba65a641c4773457fbart   tl_assert(DRD_(g_conflict_set));
14928f822af9b234e7c553c408eba65a641c4773457fbart
1493ae37e6d4c9ca1f400ef4c1636319be60f969b2afbart   if (s_trace_conflict_set) {
149419f91bbaedb4caef8a60ce94b0f507193cc0bc10florian      HChar* str;
14958f822af9b234e7c553c408eba65a641c4773457fbart
1496c6bf1846c7604390f777f88b63710702686086d9bart      str = DRD_(vc_aprint)(DRD_(thread_get_vc)(tid));
14978f822af9b234e7c553c408eba65a641c4773457fbart      VG_(message)(Vg_DebugMsg,
149863c92ea799549976957f5b4d54ede744f762c56fbart                   "updating conflict set for thread %d with vc %s\n",
149963c92ea799549976957f5b4d54ede744f762c56fbart                   tid, str);
15008f822af9b234e7c553c408eba65a641c4773457fbart      VG_(free)(str);
15018f822af9b234e7c553c408eba65a641c4773457fbart   }
15028f822af9b234e7c553c408eba65a641c4773457fbart
1503c6bf1846c7604390f777f88b63710702686086d9bart   new_vc = DRD_(thread_get_vc)(tid);
1504f5fe4b66b06998f8fa0eaa2bb17eb34eb0e3bbdebart   tl_assert(DRD_(vc_lte)(old_vc, new_vc));
15058f822af9b234e7c553c408eba65a641c4773457fbart
15068f822af9b234e7c553c408eba65a641c4773457fbart   DRD_(bm_unmark)(DRD_(g_conflict_set));
15078f822af9b234e7c553c408eba65a641c4773457fbart
15088f822af9b234e7c553c408eba65a641c4773457fbart   for (j = 0; j < DRD_N_THREADS; j++)
15098f822af9b234e7c553c408eba65a641c4773457fbart   {
15108f822af9b234e7c553c408eba65a641c4773457fbart      Segment* q;
15118f822af9b234e7c553c408eba65a641c4773457fbart
15128f822af9b234e7c553c408eba65a641c4773457fbart      if (j == tid || ! DRD_(IsValidDrdThreadId)(j))
15138f822af9b234e7c553c408eba65a641c4773457fbart         continue;
15148f822af9b234e7c553c408eba65a641c4773457fbart
151591b7ec3660efe16790bc337190a1c948beaab0a5bart      for (q = DRD_(g_threadinfo)[j].sg_last;
151691b7ec3660efe16790bc337190a1c948beaab0a5bart           q && !DRD_(vc_lte)(&q->vc, new_vc);
151791b7ec3660efe16790bc337190a1c948beaab0a5bart           q = q->thr_prev) {
151891b7ec3660efe16790bc337190a1c948beaab0a5bart         const Bool included_in_old_conflict_set
151991b7ec3660efe16790bc337190a1c948beaab0a5bart            = !DRD_(vc_lte)(old_vc, &q->vc);
152091b7ec3660efe16790bc337190a1c948beaab0a5bart         const Bool included_in_new_conflict_set
152191b7ec3660efe16790bc337190a1c948beaab0a5bart            = !DRD_(vc_lte)(new_vc, &q->vc);
1522178b686b4886b7c196df3b5fdd1187113c4e547dbart
1523178b686b4886b7c196df3b5fdd1187113c4e547dbart         if (UNLIKELY(s_trace_conflict_set)) {
152419f91bbaedb4caef8a60ce94b0f507193cc0bc10florian            HChar* str;
1525178b686b4886b7c196df3b5fdd1187113c4e547dbart
1526178b686b4886b7c196df3b5fdd1187113c4e547dbart            str = DRD_(vc_aprint)(&q->vc);
1527178b686b4886b7c196df3b5fdd1187113c4e547dbart            VG_(message)(Vg_DebugMsg,
1528178b686b4886b7c196df3b5fdd1187113c4e547dbart                         "conflict set: [%d] %s segment %s\n", j,
1529178b686b4886b7c196df3b5fdd1187113c4e547dbart                         included_in_old_conflict_set
1530178b686b4886b7c196df3b5fdd1187113c4e547dbart                         != included_in_new_conflict_set
1531178b686b4886b7c196df3b5fdd1187113c4e547dbart                         ? "merging" : "ignoring", str);
1532178b686b4886b7c196df3b5fdd1187113c4e547dbart            VG_(free)(str);
1533178b686b4886b7c196df3b5fdd1187113c4e547dbart         }
1534178b686b4886b7c196df3b5fdd1187113c4e547dbart         if (included_in_old_conflict_set != included_in_new_conflict_set)
1535178b686b4886b7c196df3b5fdd1187113c4e547dbart            DRD_(bm_mark)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
1536178b686b4886b7c196df3b5fdd1187113c4e547dbart      }
1537178b686b4886b7c196df3b5fdd1187113c4e547dbart
153891b7ec3660efe16790bc337190a1c948beaab0a5bart      for ( ; q && !DRD_(vc_lte)(&q->vc, old_vc); q = q->thr_prev) {
153991b7ec3660efe16790bc337190a1c948beaab0a5bart         const Bool included_in_old_conflict_set
154091b7ec3660efe16790bc337190a1c948beaab0a5bart            = !DRD_(vc_lte)(old_vc, &q->vc);
154191b7ec3660efe16790bc337190a1c948beaab0a5bart         const Bool included_in_new_conflict_set
154291b7ec3660efe16790bc337190a1c948beaab0a5bart            = !DRD_(vc_lte)(&q->vc, new_vc)
154391b7ec3660efe16790bc337190a1c948beaab0a5bart            && !DRD_(vc_lte)(new_vc, &q->vc);
1544178b686b4886b7c196df3b5fdd1187113c4e547dbart
1545178b686b4886b7c196df3b5fdd1187113c4e547dbart         if (UNLIKELY(s_trace_conflict_set)) {
154619f91bbaedb4caef8a60ce94b0f507193cc0bc10florian            HChar* str;
1547ac5b95bcdf94a728d8a603712b371eab26df897dbart
1548ac5b95bcdf94a728d8a603712b371eab26df897dbart            str = DRD_(vc_aprint)(&q->vc);
1549ac5b95bcdf94a728d8a603712b371eab26df897dbart            VG_(message)(Vg_DebugMsg,
1550ac5b95bcdf94a728d8a603712b371eab26df897dbart                         "conflict set: [%d] %s segment %s\n", j,
1551ac5b95bcdf94a728d8a603712b371eab26df897dbart                         included_in_old_conflict_set
1552ac5b95bcdf94a728d8a603712b371eab26df897dbart                         != included_in_new_conflict_set
1553ac5b95bcdf94a728d8a603712b371eab26df897dbart                         ? "merging" : "ignoring", str);
1554ac5b95bcdf94a728d8a603712b371eab26df897dbart            VG_(free)(str);
1555ac5b95bcdf94a728d8a603712b371eab26df897dbart         }
15568f822af9b234e7c553c408eba65a641c4773457fbart         if (included_in_old_conflict_set != included_in_new_conflict_set)
15578f822af9b234e7c553c408eba65a641c4773457fbart            DRD_(bm_mark)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
15588f822af9b234e7c553c408eba65a641c4773457fbart      }
15598f822af9b234e7c553c408eba65a641c4773457fbart   }
15608f822af9b234e7c553c408eba65a641c4773457fbart
15618f822af9b234e7c553c408eba65a641c4773457fbart   DRD_(bm_clear_marked)(DRD_(g_conflict_set));
15628f822af9b234e7c553c408eba65a641c4773457fbart
156391b7ec3660efe16790bc337190a1c948beaab0a5bart   p = DRD_(g_threadinfo)[tid].sg_last;
156491b7ec3660efe16790bc337190a1c948beaab0a5bart   for (j = 0; j < DRD_N_THREADS; j++) {
156591b7ec3660efe16790bc337190a1c948beaab0a5bart      if (j != tid && DRD_(IsValidDrdThreadId)(j)) {
15664b3fdb21a4e07b6f1d1b6753203703d7fdd9a785bart         Segment* q;
156791b7ec3660efe16790bc337190a1c948beaab0a5bart         for (q = DRD_(g_threadinfo)[j].sg_last;
156891b7ec3660efe16790bc337190a1c948beaab0a5bart              q && !DRD_(vc_lte)(&q->vc, &p->vc);
156991b7ec3660efe16790bc337190a1c948beaab0a5bart              q = q->thr_prev) {
1570178b686b4886b7c196df3b5fdd1187113c4e547dbart            if (!DRD_(vc_lte)(&p->vc, &q->vc))
15714b3fdb21a4e07b6f1d1b6753203703d7fdd9a785bart               DRD_(bm_merge2_marked)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
15728f822af9b234e7c553c408eba65a641c4773457fbart         }
15738f822af9b234e7c553c408eba65a641c4773457fbart      }
1574bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   }
15758f822af9b234e7c553c408eba65a641c4773457fbart
15768f822af9b234e7c553c408eba65a641c4773457fbart   DRD_(bm_remove_cleared_marked)(DRD_(g_conflict_set));
15778f822af9b234e7c553c408eba65a641c4773457fbart
157854803feb0b92e4708d3cee92e7449f802be70197bart   s_update_conflict_set_count++;
15798f822af9b234e7c553c408eba65a641c4773457fbart
15808f822af9b234e7c553c408eba65a641c4773457fbart   if (s_trace_conflict_set_bm)
15818f822af9b234e7c553c408eba65a641c4773457fbart   {
15821e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj      VG_(message)(Vg_DebugMsg, "[%d] updated conflict set:\n", tid);
15838f822af9b234e7c553c408eba65a641c4773457fbart      DRD_(bm_print)(DRD_(g_conflict_set));
15841e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj      VG_(message)(Vg_DebugMsg, "[%d] end of updated conflict set.\n", tid);
15858f822af9b234e7c553c408eba65a641c4773457fbart   }
15868f822af9b234e7c553c408eba65a641c4773457fbart
15878f822af9b234e7c553c408eba65a641c4773457fbart   tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
1588af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
1589af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
159086a87df5949beb1f89ebbed923068faed08d048cbart/** Report the number of context switches performed. */
159162a784c9382fdf7184065ad76ae8d3b905605f21bartULong DRD_(thread_get_context_switch_count)(void)
1592af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
1593bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return s_context_switch_count;
1594af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
1595af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
159686a87df5949beb1f89ebbed923068faed08d048cbart/** Report the number of ordered segments that have been discarded. */
159762a784c9382fdf7184065ad76ae8d3b905605f21bartULong DRD_(thread_get_discard_ordered_segments_count)(void)
1598af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
1599bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return s_discard_ordered_segments_count;
1600af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
1601af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
160254803feb0b92e4708d3cee92e7449f802be70197bart/** Return how many times the conflict set has been updated entirely. */
160354803feb0b92e4708d3cee92e7449f802be70197bartULong DRD_(thread_get_compute_conflict_set_count)()
160454803feb0b92e4708d3cee92e7449f802be70197bart{
160554803feb0b92e4708d3cee92e7449f802be70197bart   return s_compute_conflict_set_count;
160654803feb0b92e4708d3cee92e7449f802be70197bart}
160754803feb0b92e4708d3cee92e7449f802be70197bart
160854803feb0b92e4708d3cee92e7449f802be70197bart/** Return how many times the conflict set has been updated partially. */
160954803feb0b92e4708d3cee92e7449f802be70197bartULong DRD_(thread_get_update_conflict_set_count)(void)
1610af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
1611bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return s_update_conflict_set_count;
1612af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
1613af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
161486a87df5949beb1f89ebbed923068faed08d048cbart/**
1615e5214666ead5aebb79ad662deacff0a952cba70dbart * Return how many times the conflict set has been updated partially
1616e5214666ead5aebb79ad662deacff0a952cba70dbart * because a new segment has been created.
1617e5214666ead5aebb79ad662deacff0a952cba70dbart */
1618e5214666ead5aebb79ad662deacff0a952cba70dbartULong DRD_(thread_get_update_conflict_set_new_sg_count)(void)
1619e5214666ead5aebb79ad662deacff0a952cba70dbart{
1620e5214666ead5aebb79ad662deacff0a952cba70dbart   return s_update_conflict_set_new_sg_count;
1621e5214666ead5aebb79ad662deacff0a952cba70dbart}
1622e5214666ead5aebb79ad662deacff0a952cba70dbart
1623e5214666ead5aebb79ad662deacff0a952cba70dbart/**
1624e5214666ead5aebb79ad662deacff0a952cba70dbart * Return how many times the conflict set has been updated partially
1625e5214666ead5aebb79ad662deacff0a952cba70dbart * because of combining vector clocks due to synchronization operations
1626e5214666ead5aebb79ad662deacff0a952cba70dbart * other than reader/writer lock or barrier operations.
1627e5214666ead5aebb79ad662deacff0a952cba70dbart */
1628e5214666ead5aebb79ad662deacff0a952cba70dbartULong DRD_(thread_get_update_conflict_set_sync_count)(void)
1629e5214666ead5aebb79ad662deacff0a952cba70dbart{
1630e5214666ead5aebb79ad662deacff0a952cba70dbart   return s_update_conflict_set_sync_count;
1631e5214666ead5aebb79ad662deacff0a952cba70dbart}
1632e5214666ead5aebb79ad662deacff0a952cba70dbart
1633e5214666ead5aebb79ad662deacff0a952cba70dbart/**
1634e5214666ead5aebb79ad662deacff0a952cba70dbart * Return how many times the conflict set has been updated partially
1635e5214666ead5aebb79ad662deacff0a952cba70dbart * because of thread joins.
1636e5214666ead5aebb79ad662deacff0a952cba70dbart */
1637e5214666ead5aebb79ad662deacff0a952cba70dbartULong DRD_(thread_get_update_conflict_set_join_count)(void)
1638e5214666ead5aebb79ad662deacff0a952cba70dbart{
1639e5214666ead5aebb79ad662deacff0a952cba70dbart   return s_update_conflict_set_join_count;
1640e5214666ead5aebb79ad662deacff0a952cba70dbart}
1641e5214666ead5aebb79ad662deacff0a952cba70dbart
1642e5214666ead5aebb79ad662deacff0a952cba70dbart/**
164386a87df5949beb1f89ebbed923068faed08d048cbart * Return the number of first-level bitmaps that have been created during
164486a87df5949beb1f89ebbed923068faed08d048cbart * conflict set updates.
164586a87df5949beb1f89ebbed923068faed08d048cbart */
164662a784c9382fdf7184065ad76ae8d3b905605f21bartULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void)
1647af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
1648bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return s_conflict_set_bitmap_creation_count;
1649af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
1650af44c8236f7a73e71b16b707bba56f33af4d01cesewardj
165186a87df5949beb1f89ebbed923068faed08d048cbart/**
165286a87df5949beb1f89ebbed923068faed08d048cbart * Return the number of second-level bitmaps that have been created during
165386a87df5949beb1f89ebbed923068faed08d048cbart * conflict set updates.
165486a87df5949beb1f89ebbed923068faed08d048cbart */
165562a784c9382fdf7184065ad76ae8d3b905605f21bartULong DRD_(thread_get_conflict_set_bitmap2_creation_count)(void)
1656af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{
1657bedfd237fbdc80d0c917cfcb85a94b5561c92633bart   return s_conflict_set_bitmap2_creation_count;
1658af44c8236f7a73e71b16b707bba56f33af4d01cesewardj}
1659