From 916c8dfde6a4ee5b86af4d4db882c05c6bb08e9b Mon Sep 17 00:00:00 2001 From: Bjoern Brandenburg Date: Fri, 11 Jan 2013 11:00:30 +0100 Subject: Add tests for PCP/SRP ceiling blocking Context: priority inheritance triggered a BUG_ON() in fp_common.c. While at it, add a similar test for the SRP. --- tests/pcp.c | 208 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) (limited to 'tests') diff --git a/tests/pcp.c b/tests/pcp.c index 88d1be3..52ee959 100644 --- a/tests/pcp.c +++ b/tests/pcp.c @@ -1,6 +1,8 @@ #include #include #include +#include /* for waitpid() */ + #include "tests.h" #include "litmus.h" @@ -37,6 +39,212 @@ TESTCASE(lock_pcp, P_FP, SYSCALL( remove(".pcp_locks") ); } +TESTCASE(pcp_inheritance, P_FP, + "PCP priority inheritance") +{ + int fd, od, cpu = 0; + + int child_hi, child_lo, child_middle, status, waiters; + lt_t delay = ms2lt(100); + double start, stop; + + struct rt_task params; + params.cpu = 0; + params.exec_cost = ms2lt(10000); + params.period = ms2lt(100000); + params.relative_deadline = params.period; + params.phase = 0; + params.cls = RT_CLASS_HARD; + params.budget_policy = NO_ENFORCEMENT; + + SYSCALL( fd = open(".pcp_locks", O_RDONLY | O_CREAT) ); + + + child_lo = FORK_TASK( + params.priority = LITMUS_LOWEST_PRIORITY; + params.phase = 0; + SYSCALL( set_rt_task_param(gettid(), ¶ms) ); + SYSCALL( be_migrate_to(params.cpu) ); + SYSCALL( task_mode(LITMUS_RT_TASK) ); + + SYSCALL( od = open_pcp_sem(fd, 0, cpu) ); + + SYSCALL( wait_for_ts_release() ); + + SYSCALL( litmus_lock(od) ); + start = cputime(); + while (cputime() - start < 0.25) + ; + SYSCALL( litmus_unlock(od) ); + + SYSCALL(sleep_next_period() ); + ); + + child_middle = FORK_TASK( + params.priority = LITMUS_HIGHEST_PRIORITY + 1; + params.phase = ms2lt(100); + + SYSCALL( set_rt_task_param(gettid(), ¶ms) ); + SYSCALL( be_migrate_to(params.cpu) ); + SYSCALL( task_mode(LITMUS_RT_TASK) ); + + + SYSCALL( wait_for_ts_release() ); + + start = cputime(); + while (cputime() - start < 5) + ; + SYSCALL( sleep_next_period() ); + ); + + child_hi = FORK_TASK( + params.priority = LITMUS_HIGHEST_PRIORITY; + params.phase = ms2lt(50); + + SYSCALL( set_rt_task_param(gettid(), ¶ms) ); + SYSCALL( be_migrate_to(params.cpu) ); + SYSCALL( task_mode(LITMUS_RT_TASK) ); + + SYSCALL( od = open_pcp_sem(fd, 0, cpu) ); + + SYSCALL( wait_for_ts_release() ); + + start = wctime(); + /* block on semaphore */ + SYSCALL( litmus_lock(od) ); + SYSCALL( litmus_unlock(od) ); + stop = wctime(); + + /* Assert we had some blocking. */ + ASSERT( stop - start > 0.1); + + /* Assert we woke up 'soonish' after the sleep. */ + ASSERT( stop - start < 1 ); + + SYSCALL( kill(child_middle, SIGUSR2) ); + SYSCALL( kill(child_lo, SIGUSR2) ); + ); + + do { + waiters = get_nr_ts_release_waiters(); + ASSERT( waiters >= 0 ); + } while (waiters != 3); + + SYSCALL( be_migrate_to(1) ); + + waiters = release_ts(&delay); + + SYSCALL( waitpid(child_hi, &status, 0) ); + ASSERT( status == 0 ); + + SYSCALL( waitpid(child_lo, &status, 0) ); + ASSERT( status == SIGUSR2); + + SYSCALL( waitpid(child_middle, &status, 0) ); + ASSERT( status == SIGUSR2); +} + +TESTCASE(srp_ceiling_blocking, P_FP | PSN_EDF, + "SRP ceiling blocking") +{ + int fd, od; + + int child_hi, child_lo, child_middle, status, waiters; + lt_t delay = ms2lt(100); + double start, stop; + + struct rt_task params; + params.cpu = 0; + params.exec_cost = ms2lt(10000); + params.period = ms2lt(100000); + params.relative_deadline = params.period; + params.phase = 0; + params.cls = RT_CLASS_HARD; + params.budget_policy = NO_ENFORCEMENT; + + SYSCALL( fd = open(".srp_locks", O_RDONLY | O_CREAT) ); + + + child_lo = FORK_TASK( + params.priority = LITMUS_LOWEST_PRIORITY; + params.phase = 0; + SYSCALL( set_rt_task_param(gettid(), ¶ms) ); + SYSCALL( be_migrate_to(params.cpu) ); + SYSCALL( task_mode(LITMUS_RT_TASK) ); + + SYSCALL( od = open_srp_sem(fd, 0) ); + + SYSCALL( wait_for_ts_release() ); + + SYSCALL( litmus_lock(od) ); + start = cputime(); + while (cputime() - start < 0.25) + ; + SYSCALL( litmus_unlock(od) ); + ); + + child_middle = FORK_TASK( + params.priority = LITMUS_HIGHEST_PRIORITY + 1; + params.phase = ms2lt(100); + params.relative_deadline -= ms2lt(110); + + SYSCALL( set_rt_task_param(gettid(), ¶ms) ); + SYSCALL( be_migrate_to(params.cpu) ); + SYSCALL( task_mode(LITMUS_RT_TASK) ); + + + SYSCALL( wait_for_ts_release() ); + + start = cputime(); + while (cputime() - start < 5) + ; + ); + + child_hi = FORK_TASK( + params.priority = LITMUS_HIGHEST_PRIORITY; + params.phase = ms2lt(50); + params.relative_deadline -= ms2lt(200); + + SYSCALL( set_rt_task_param(gettid(), ¶ms) ); + SYSCALL( be_migrate_to(params.cpu) ); + SYSCALL( task_mode(LITMUS_RT_TASK) ); + + SYSCALL( od = open_srp_sem(fd, 0) ); + + SYSCALL( wait_for_ts_release() ); + + start = wctime(); + /* block on semaphore */ + SYSCALL( litmus_lock(od) ); + SYSCALL( litmus_unlock(od) ); + stop = wctime(); + + /* Assert we had "no" blocking (modulo qemu overheads). */ + ASSERT( stop - start < 0.01); + + SYSCALL( kill(child_middle, SIGUSR2) ); + SYSCALL( kill(child_lo, SIGUSR2) ); + ); + + do { + waiters = get_nr_ts_release_waiters(); + ASSERT( waiters >= 0 ); + } while (waiters != 3); + + SYSCALL( be_migrate_to(1) ); + + waiters = release_ts(&delay); + + SYSCALL( waitpid(child_hi, &status, 0) ); + ASSERT( status == 0 ); + + SYSCALL( waitpid(child_lo, &status, 0) ); + ASSERT( status == SIGUSR2); + + SYSCALL( waitpid(child_middle, &status, 0) ); + ASSERT( status == SIGUSR2); +} + TESTCASE(lock_dpcp, P_FP, "DPCP acquisition and release") { -- cgit v1.2.2