diff --git a/src/test/seekticks_threads.c b/src/test/seekticks_threads.c new file mode 100644 index 00000000000..95d3fd9fe25 --- /dev/null +++ b/src/test/seekticks_threads.c @@ -0,0 +1,28 @@ +/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ + +#include "util.h" + +// Run two threads until there have been at least a couple +// (approx. 20) context switches between them. +volatile int counter; +static void* start_thread(__attribute__((unused)) void* p) { + while (1) { + int c = counter; + if ((c&1) == 1) counter = c+1; + } + + return NULL; +} + +int main(void) { + pthread_t thread; + pthread_create(&thread, NULL, start_thread, NULL); + + while (1) { + int c = counter; + if ((c&1) == 0) counter = c+1; + if (counter >= 20) break; + } + + return 0; +} diff --git a/src/test/seekticks_threads.py b/src/test/seekticks_threads.py new file mode 100644 index 00000000000..bd556a99bc8 --- /dev/null +++ b/src/test/seekticks_threads.py @@ -0,0 +1,81 @@ +from util import * +import re, os + +def curr_thread(): + send_gdb('thread') + expect_gdb(re.compile(r'\[Current thread is \d+ \(Thread (.*?)\)\]')) + return last_match().group(1); + +def expect_thread_tick(expected_thread, expected_tick): + if curr_thread() != expected_thread: + failed('Incorrect thread: expected %s, got %s' % (expected_thread, curr_thread())) + + send_gdb('when-ticks') + expect_gdb(re.compile(r'Current tick: (\d+)')) + got_tick = int(last_match().group(1)); + if expected_tick != got_tick: + failed('Incorrect ticks: expected %d, got %d' % (expected_tick, got_tick)) + +def expect_stopped(): + expect_gdb(re.compile(r'(Thread \d+|Program) stopped')) + + + +sched_matches = re.compile(r'global_time:(\d+).*ticks:(\d+)').findall(os.environ['SCHED_EVENTS']) +sched_events = [[int(y) for y in x] for x in sched_matches][:-2] +while True: + if (len(sched_events) < 4): + failed('Adjacent SCHED events not found') + last = sched_events[-4:] + if all([last[0][0]+i == last[i][0] for i in range(4)]): + break + sched_events.pop() + +sched_events = sched_events[-4:] + +[event_A, tick_A] = sched_events[0] +[event_B, tick_B] = sched_events[1] +[event_C, tick_C] = sched_events[2] +[event_D, tick_D] = sched_events[3] + +threads = set() +for [start_event, t1, t2] in [[event_B, tick_A, tick_C], [event_A, tick_B, tick_D]]: + center_tick = (t1 + t2) // 2 + send_gdb('run %d' % start_event) + expect_gdb('from the beginning') + send_gdb('y') + expect_stopped(); + + thread = curr_thread() + threads.add(thread) + + send_gdb('seek-ticks %d' % center_tick) + expect_stopped(); + expect_thread_tick(thread, center_tick) + + send_gdb('seek-ticks %d' % center_tick) + expect_stopped(); + expect_thread_tick(thread, center_tick) + + ticks = center_tick + 1 + send_gdb('seek-ticks %d' % ticks) + expect_stopped(); + expect_thread_tick(thread, ticks) + + ticks = center_tick - 1 + send_gdb('seek-ticks %d' % ticks) + expect_stopped(); + expect_thread_tick(thread, ticks) + + send_gdb('seek-ticks %d' % t1) + expect_stopped(); + expect_thread_tick(thread, t1) + + send_gdb('seek-ticks %d' % t2) + expect_stopped(); + expect_thread_tick(thread, t2) + +if len(threads) != 2: + failed('Tested events had the same thread') + +ok() diff --git a/src/test/seekticks_threads.run b/src/test/seekticks_threads.run new file mode 100644 index 00000000000..a23e5322a53 --- /dev/null +++ b/src/test/seekticks_threads.run @@ -0,0 +1,4 @@ +source `dirname $0`/util.sh +record seekticks_threads$bitness +SCHED_EVENTS="$(get_events | grep \`SCHED\')" \ +debug seekticks_threads diff --git a/src/test/util.sh b/src/test/util.sh index 487ec79a3f8..372807e1c8b 100644 --- a/src/test/util.sh +++ b/src/test/util.sh @@ -488,9 +488,14 @@ function rerun_singlestep_test { rerun "--singlestep=rip,gp_x16,flags" } +# Return an rr dump result of the most recent local recording. +function get_events { + $RR_EXE $GLOBAL_OPTIONS dump "$@" latest-trace +} + # Return the number of events in the most recent local recording. function count_events { - local events=$($RR_EXE $GLOBAL_OPTIONS dump -r latest-trace | wc -l) + local events=$(get_events -r | wc -l) # The |simple| test is just about the simplest possible C program, # and has around 180 events (when recorded on a particular # developer's machine). If we count a number of events