Skip to content

Commit

Permalink
Tests for seek-ticks around threads
Browse files Browse the repository at this point in the history
  • Loading branch information
dzaima committed Nov 8, 2023
1 parent 44e5338 commit 135a049
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 1 deletion.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1515,6 +1515,7 @@ set(TESTS_WITH_PROGRAM
seccomp_blocks_rr
seccomp_open
seccomp_signals
seekticks_threads
segfault
setuid
shared_map
Expand Down
28 changes: 28 additions & 0 deletions src/test/seekticks_threads.c
Original file line number Diff line number Diff line change
@@ -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;
}
81 changes: 81 additions & 0 deletions src/test/seekticks_threads.py
Original file line number Diff line number Diff line change
@@ -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()
4 changes: 4 additions & 0 deletions src/test/seekticks_threads.run
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source `dirname $0`/util.sh
record seekticks_threads$bitness
SCHED_EVENTS="$(get_events | grep \`SCHED\')" \
debug seekticks_threads
7 changes: 6 additions & 1 deletion src/test/util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 135a049

Please sign in to comment.