From: Bart Van Assche Date: Sat, 22 Mar 2008 09:38:48 +0000 (+0000) Subject: Implemented segment merging. X-Git-Tag: svn/VALGRIND_3_4_0~823 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fd57d8b1f81852e10ca68709976ca2ec0238d831;p=thirdparty%2Fvalgrind.git Implemented segment merging. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@7750 --- diff --git a/exp-drd/drd_main.c b/exp-drd/drd_main.c index 758edc40a9..32f85bd909 100644 --- a/exp-drd/drd_main.c +++ b/exp-drd/drd_main.c @@ -71,20 +71,22 @@ static Addr drd_trace_address = 0; static Bool drd_process_cmd_line_option(Char* arg) { - Bool show_confl_seg = True; - Bool trace_barrier = False; - Bool trace_clientobj = False; - Bool trace_cond = False; - Bool trace_csw = False; - Bool trace_danger_set = False; - Bool trace_mutex = False; - Bool trace_rwlock = False; - Bool trace_segment = False; - Bool trace_semaphore = False; - Bool trace_suppression = False; - Char* trace_address = 0; + int segment_merging = -1; + int show_confl_seg = -1; + int trace_barrier = -1; + int trace_clientobj = -1; + int trace_cond = -1; + int trace_csw = -1; + int trace_danger_set = -1; + int trace_mutex = -1; + int trace_rwlock = -1; + int trace_segment = -1; + int trace_semaphore = -1; + int trace_suppression = -1; + Char* trace_address = 0; VG_BOOL_CLO (arg, "--drd-stats", drd_print_stats) + else VG_BOOL_CLO(arg, "--segment-merging", segment_merging) else VG_BOOL_CLO(arg, "--show-confl-seg", show_confl_seg) else VG_BOOL_CLO(arg, "--trace-barrier", trace_barrier) else VG_BOOL_CLO(arg, "--trace-clientobj", trace_clientobj) @@ -102,31 +104,33 @@ static Bool drd_process_cmd_line_option(Char* arg) else return False; - if (! show_confl_seg) + if (segment_merging != -1) + thread_set_segment_merging(segment_merging); + if (show_confl_seg != -1) set_show_conflicting_segments(show_confl_seg); if (trace_address) { drd_trace_address = VG_(strtoll16)(trace_address, 0); } - if (trace_barrier) + if (trace_barrier != -1) barrier_set_trace(trace_barrier); - if (trace_clientobj) + if (trace_clientobj != -1) clientobj_set_trace(trace_clientobj); - if (trace_cond) + if (trace_cond != -1) cond_set_trace(trace_cond); - if (trace_csw) + if (trace_csw != -1) thread_trace_context_switches(trace_csw); - if (trace_danger_set) + if (trace_danger_set != -1) thread_trace_danger_set(trace_danger_set); - if (trace_mutex) + if (trace_mutex != -1) mutex_set_trace(trace_mutex); - if (trace_rwlock) + if (trace_rwlock != -1) rwlock_set_trace(trace_rwlock); - if (trace_segment) + if (trace_segment != -1) sg_set_trace(trace_segment); - if (trace_semaphore) + if (trace_semaphore != -1) semaphore_set_trace(trace_semaphore); - if (trace_suppression) + if (trace_suppression != -1) suppression_set_trace(trace_suppression); return True; diff --git a/exp-drd/drd_segment.c b/exp-drd/drd_segment.c index 1bb186efad..3fbed86d06 100644 --- a/exp-drd/drd_segment.c +++ b/exp-drd/drd_segment.c @@ -188,6 +188,32 @@ void sg_put(Segment* const sg) } } +/** Merge sg1 and sg2 into sg1. */ +void sg_merge(const Segment* const sg1, Segment* const sg2) +{ + tl_assert(sg1); + tl_assert(sg2); + + if (drd_trace_segment) + { + char msg[256]; + + VG_(snprintf)(msg, sizeof(msg), "Merging segments with vector clocks "); + vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), + &sg1->vc); + VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), + " and "); + vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), + &sg2->vc); + VG_(message)(Vg_UserMsg, "%s", msg); + } + + // Keep sg1->stacktrace. + // Keep sg1->vc. + // Merge sg2->bm into sg1->bm. + bm_merge2(sg1->bm, sg2->bm); +} + void sg_print(const Segment* const sg) { tl_assert(sg); diff --git a/exp-drd/drd_segment.h b/exp-drd/drd_segment.h index e7eeeebad0..487dc2293f 100644 --- a/exp-drd/drd_segment.h +++ b/exp-drd/drd_segment.h @@ -53,6 +53,7 @@ Segment* sg_new(const ThreadId creator, const ThreadId created); int sg_get_refcnt(const Segment* const sg); Segment* sg_get(Segment* const sg); void sg_put(Segment* const sg); +void sg_merge(const Segment* const sg1, Segment* const sg2); void sg_print(const Segment* const sg); Bool sg_get_trace(void); void sg_set_trace(const Bool trace_segment); diff --git a/exp-drd/drd_thread.c b/exp-drd/drd_thread.c index fe68c45e98..62eb0f35a8 100644 --- a/exp-drd/drd_thread.c +++ b/exp-drd/drd_thread.c @@ -59,6 +59,7 @@ ThreadInfo s_threadinfo[DRD_N_THREADS]; struct bitmap* s_danger_set; static Bool s_trace_context_switches = False; static Bool s_trace_danger_set = False; +static Bool s_segment_merging = True; // Function definitions. @@ -73,6 +74,11 @@ void thread_trace_danger_set(const Bool t) s_trace_danger_set = t; } +void thread_set_segment_merging(const Bool m) +{ + s_segment_merging = m; +} + __inline__ Bool IsValidDrdThreadId(const DrdThreadId tid) { return (0 <= tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID @@ -538,6 +544,41 @@ static void thread_discard_ordered_segments(void) vc_cleanup(&thread_vc_min); } +/** Merge all segments that may be merged without triggering false positives + * or discarding real data races. For the theoretical background of segment + * merging, see also the following paper: + * Mark Christiaens, Michiel Ronsse and Koen De Bosschere. + * Bounding the number of segment histories during data race detection. + * Parallel Computing archive, Volume 28, Issue 9, pp 1221-1238, + * September 2002. + */ +static void thread_merge_segments(void) +{ + unsigned i; + + for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++) + { + Segment* sg; + + tl_assert(sane_ThreadInfo(&s_threadinfo[i])); + + for (sg = s_threadinfo[i].first; sg; sg = sg->next) + { + if (sg_get_refcnt(sg) == 1 + && sg->next + && sg_get_refcnt(sg->next) == 1 + && sg->next->next) + { + /* Merge sg and sg->next into sg. */ + sg_merge(sg, sg->next); + thread_discard_segment(i, sg->next); + } + } + + tl_assert(sane_ThreadInfo(&s_threadinfo[i])); + } +} + /** Create a new segment for the specified thread, and discard any segments * that cannot cause races anymore. */ @@ -549,6 +590,9 @@ void thread_new_segment(const DrdThreadId tid) thread_discard_ordered_segments(); + if (s_segment_merging) + thread_merge_segments(); + if (tid == s_drd_running_tid) { /* Every change in the vector clock of the current thread may cause */ diff --git a/exp-drd/drd_thread.h b/exp-drd/drd_thread.h index 66aa6370e1..bbfbbd8296 100644 --- a/exp-drd/drd_thread.h +++ b/exp-drd/drd_thread.h @@ -89,6 +89,7 @@ extern struct bitmap* s_danger_set; void thread_trace_context_switches(const Bool t); void thread_trace_danger_set(const Bool t); +void thread_set_segment_merging(const Bool m); Bool IsValidDrdThreadId(const DrdThreadId tid); DrdThreadId VgThreadIdToDrdThreadId(const ThreadId tid);