memory_range_lock: Enable interrupt when trylock fails

Also use read-write-lock

Change-Id: I03150b7208325ec1fe422dcd5f931e4e41c8e40e
Refs: #452
This commit is contained in:
Tomoki Shirasawa
2019-07-29 14:12:50 +09:00
committed by Masamichi Takagi
parent 258156b57e
commit 0d3ef65092
13 changed files with 444 additions and 101 deletions

107
test/issues/452/C452.patch Normal file
View File

@ -0,0 +1,107 @@
diff --git a/arch/arm64/kernel/include/syscall_list.h b/arch/arm64/kernel/include/syscall_list.h
index f911674..52c164f 100644
--- a/arch/arm64/kernel/include/syscall_list.h
+++ b/arch/arm64/kernel/include/syscall_list.h
@@ -134,6 +134,8 @@ SYSCALL_HANDLED(731, util_indicate_clone)
SYSCALL_HANDLED(732, get_system)
SYSCALL_HANDLED(733, util_register_desc)
+SYSCALL_HANDLED(740, setkdebug)
+
/* McKernel Specific */
SYSCALL_HANDLED(801, swapout)
SYSCALL_HANDLED(802, linux_mlock)
diff --git a/arch/x86_64/kernel/include/syscall_list.h b/arch/x86_64/kernel/include/syscall_list.h
index 79eda7f..1f81b0a 100644
--- a/arch/x86_64/kernel/include/syscall_list.h
+++ b/arch/x86_64/kernel/include/syscall_list.h
@@ -174,6 +174,8 @@ SYSCALL_HANDLED(731, util_indicate_clone)
SYSCALL_HANDLED(732, get_system)
SYSCALL_HANDLED(733, util_register_desc)
+SYSCALL_HANDLED(740, setkdebug)
+
/* McKernel Specific */
SYSCALL_HANDLED(801, swapout)
SYSCALL_HANDLED(802, linux_mlock)
diff --git a/kernel/include/process.h b/kernel/include/process.h
index 0a9ff47..ecb464f 100644
--- a/kernel/include/process.h
+++ b/kernel/include/process.h
@@ -573,6 +573,7 @@ struct process {
#endif // PROFILE_ENABLE
int nr_processes; /* For partitioned execution */
int process_rank; /* Rank in partition */
+ int debug_flags;
};
/*
diff --git a/kernel/procfs.c b/kernel/procfs.c
index 5f9675c..a1b6d22 100644
--- a/kernel/procfs.c
+++ b/kernel/procfs.c
@@ -420,6 +420,7 @@ int process_procfs_request(struct ikc_scd_packet *rpacket)
if (strcmp(p, "maps") == 0) {
struct vm_range *range;
+ kprintf("read /proc/*/maps\n");
memory_range_read_lock(vm, &irqflags);
range = lookup_process_memory_range(vm, 0, -1);
@@ -485,6 +486,7 @@ int process_procfs_request(struct ikc_scd_packet *rpacket)
start = (offset / sizeof(uint64_t)) << PAGE_SHIFT;
end = start + ((count / sizeof(uint64_t)) << PAGE_SHIFT);
+ kprintf("read /proc/*/pagemap\n");
memory_range_read_lock(vm, &irqflags);
while (start < end) {
@@ -527,6 +529,7 @@ int process_procfs_request(struct ikc_scd_packet *rpacket)
goto err;
}
+ kprintf("read /proc/*/status\n");
memory_range_read_lock(proc->vm, &irqflags);
range = lookup_process_memory_range(vm, 0, -1);
while (range) {
diff --git a/kernel/syscall.c b/kernel/syscall.c
index 012ef13..9a34984 100644
--- a/kernel/syscall.c
+++ b/kernel/syscall.c
@@ -1635,6 +1635,18 @@ do_mmap(const uintptr_t addr0, const size_t len0, const int prot,
flush_nfo_tlb();
memory_range_write_lock(thread->vm, &irqflags);
+ if(thread->proc->debug_flags) {
+ // sleep 5 sec
+ unsigned long ts = rdtsc();
+ unsigned long nanosecs = 5000000000L;
+ unsigned long tscs = nanosecs * 1000 / ihk_mc_get_ns_per_tsc();
+
+ kprintf("kernel debug sleep 5sec...\n");
+ while (rdtsc() - ts < tscs) {
+ cpu_pause();
+ }
+ kprintf("kernel debug wake up\n");
+ }
if (flags & MAP_HUGETLB) {
pgshift = (flags >> MAP_HUGE_SHIFT) & 0x3F;
@@ -9482,6 +9494,17 @@ SYSCALL_DECLARE(util_register_desc)
return 0;
}
+SYSCALL_DECLARE(setkdebug)
+{
+ int flags = ihk_mc_syscall_arg0(ctx);
+ struct thread *mythread = cpu_local_var(current);
+ struct process *proc = mythread->proc;
+
+ kprintf("set kernel debug flag pid=%d val=%d\n", proc->pid, flags);
+ proc->debug_flags = flags;
+ return 0;
+}
+
void
reset_cputime()
{

22
test/issues/452/C452.sh Normal file
View File

@ -0,0 +1,22 @@
#!/bin/sh
USELTP=1
USEOSTEST=0
. ../../common.sh
################################################################################
$MCEXEC ./C452T01
for i in mmap01:02 mmap02:03 mmap03:04 mmap04:05 mmap12:06 brk01:07 fork01:08 \
fork02:09 fork03:10; do
tp=`echo $i|sed 's/:.*//'`
id=`echo $i|sed 's/.*://'`
$MCEXEC $LTPBIN/$tp 2>&1 | tee $tp.txt
ok=`grep TPASS $tp.txt | wc -l`
ng=`grep TFAIL $tp.txt | wc -l`
if [ $ng = 0 ]; then
echo "*** C452T$id: $tp PASS ($ok)"
else
echo "*** C452T$id: $tp FAIL (ok=$ok ng=%ng)"
fi
done

52
test/issues/452/C452.txt Normal file
View File

@ -0,0 +1,52 @@
Script started on Wed Jul 3 13:39:36 2019
bash-4.2$ make test
sh ./C452.sh
mcstop+release.sh ... done
mcreboot.sh -c 1-7,17-23,9-15,25-31 -m 10G@0,10G@1 ... done
*** C452T01 test start
000000400000-000000401000 r-xs 0 0:0 0
000000600000-000000601000 r--s 0 0:0 0
000000601000-000000602000 rw-s 0 0:0 0
155555600000-155555622000 r-xs 0 0:0 0
155555821000-155555822000 r--s 0 0:0 0
155555822000-155555824000 rw-s 0 0:0 0
2aaaaa9f8000-2aaaaaa00000 rw-p 0 0:0 0
2aaaaaa00000-2aaaaaa02000 r-xs 0 0:0 0 [vdso]
2aaaaaa02000-2aaaaaa03000 rw-p 0 0:0 0
2aaaaaa1a000-2aaaaaa1b000 rw-p 0 0:0 0
2aaaaaa1b000-2aaaaabde000 r-xp 0 0:0 0 /usr/lib64/libc-2.17.so
2aaaaabde000-2aaaaaddd000 ---p 0 0:0 0 /usr/lib64/libc-2.17.so
2aaaaaddd000-2aaaaade1000 r--p 0 0:0 0 /usr/lib64/libc-2.17.so
2aaaaade1000-2aaaaade3000 rw-p 0 0:0 0 /usr/lib64/libc-2.17.so
2aaaaade3000-2aaaaade8000 rw-p 0 0:0 0
2aaaaade8000-2aaaaadea000 rw-p 0 0:0 0
2aaaaadea000-2aaaaadeb000 rw-p 0 0:0 0
547fff800000-548000000000 rw-p 0 0:0 0 [stack]
*** C452T01 PASS
mmap01 1 TPASS : Functionality of mmap() successful
*** C452T02: mmap01 PASS (1)
mmap02 1 TPASS : Functionality of mmap() successful
*** C452T03: mmap02 PASS (1)
mmap03 1 TPASS : mmap() functionality is correct
*** C452T04: mmap03 PASS (1)
mmap04 1 TPASS : Functionality of mmap() successful
*** C452T05: mmap04 PASS (1)
mmap12 1 TPASS : Functionality of mmap() successful
*** C452T06: mmap12 PASS (1)
brk01 1 TPASS : brk(8626060) returned 0, new size verified by sbrk
*** C452T07: brk01 PASS (1)
fork01 1 TPASS : fork() returned 19074
fork01 2 TPASS : child pid and fork() return agree: 19074
*** C452T08: fork01 PASS (2)
fork02 0 TINFO : Inside parent
fork02 0 TINFO : Inside child
fork02 0 TINFO : exit status of wait 0
fork02 1 TPASS : test 1 PASSED
*** C452T09: fork02 PASS (1)
fork03 0 TINFO : process id in parent of child from fork : 19223
fork03 1 TPASS : test 1 PASSED
*** C452T10: fork03 PASS (1)
bash-4.2$ exit
exit
Script done on Wed Jul 3 13:39:53 2019

40
test/issues/452/C452T01.c Normal file
View File

@ -0,0 +1,40 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
int
main(int argc, char **argv)
{
pid_t pid;
int st;
fprintf(stderr, "*** C452T01 test start\n");
fflush(stderr);
pid = fork();
if (pid == 0) {
char file[32];
sleep(1);
sprintf(file, "/proc/%d/maps", getppid());
execlp("cat", "cat", file, NULL);
exit(1);
}
fflush(stdout);
if (syscall(740, 1) == -1) {
fprintf(stderr, "*** C452T01 FAIL no patched kernel\n");
exit(1);
}
mmap(NULL, 4096, PROT_READ|PROT_WRITE,
MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
syscall(740, 0);
while (waitpid(pid, &st, 0) == -1 && errno == EINTR)
;
fprintf(stderr, "*** C452T01 PASS\n");
exit(0);
}

13
test/issues/452/Makefile Normal file
View File

@ -0,0 +1,13 @@
CC = gcc
TARGET = C452T01
all:: $(TARGET)
C452T01: C452T01.c
$(CC) -g -Wall -o $@ $^
test:: all
sh ./C452.sh
clean::
rm -f $(TARGET) *.o

36
test/issues/452/README Normal file
View File

@ -0,0 +1,36 @@
【Issue#452 動作確認】
□ テスト内容
1. Issue 指摘事項の再現確認
以下のパッチ (C452.patch) を McKernel に適用し、意図的に memory_range_lock の
競合を起こすことでテストを容易にする。
- mmap処理のmemory_range_lock取得中にsleep可能とする
- mmap処理のmemory_range_lock取得中にsleepするかどうかを制御する
システムコールを追加する
このパッチ適用カーネルを使ってテストする。
C452T01 memory_range_lock 取得中に /proc/*/maps を参照し、PASS すること
2. LTP を用いて既存処理に影響しないことを確認
メモリ関連処理を変更したため、関連するシステムコールのテストを選定した。
C452T02 mmap01: mmap の基本機能の確認
C452T03 mmap02: mmap の基本機能の確認
C452T04 mmap03: mmap の基本機能の確認
C452T05 mmap04: mmap の基本機能の確認
C452T06 mmap12: mmap の基本機能の確認
C452T07 brk01: brk の基本機能の確認
C452T08 fork01: fork の基本機能の確認 (fork時メモリがコピーされる)
C452T09 fork02: fork の基本機能の確認
C452T10 fork03: fork の基本機能の確認
□ 実行手順
$ make test
McKernelのインストール先や LTP の配置場所は、$HOME/.mck_test_config を
参照する。.mck_test_config は、McKernel をビルドした際に生成される
mck_test_config.sample ファイルを $HOME にコピーし、適宜編集すること。
尚、テスト実行には C452.patch を適用した McKernel を使用すること。
□ 実行結果
C452.txt 参照。
全ての項目が PASS していることを確認。