From 3aa5cfa0d1cdbbd839884302535da28ca8c8b00d Mon Sep 17 00:00:00 2001 From: Antoine Tremblay Date: Wed, 31 Aug 2016 13:46:22 -0400 Subject: [PATCH] Fix lwp_suspend/unsuspend imbalance in linux_wait_1 This patch fixes imbalanced lwp_suspend/unsuspend calls caused by the premature choosing of another event for fairness. select_event_lwp would switch the event before a call to unsuspend_all_lwps, thus it would be called with the wrong event. This caused an assertion failure: unsuspend LWP xx, suspended=-1 when testing gdb.threads/non-stop-fair-events.exp with ARM range stepping in GDBServer. This patch moves the switch of event after the unsuspend/unstop calls. No regressions, tested on ubuntu 14.04 ARMv7 and x86. With gdbserver-native. gdb/gdbserver/ChangeLog: * linux-low.c (linux_wait_1): Move event switch after unsuspend_lwps. --- gdb/gdbserver/ChangeLog | 4 ++++ gdb/gdbserver/linux-low.c | 37 +++++++++++++++++++------------------ 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index af0140f0ed..4dc2e451ea 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,7 @@ +2016-08-31 Antoine Tremblay + + * linux-low.c (linux_wait_1): Move event switch after unsuspend_lwps. + 2016-08-25 Adhemerval Zanella PR server/20491 diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index 45061ac256..cdff436cff 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -3771,24 +3771,6 @@ linux_wait_1 (ptid_t ptid, if (!non_stop) stop_all_lwps (0, NULL); - /* If we're not waiting for a specific LWP, choose an event LWP - from among those that have had events. Giving equal priority - to all LWPs that have had events helps prevent - starvation. */ - if (ptid_equal (ptid, minus_one_ptid)) - { - event_child->status_pending_p = 1; - event_child->status_pending = w; - - select_event_lwp (&event_child); - - /* current_thread and event_child must stay in sync. */ - current_thread = get_lwp_thread (event_child); - - event_child->status_pending_p = 0; - w = event_child->status_pending; - } - if (step_over_finished) { if (!non_stop) @@ -3813,6 +3795,25 @@ linux_wait_1 (ptid_t ptid, } } + /* If we're not waiting for a specific LWP, choose an event LWP + from among those that have had events. Giving equal priority + to all LWPs that have had events helps prevent + starvation. */ + if (ptid_equal (ptid, minus_one_ptid)) + { + event_child->status_pending_p = 1; + event_child->status_pending = w; + + select_event_lwp (&event_child); + + /* current_thread and event_child must stay in sync. */ + current_thread = get_lwp_thread (event_child); + + event_child->status_pending_p = 0; + w = event_child->status_pending; + } + + /* Stabilize threads (move out of jump pads). */ if (!non_stop) stabilize_threads (); -- 2.34.1