From f57b0c5d4f284ebeda5e31544f746aa9dade065d Mon Sep 17 00:00:00 2001 From: Ken Sato Date: Wed, 29 Aug 2018 14:30:32 +0900 Subject: [PATCH] wait: Delay wake-up parent within switch context Fujitsu: POSTK_DEBUG_TEMP_FIX_41 Refs: #1006 Change-Id: Ia98e896505ad0f6549766604ade84550eee8bd2d --- arch/arm64/kernel/cpu.c | 6 +- arch/arm64/kernel/ptrace.c | 8 --- arch/arm64/kernel/syscall.c | 18 ------ arch/x86_64/kernel/cpu.c | 23 ++++++++ arch/x86_64/kernel/syscall.c | 14 +---- kernel/include/process.h | 2 - test/issues/1006/C1006.sh | 106 +++++++++++++++++++++++++++++++++++ test/issues/1006/Makefile | 14 +++++ test/issues/1006/README | 37 ++++++++++++ test/issues/1006/result.log | 95 +++++++++++++++++++++++++++++++ 10 files changed, 280 insertions(+), 43 deletions(-) create mode 100644 test/issues/1006/C1006.sh create mode 100644 test/issues/1006/Makefile create mode 100644 test/issues/1006/README create mode 100644 test/issues/1006/result.log diff --git a/arch/arm64/kernel/cpu.c b/arch/arm64/kernel/cpu.c index 6701c7f1..644b24aa 100644 --- a/arch/arm64/kernel/cpu.c +++ b/arch/arm64/kernel/cpu.c @@ -1306,9 +1306,7 @@ struct thread *arch_switch_context(struct thread *prev, struct thread *next) extern void perf_start(struct mc_perf_event *event); extern void perf_reset(struct mc_perf_event *event); struct thread *last; -#ifdef POSTK_DEBUG_TEMP_FIX_41 /* early to wait4() wakeup for ptrace, fix. */ struct mcs_rwlock_node_irqsave lock; -#endif /* POSTK_DEBUG_TEMP_FIX_41 */ /* Set up new TLS.. */ dkprintf("[%d] arch_switch_context: tlsblock_base: 0x%lX\n", @@ -1328,7 +1326,6 @@ struct thread *arch_switch_context(struct thread *prev, struct thread *next) if (likely(prev)) { tls_thread_switch(prev, next); -#ifdef POSTK_DEBUG_TEMP_FIX_41 /* early to wait4() wakeup for ptrace, fix. */ mcs_rwlock_writer_lock(&prev->proc->update_lock, &lock); if (prev->proc->status & (PS_DELAY_STOPPED | PS_DELAY_TRACED)) { switch (prev->proc->status) { @@ -1342,11 +1339,12 @@ struct thread *arch_switch_context(struct thread *prev, struct thread *next) break; } mcs_rwlock_writer_unlock(&prev->proc->update_lock, &lock); + + /* Wake up the parent who tried wait4 and sleeping */ waitq_wakeup(&prev->proc->parent->waitpid_q); } else { mcs_rwlock_writer_unlock(&prev->proc->update_lock, &lock); } -#endif /* POSTK_DEBUG_TEMP_FIX_41 */ last = ihk_mc_switch_context(&prev->ctx, &next->ctx, prev); } diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index f6572a0e..84b91dd1 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -957,11 +957,7 @@ void ptrace_report_signal(struct thread *thread, int sig) } thread->exit_status = sig; /* Transition thread state */ -#ifdef POSTK_DEBUG_TEMP_FIX_41 /* early to wait4() wakeup for ptrace, fix. */ proc->status = PS_DELAY_TRACED; -#else /* POSTK_DEBUG_TEMP_FIX_41 */ - proc->status = PS_TRACED; -#endif /* POSTK_DEBUG_TEMP_FIX_41 */ thread->status = PS_TRACED; proc->ptrace &= ~PT_TRACE_SYSCALL; if (sig == SIGSTOP || sig == SIGTSTP || @@ -980,10 +976,6 @@ void ptrace_report_signal(struct thread *thread, int sig) info._sifields._sigchld.si_pid = thread->tid; info._sifields._sigchld.si_status = thread->exit_status; do_kill(cpu_local_var(current), parent_pid, -1, SIGCHLD, &info, 0); -#ifndef POSTK_DEBUG_TEMP_FIX_41 /* early to wait4() wakeup for ptrace, fix. */ - /* Wake parent (if sleeping in wait4()) */ - waitq_wakeup(&proc->parent->waitpid_q); -#endif /* !POSTK_DEBUG_TEMP_FIX_41 */ dkprintf("ptrace_report_signal,sleeping\n"); /* Sleep */ diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c index b090ed5c..1185ebf6 100644 --- a/arch/arm64/kernel/syscall.c +++ b/arch/arm64/kernel/syscall.c @@ -1176,19 +1176,10 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi /* Reap and set new signal_flags */ proc->signal_flags = SIGNAL_STOP_STOPPED; -#ifdef POSTK_DEBUG_TEMP_FIX_41 /* early to wait4() wakeup for ptrace, fix. */ proc->status = PS_DELAY_STOPPED; -#else /* POSTK_DEBUG_TEMP_FIX_41 */ - proc->status = PS_STOPPED; -#endif /* POSTK_DEBUG_TEMP_FIX_41 */ thread->status = PS_STOPPED; mcs_rwlock_writer_unlock(&proc->update_lock, &lock); -#ifndef POSTK_DEBUG_TEMP_FIX_41 /* early to wait4() wakeup for ptrace, fix. */ - /* Wake up the parent who tried wait4 and sleeping */ - waitq_wakeup(&proc->parent->waitpid_q); -#endif /* !POSTK_DEBUG_TEMP_FIX_41 */ - dkprintf("do_signal(): pid: %d, tid: %d SIGSTOP, sleeping\n", proc->pid, thread->tid); /* Sleep */ @@ -1205,19 +1196,10 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi /* Update thread state in fork tree */ mcs_rwlock_writer_lock(&proc->update_lock, &lock); thread->exit_status = SIGTRAP; -#ifdef POSTK_DEBUG_TEMP_FIX_41 /* early to wait4() wakeup for ptrace, fix. */ proc->status = PS_DELAY_TRACED; -#else /* POSTK_DEBUG_TEMP_FIX_41 */ - proc->status = PS_TRACED; -#endif /* POSTK_DEBUG_TEMP_FIX_41 */ thread->status = PS_TRACED; mcs_rwlock_writer_unlock(&proc->update_lock, &lock); -#ifndef POSTK_DEBUG_TEMP_FIX_41 /* early to wait4() wakeup for ptrace, fix. */ - /* Wake up the parent who tried wait4 and sleeping */ - waitq_wakeup(&thread->proc->parent->waitpid_q); -#endif /* !POSTK_DEBUG_TEMP_FIX_41 */ - /* Sleep */ dkprintf("do_signal,SIGTRAP,sleeping\n"); diff --git a/arch/x86_64/kernel/cpu.c b/arch/x86_64/kernel/cpu.c index 3570903e..a283ad99 100644 --- a/arch/x86_64/kernel/cpu.c +++ b/arch/x86_64/kernel/cpu.c @@ -1647,6 +1647,7 @@ int ihk_mc_interrupt_cpu(int cpu, int vector) struct thread *arch_switch_context(struct thread *prev, struct thread *next) { struct thread *last; + struct mcs_rwlock_node_irqsave lock; dkprintf("[%d] schedule: tlsblock_base: 0x%lX\n", ihk_mc_get_processor_id(), next->tlsblock_base); @@ -1677,6 +1678,28 @@ struct thread *arch_switch_context(struct thread *prev, struct thread *next) #endif if (prev) { + mcs_rwlock_writer_lock(&prev->proc->update_lock, &lock); + if (prev->proc->status & (PS_DELAY_STOPPED | PS_DELAY_TRACED)) { + switch (prev->proc->status) { + case PS_DELAY_STOPPED: + prev->proc->status = PS_STOPPED; + break; + case PS_DELAY_TRACED: + prev->proc->status = PS_TRACED; + break; + default: + break; + } + mcs_rwlock_writer_unlock(&prev->proc->update_lock, + &lock); + + /* Wake up the parent who tried wait4 and sleeping */ + waitq_wakeup(&prev->proc->parent->waitpid_q); + } else { + mcs_rwlock_writer_unlock(&prev->proc->update_lock, + &lock); + } + last = ihk_mc_switch_context(&prev->ctx, &next->ctx, prev); } else { diff --git a/arch/x86_64/kernel/syscall.c b/arch/x86_64/kernel/syscall.c index 2a5af272..0d60b120 100644 --- a/arch/x86_64/kernel/syscall.c +++ b/arch/x86_64/kernel/syscall.c @@ -534,7 +534,7 @@ void ptrace_report_signal(struct thread *thread, int sig) } thread->exit_status = sig; /* Transition thread state */ - proc->status = PS_TRACED; + proc->status = PS_DELAY_TRACED; thread->status = PS_TRACED; proc->ptrace &= ~PT_TRACE_SYSCALL; if (sig == SIGSTOP || sig == SIGTSTP || @@ -553,8 +553,6 @@ void ptrace_report_signal(struct thread *thread, int sig) info._sifields._sigchld.si_pid = thread->tid; info._sifields._sigchld.si_status = thread->exit_status; do_kill(cpu_local_var(current), parent_pid, -1, SIGCHLD, &info, 0); - /* Wake parent (if sleeping in wait4()) */ - waitq_wakeup(&proc->parent->waitpid_q); dkprintf("ptrace_report_signal,sleeping\n"); /* Sleep */ @@ -864,13 +862,10 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi /* Reap and set new signal_flags */ proc->signal_flags = SIGNAL_STOP_STOPPED; - proc->status = PS_STOPPED; + proc->status = PS_DELAY_STOPPED; thread->status = PS_STOPPED; mcs_rwlock_writer_unlock(&proc->update_lock, &lock); - /* Wake up the parent who tried wait4 and sleeping */ - waitq_wakeup(&proc->parent->waitpid_q); - dkprintf("do_signal(): pid: %d, tid: %d SIGSTOP, sleeping\n", proc->pid, thread->tid); /* Sleep */ @@ -887,13 +882,10 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi /* Update thread state in fork tree */ mcs_rwlock_writer_lock(&proc->update_lock, &lock); thread->exit_status = SIGTRAP; - proc->status = PS_TRACED; + proc->status = PS_DELAY_TRACED; thread->status = PS_TRACED; mcs_rwlock_writer_unlock(&proc->update_lock, &lock); - /* Wake up the parent who tried wait4 and sleeping */ - waitq_wakeup(&thread->proc->parent->waitpid_q); - /* Sleep */ dkprintf("do_signal,SIGTRAP,sleeping\n"); diff --git a/kernel/include/process.h b/kernel/include/process.h index ebc18219..1c25c86f 100644 --- a/kernel/include/process.h +++ b/kernel/include/process.h @@ -70,10 +70,8 @@ #define PS_TRACED 0x40 /* Set to "not running" by a ptrace related event */ #define PS_STOPPING 0x80 #define PS_TRACING 0x100 -#ifdef POSTK_DEBUG_TEMP_FIX_41 /* early to wait4() wakeup for ptrace, fix. */ #define PS_DELAY_STOPPED 0x200 #define PS_DELAY_TRACED 0x400 -#endif /* POSTK_DEBUG_TEMP_FIX_41 */ #define PS_NORMAL (PS_INTERRUPTIBLE | PS_UNINTERRUPTIBLE) diff --git a/test/issues/1006/C1006.sh b/test/issues/1006/C1006.sh new file mode 100644 index 00000000..d0b4b375 --- /dev/null +++ b/test/issues/1006/C1006.sh @@ -0,0 +1,106 @@ +#!/bin/sh +if [ -f $HOME/mck_test_config ]; then + . $HOME/mck_test_config +else + BIN= + SBIN= + OSTEST= + LTP= +fi +BOOTPARAM="-c 1-7,9-15,17-23,25-31 -m 10G@0,10G@1 -r 1-7:0+9-15:8+17-23:16+25-31:24" + +if [ "x$BINDIR" = x ];then + BINDIR="$BIN" +fi + +if [ "x$SBINDIR" = x ];then + SBINDIR="$SBIN" +fi + +if [ "x$OSTESTDIR" = x ]; then + OSTESTDIR="$OSTEST" +fi + +if [ "x$LTPDIR" = x ]; then + LTPDIR="$LTP" +fi + +if [ ! -x $SBINDIR/mcstop+release.sh ]; then + echo mcstop+release: not found >&2 + exit 1 +fi +echo -n "mcstop+release.sh ... " +sudo $SBINDIR/mcstop+release.sh +echo "done" + +if [ ! -x $SBINDIR/mcreboot.sh ]; then + echo mcreboot: not found >&2 + exit 1 +fi +echo -n "mcreboot.sh $BOOTPARAM ... " +sudo $SBINDIR/mcreboot.sh $BOOTPARAM +echo "done" + +if [ ! -x $BINDIR/mcexec ]; then + echo mcexec: not found >&2 + exit 1 +fi + +tid=001 +echo "*** RT_$tid start *******************************" +sudo $BINDIR/mcexec $OSTESTDIR/bin/test_mck -s ptrace -n 8 2>&1 | tee ./RT_${tid}.txt +if grep "RESULT: ok" ./RT_${tid}.txt > /dev/null 2>&1 ; then + echo "*** RT_$tid: PASSED" +else + echo "*** RT_$tid: FAILED" +fi +echo "" + +tid=001 +echo "*** LT_$tid start *******************************" +sudo PATH=$LTPDIR/bin:${PATH} $BINDIR/mcexec $LTPDIR/bin/ptrace01 2>&1 | tee ./LT_${tid}.txt +ok=`grep TPASS LT_${tid}.txt | wc -l` +ng=`grep TFAIL LT_${tid}.txt | wc -l` +if [ $ng = 0 ]; then + echo "*** LT_$tid: PASSED (ok:$ok)" +else + echo "*** LT_$tid: FAILED (ok:$ok, ng:$ng)" +fi +echo "" + +tid=002 +echo "*** LT_$tid start *******************************" +sudo PATH=$LTPDIR/bin:${PATH} $BINDIR/mcexec $LTPDIR/bin/ptrace02 2>&1 | tee ./LT_${tid}.txt +ok=`grep TPASS LT_${tid}.txt | wc -l` +ng=`grep TFAIL LT_${tid}.txt | wc -l` +if [ $ng = 0 ]; then + echo "*** LT_$tid: PASSED (ok:$ok)" +else + echo "*** LT_$tid: FAILED (ok:$ok, ng:$ng)" +fi +echo "" + +tid=003 +echo "*** LT_$tid start *******************************" +sudo PATH=$LTPDIR/bin:${PATH} $BINDIR/mcexec $LTPDIR/bin/ptrace03 2>&1 | tee ./LT_${tid}.txt +ok=`grep TPASS LT_${tid}.txt | wc -l` +ng=`grep TFAIL LT_${tid}.txt | wc -l` +if [ $ng = 0 ]; then + echo "*** LT_$tid: PASSED (ok:$ok)" +else + echo "*** LT_$tid: FAILED (ok:$ok, ng:$ng)" +fi +echo "" + +tid=004 +echo "*** LT_$tid start *******************************" +sudo PATH=$LTPDIR/bin:${PATH} $BINDIR/mcexec $LTPDIR/bin/ptrace05 2>&1 | tee ./LT_${tid}.txt +ok=`grep TPASS LT_${tid}.txt | wc -l` +ng=`grep TFAIL LT_${tid}.txt | wc -l` +if [ $ng = 0 ]; then + echo "*** LT_$tid: PASSED (ok:$ok)" +else + echo "*** LT_$tid: FAILED (ok:$ok, ng:$ng)" +fi +echo "" + diff --git a/test/issues/1006/Makefile b/test/issues/1006/Makefile new file mode 100644 index 00000000..609d82b1 --- /dev/null +++ b/test/issues/1006/Makefile @@ -0,0 +1,14 @@ +CC = gcc +TARGET= + +CPPFLAGS = +LDFLAGS = + +all: $(TARGET) + +test: all + @sh ./C1006.sh + +clean: + rm -f $(TARGET) *.o + diff --git a/test/issues/1006/README b/test/issues/1006/README new file mode 100644 index 00000000..8c379263 --- /dev/null +++ b/test/issues/1006/README @@ -0,0 +1,37 @@ +【Issue#1006 動作確認】 +□ テスト内容 +1. Issueで報告された再現プログラムでの確認 +RT_001: ostest-ptrace.008 での確認 + wait()で待っている親プロセスを起動した直後の子プロセスから、 + ptrace(GETFPREGS)で正しい値が取得できることを確認 + +2. 既存のptrace機能に影響がないことをLTPを用いて確認 +LT_001: ltp-ptrace01 + PTRACE_TRACEME と PTRACE_KILL の動作を確認 (TPASS 2件) + +LT_002: ltp-ptrace02 + PTRACE_TRACEME と PTRACE_CONT の動作を確認 (TPASS 2件) + +LT_003: ltp-ptrace03 + ptrace()に不正なpidを指定した場合の動作を確認 (TCONF 1件、TPASS 2件) + +LT_004: ltp-ptrace05 + TRACE状態での各シグナル受信時の動作を確認 (TPASS 65件) + +□ 実行手順 +McKernelのインストール先や、OSTEST, LTPの配置場所は、 +$HOME/mck_test_config を参照している +mck_test_config は、McKernelをビルドした際に生成される +mck_test_config.sample ファイルを$HOMEにコピーし、適宜編集する + +$ make test + +実行できない場合は、C976.shの以下の行を適切に書き換えた後に実行。 +BIN= mcexec が存在するパス +SBIN= mcreboot.sh が存在するパス +OSTEST= OSTESTが存在するパス +LTP= LTPが存在するパス + +□ 実行結果 +result.log 参照。 +すべての項目をPASSしていることを確認。 diff --git a/test/issues/1006/result.log b/test/issues/1006/result.log new file mode 100644 index 00000000..a2c92f99 --- /dev/null +++ b/test/issues/1006/result.log @@ -0,0 +1,95 @@ +*** RT_001 start ******************************* +TEST_SUITE: ptrace +TEST_NUMBER: 8 +ARGS: +TEST_SUITE: ptrace +TEST_NUMBER: 8 +ARGS: +child's fpregs.swd is 0x38 (expected NOT ZERO) +RESULT: ok +*** RT_001: PASSED + +*** LT_001 start ******************************* +ptrace01 1 TPASS : Test Passed +ptrace01 2 TPASS : Test Passed +*** LT_001: PASSED (ok:2) + +*** LT_002 start ******************************* +ptrace02 1 TPASS : Test Passed +ptrace02 2 TPASS : Test Passed +*** LT_002: PASSED (ok:2) + +*** LT_003 start ******************************* +ptrace03 1 TCONF : ptrace03.c:137: this kernel allows to trace init +ptrace03 2 TPASS : Test Passed +ptrace03 3 TPASS : Test Passed +*** LT_003: PASSED (ok:2) + +*** LT_004 start ******************************* +ptrace05 0 TINFO : [child] Sending kill(.., 0) +ptrace05 1 TPASS : kill(.., 0) exited with 0, as expected. +ptrace05 2 TPASS : Stopped as expected +ptrace05 3 TPASS : Stopped as expected +ptrace05 4 TPASS : Stopped as expected +ptrace05 5 TPASS : Stopped as expected +ptrace05 6 TPASS : Stopped as expected +ptrace05 7 TPASS : Stopped as expected +ptrace05 8 TPASS : Stopped as expected +ptrace05 9 TPASS : Stopped as expected +ptrace05 10 TPASS : Killed with SIGKILL, as expected. +ptrace05 11 TPASS : Stopped as expected +ptrace05 12 TPASS : Stopped as expected +ptrace05 13 TPASS : Stopped as expected +ptrace05 14 TPASS : Stopped as expected +ptrace05 15 TPASS : Stopped as expected +ptrace05 16 TPASS : Stopped as expected +ptrace05 17 TPASS : Stopped as expected +ptrace05 18 TPASS : Stopped as expected +ptrace05 19 TPASS : Stopped as expected +ptrace05 20 TPASS : Stopped as expected +ptrace05 21 TPASS : Stopped as expected +ptrace05 22 TPASS : Stopped as expected +ptrace05 23 TPASS : Stopped as expected +ptrace05 24 TPASS : Stopped as expected +ptrace05 25 TPASS : Stopped as expected +ptrace05 26 TPASS : Stopped as expected +ptrace05 27 TPASS : Stopped as expected +ptrace05 28 TPASS : Stopped as expected +ptrace05 29 TPASS : Stopped as expected +ptrace05 30 TPASS : Stopped as expected +ptrace05 31 TPASS : Stopped as expected +ptrace05 32 TPASS : Stopped as expected +ptrace05 33 TPASS : Stopped as expected +ptrace05 34 TPASS : Stopped as expected +ptrace05 35 TPASS : Stopped as expected +ptrace05 36 TPASS : Stopped as expected +ptrace05 37 TPASS : Stopped as expected +ptrace05 38 TPASS : Stopped as expected +ptrace05 39 TPASS : Stopped as expected +ptrace05 40 TPASS : Stopped as expected +ptrace05 41 TPASS : Stopped as expected +ptrace05 42 TPASS : Stopped as expected +ptrace05 43 TPASS : Stopped as expected +ptrace05 44 TPASS : Stopped as expected +ptrace05 45 TPASS : Stopped as expected +ptrace05 46 TPASS : Stopped as expected +ptrace05 47 TPASS : Stopped as expected +ptrace05 48 TPASS : Stopped as expected +ptrace05 49 TPASS : Stopped as expected +ptrace05 50 TPASS : Stopped as expected +ptrace05 51 TPASS : Stopped as expected +ptrace05 52 TPASS : Stopped as expected +ptrace05 53 TPASS : Stopped as expected +ptrace05 54 TPASS : Stopped as expected +ptrace05 55 TPASS : Stopped as expected +ptrace05 56 TPASS : Stopped as expected +ptrace05 57 TPASS : Stopped as expected +ptrace05 58 TPASS : Stopped as expected +ptrace05 59 TPASS : Stopped as expected +ptrace05 60 TPASS : Stopped as expected +ptrace05 61 TPASS : Stopped as expected +ptrace05 62 TPASS : Stopped as expected +ptrace05 63 TPASS : Stopped as expected +ptrace05 64 TPASS : Stopped as expected +ptrace05 65 TPASS : Stopped as expected +*** LT_004: PASSED (ok:65)