wait: Delay wake-up parent within switch context

Fujitsu: POSTK_DEBUG_TEMP_FIX_41
Refs: #1006
Change-Id: Ia98e896505ad0f6549766604ade84550eee8bd2d
This commit is contained in:
Ken Sato
2018-08-29 14:30:32 +09:00
committed by Masamichi Takagi
parent 0fdeb254b3
commit f57b0c5d4f
10 changed files with 280 additions and 43 deletions

View File

@ -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_start(struct mc_perf_event *event);
extern void perf_reset(struct mc_perf_event *event); extern void perf_reset(struct mc_perf_event *event);
struct thread *last; struct thread *last;
#ifdef POSTK_DEBUG_TEMP_FIX_41 /* early to wait4() wakeup for ptrace, fix. */
struct mcs_rwlock_node_irqsave lock; struct mcs_rwlock_node_irqsave lock;
#endif /* POSTK_DEBUG_TEMP_FIX_41 */
/* Set up new TLS.. */ /* Set up new TLS.. */
dkprintf("[%d] arch_switch_context: tlsblock_base: 0x%lX\n", 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)) { if (likely(prev)) {
tls_thread_switch(prev, next); 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); mcs_rwlock_writer_lock(&prev->proc->update_lock, &lock);
if (prev->proc->status & (PS_DELAY_STOPPED | PS_DELAY_TRACED)) { if (prev->proc->status & (PS_DELAY_STOPPED | PS_DELAY_TRACED)) {
switch (prev->proc->status) { switch (prev->proc->status) {
@ -1342,11 +1339,12 @@ struct thread *arch_switch_context(struct thread *prev, struct thread *next)
break; break;
} }
mcs_rwlock_writer_unlock(&prev->proc->update_lock, &lock); 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); waitq_wakeup(&prev->proc->parent->waitpid_q);
} else { } else {
mcs_rwlock_writer_unlock(&prev->proc->update_lock, &lock); 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); last = ihk_mc_switch_context(&prev->ctx, &next->ctx, prev);
} }

View File

@ -957,11 +957,7 @@ void ptrace_report_signal(struct thread *thread, int sig)
} }
thread->exit_status = sig; thread->exit_status = sig;
/* Transition thread state */ /* Transition thread state */
#ifdef POSTK_DEBUG_TEMP_FIX_41 /* early to wait4() wakeup for ptrace, fix. */
proc->status = PS_DELAY_TRACED; 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; thread->status = PS_TRACED;
proc->ptrace &= ~PT_TRACE_SYSCALL; proc->ptrace &= ~PT_TRACE_SYSCALL;
if (sig == SIGSTOP || sig == SIGTSTP || 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_pid = thread->tid;
info._sifields._sigchld.si_status = thread->exit_status; info._sifields._sigchld.si_status = thread->exit_status;
do_kill(cpu_local_var(current), parent_pid, -1, SIGCHLD, &info, 0); 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"); dkprintf("ptrace_report_signal,sleeping\n");
/* Sleep */ /* Sleep */

View File

@ -1176,19 +1176,10 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
/* Reap and set new signal_flags */ /* Reap and set new signal_flags */
proc->signal_flags = SIGNAL_STOP_STOPPED; proc->signal_flags = SIGNAL_STOP_STOPPED;
#ifdef POSTK_DEBUG_TEMP_FIX_41 /* early to wait4() wakeup for ptrace, fix. */
proc->status = PS_DELAY_STOPPED; 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; thread->status = PS_STOPPED;
mcs_rwlock_writer_unlock(&proc->update_lock, &lock); 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", dkprintf("do_signal(): pid: %d, tid: %d SIGSTOP, sleeping\n",
proc->pid, thread->tid); proc->pid, thread->tid);
/* Sleep */ /* Sleep */
@ -1205,19 +1196,10 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
/* Update thread state in fork tree */ /* Update thread state in fork tree */
mcs_rwlock_writer_lock(&proc->update_lock, &lock); mcs_rwlock_writer_lock(&proc->update_lock, &lock);
thread->exit_status = SIGTRAP; thread->exit_status = SIGTRAP;
#ifdef POSTK_DEBUG_TEMP_FIX_41 /* early to wait4() wakeup for ptrace, fix. */
proc->status = PS_DELAY_TRACED; 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; thread->status = PS_TRACED;
mcs_rwlock_writer_unlock(&proc->update_lock, &lock); 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 */ /* Sleep */
dkprintf("do_signal,SIGTRAP,sleeping\n"); dkprintf("do_signal,SIGTRAP,sleeping\n");

View File

@ -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 *arch_switch_context(struct thread *prev, struct thread *next)
{ {
struct thread *last; struct thread *last;
struct mcs_rwlock_node_irqsave lock;
dkprintf("[%d] schedule: tlsblock_base: 0x%lX\n", dkprintf("[%d] schedule: tlsblock_base: 0x%lX\n",
ihk_mc_get_processor_id(), next->tlsblock_base); ihk_mc_get_processor_id(), next->tlsblock_base);
@ -1677,6 +1678,28 @@ struct thread *arch_switch_context(struct thread *prev, struct thread *next)
#endif #endif
if (prev) { 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); last = ihk_mc_switch_context(&prev->ctx, &next->ctx, prev);
} }
else { else {

View File

@ -534,7 +534,7 @@ void ptrace_report_signal(struct thread *thread, int sig)
} }
thread->exit_status = sig; thread->exit_status = sig;
/* Transition thread state */ /* Transition thread state */
proc->status = PS_TRACED; proc->status = PS_DELAY_TRACED;
thread->status = PS_TRACED; thread->status = PS_TRACED;
proc->ptrace &= ~PT_TRACE_SYSCALL; proc->ptrace &= ~PT_TRACE_SYSCALL;
if (sig == SIGSTOP || sig == SIGTSTP || 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_pid = thread->tid;
info._sifields._sigchld.si_status = thread->exit_status; info._sifields._sigchld.si_status = thread->exit_status;
do_kill(cpu_local_var(current), parent_pid, -1, SIGCHLD, &info, 0); 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"); dkprintf("ptrace_report_signal,sleeping\n");
/* Sleep */ /* Sleep */
@ -864,13 +862,10 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
/* Reap and set new signal_flags */ /* Reap and set new signal_flags */
proc->signal_flags = SIGNAL_STOP_STOPPED; proc->signal_flags = SIGNAL_STOP_STOPPED;
proc->status = PS_STOPPED; proc->status = PS_DELAY_STOPPED;
thread->status = PS_STOPPED; thread->status = PS_STOPPED;
mcs_rwlock_writer_unlock(&proc->update_lock, &lock); 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", dkprintf("do_signal(): pid: %d, tid: %d SIGSTOP, sleeping\n",
proc->pid, thread->tid); proc->pid, thread->tid);
/* Sleep */ /* Sleep */
@ -887,13 +882,10 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
/* Update thread state in fork tree */ /* Update thread state in fork tree */
mcs_rwlock_writer_lock(&proc->update_lock, &lock); mcs_rwlock_writer_lock(&proc->update_lock, &lock);
thread->exit_status = SIGTRAP; thread->exit_status = SIGTRAP;
proc->status = PS_TRACED; proc->status = PS_DELAY_TRACED;
thread->status = PS_TRACED; thread->status = PS_TRACED;
mcs_rwlock_writer_unlock(&proc->update_lock, &lock); 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 */ /* Sleep */
dkprintf("do_signal,SIGTRAP,sleeping\n"); dkprintf("do_signal,SIGTRAP,sleeping\n");

View File

@ -70,10 +70,8 @@
#define PS_TRACED 0x40 /* Set to "not running" by a ptrace related event */ #define PS_TRACED 0x40 /* Set to "not running" by a ptrace related event */
#define PS_STOPPING 0x80 #define PS_STOPPING 0x80
#define PS_TRACING 0x100 #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_STOPPED 0x200
#define PS_DELAY_TRACED 0x400 #define PS_DELAY_TRACED 0x400
#endif /* POSTK_DEBUG_TEMP_FIX_41 */
#define PS_NORMAL (PS_INTERRUPTIBLE | PS_UNINTERRUPTIBLE) #define PS_NORMAL (PS_INTERRUPTIBLE | PS_UNINTERRUPTIBLE)

106
test/issues/1006/C1006.sh Normal file
View File

@ -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 ""

14
test/issues/1006/Makefile Normal file
View File

@ -0,0 +1,14 @@
CC = gcc
TARGET=
CPPFLAGS =
LDFLAGS =
all: $(TARGET)
test: all
@sh ./C1006.sh
clean:
rm -f $(TARGET) *.o

37
test/issues/1006/README Normal file
View File

@ -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していることを確認。

View File

@ -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)