@@ -58,7 +58,7 @@ Thread: 'Thread 1'
| NN | acquire_lock_b ();
| | ^~~~~~~~~~~~~~~~~
| | |
- | | (5) deadlocked due to waiting for lock b in thread 1...
+ | | (5) deadlocked due to waiting for lock b in thread 1 (acquired by thread 2 at (4))...
|
Thread: 'Thread 2'
@@ -67,6 +67,6 @@ Thread: 'Thread 2'
| NN | acquire_lock_a ();
| | ^~~~~~~~~~~~~~~~~
| | |
- | | (6) ...whilst waiting for lock a in thread 2
+ | | (6) ...whilst waiting for lock a in thread 2 (acquired by thread 1 at (2))
|
{ dg-end-multiline-output "" } */
@@ -95,7 +95,7 @@ def test_result(sarif):
== "lock a is now held by thread 1"
assert tf0['locations'][2]['executionOrder'] == 5
assert tf0['locations'][2]['location']['message']['text'] \
- == "deadlocked due to waiting for lock b in thread 1..."
+ == "deadlocked due to waiting for lock b in thread 1 (acquired by thread 2 at (4))..."
assert len(tf1['locations']) == 3
assert tf1['locations'][0]['executionOrder'] == 3
@@ -106,4 +106,4 @@ def test_result(sarif):
== "lock b is now held by thread 2"
assert tf1['locations'][2]['executionOrder'] == 6
assert tf1['locations'][2]['location']['message']['text'] \
- == "...whilst waiting for lock a in thread 2"
+ == "...whilst waiting for lock a in thread 2 (acquired by thread 1 at (2))"
@@ -7,12 +7,12 @@ extern void acquire_lock_b(void);
void foo ()
{ /* { dg-message "\\(1\\) entering 'foo'" } */
acquire_lock_a (); /* { dg-message "\\(2\\) lock a is now held by thread 1" } */
- acquire_lock_b (); /* { dg-message "\\(5\\) deadlocked due to waiting for lock b in thread 1\.\.\." } */
+ acquire_lock_b (); /* { dg-message "\\(5\\) deadlocked due to waiting for lock b in thread 1 \\(acquired by thread 2 at \\(4\\)\\)\.\.\." } */
}
void bar ()
{ /* { dg-message "\\(3\\) entering 'bar'" } */
acquire_lock_b (); /* { dg-message "\\(4\\) lock b is now held by thread 2" } */
acquire_lock_a (); /* { dg-warning "deadlock due to inconsistent lock acquisition order" } */
- /* { dg-message "\\(6\\) \.\.\.whilst waiting for lock a in thread 2" "" { target *-*-* } .-1 } */
+ /* { dg-message "\\(6\\) \.\.\.whilst waiting for lock a in thread 2 \\(acquired by thread 1 at \\(2\\)\\)" "" { target *-*-* } .-1 } */
}
@@ -217,14 +217,26 @@ class test_diagnostic_path : public simple_diagnostic_path
: simple_diagnostic_path (event_pp)
{
}
- void add_event_2 (event_location_t evloc, int stack_depth,
- const char *desc,
- diagnostic_thread_id_t thread_id = 0)
+ diagnostic_event_id_t
+ add_event_2 (event_location_t evloc, int stack_depth,
+ const char *desc,
+ diagnostic_thread_id_t thread_id = 0)
{
gcc_assert (evloc.m_fun);
- add_thread_event (thread_id, evloc.m_loc, evloc.m_fun->decl,
+ return add_thread_event (thread_id, evloc.m_loc, evloc.m_fun->decl,
stack_depth, desc);
}
+ diagnostic_event_id_t
+ add_event_2_with_event_id (event_location_t evloc, int stack_depth,
+ const char *fmt,
+ diagnostic_thread_id_t thread_id,
+ diagnostic_event_id_t event_id)
+ {
+ gcc_assert (evloc.m_fun);
+ // FMT is assumed to have a single %@ argument
+ return add_thread_event (thread_id, evloc.m_loc, evloc.m_fun->decl,
+ stack_depth, fmt, &event_id);
+ }
void add_entry (event_location_t evloc, int stack_depth,
const char *funcname,
diagnostic_thread_id_t thread_id = 0)
@@ -487,17 +499,23 @@ example_4 ()
diagnostic_thread_id_t thread_1 = path.add_thread ("Thread 1");
diagnostic_thread_id_t thread_2 = path.add_thread ("Thread 2");
path.add_entry (entry_to_foo, 0, "foo", thread_1);
- path.add_event_2 (call_to_acquire_lock_a_in_foo, 1,
- "lock a is now held by thread 1", thread_1);
+ diagnostic_event_id_t event_a_acquired
+ = path.add_event_2 (call_to_acquire_lock_a_in_foo, 1,
+ "lock a is now held by thread 1", thread_1);
path.add_entry (entry_to_bar, 0, "bar", thread_2);
- path.add_event_2 (call_to_acquire_lock_b_in_bar, 1,
- "lock b is now held by thread 2", thread_2);
- path.add_event_2 (call_to_acquire_lock_b_in_foo, 1,
- "deadlocked due to waiting for lock b in thread 1...",
- thread_1);
- path.add_event_2 (call_to_acquire_lock_a_in_bar, 1,
- "...whilst waiting for lock a in thread 2",
- thread_2);
+ diagnostic_event_id_t event_b_acquired
+ = path.add_event_2 (call_to_acquire_lock_b_in_bar, 1,
+ "lock b is now held by thread 2", thread_2);
+ path.add_event_2_with_event_id
+ (call_to_acquire_lock_b_in_foo, 1,
+ "deadlocked due to waiting for lock b in thread 1"
+ " (acquired by thread 2 at %@)...",
+ thread_1, event_b_acquired);
+ path.add_event_2_with_event_id
+ (call_to_acquire_lock_a_in_bar, 1,
+ "...whilst waiting for lock a in thread 2"
+ " (acquired by thread 1 at %@)",
+ thread_2, event_a_acquired);
richloc.set_path (&path);
diagnostic_metadata m;
Add test coverage of "%@" in event messages in a multithreaded execution path. Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. Pushed to trunk as r15-3199-g6a1c359e28442c. gcc/testsuite/ChangeLog: * gcc.dg/plugin/diagnostic-test-paths-multithreaded-inline-events.c: Update expected output. * gcc.dg/plugin/diagnostic-test-paths-multithreaded-sarif.py: Likewise. * gcc.dg/plugin/diagnostic-test-paths-multithreaded-separate-events.c: Likewise. * gcc.dg/plugin/diagnostic_plugin_test_paths.c (test_diagnostic_path::add_event_2): Return the id of the added event. (test_diagnostic_path::add_event_2_with_event_id): New. (example_4): Add event IDs to the deadlock messages indicating where the locks where acquired. Signed-off-by: David Malcolm <dmalcolm@redhat.com> --- ...c-test-paths-multithreaded-inline-events.c | 4 +- ...agnostic-test-paths-multithreaded-sarif.py | 4 +- ...test-paths-multithreaded-separate-events.c | 4 +- .../plugin/diagnostic_plugin_test_paths.c | 46 +++++++++++++------ 4 files changed, 38 insertions(+), 20 deletions(-)