Compare commits
93 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 63ed4e7af0 | |||
| d7cf39883f | |||
| 40f8091fab | |||
| a20e1acf01 | |||
| b3d7bbda56 | |||
| 9a60997ea0 | |||
| 4b66373813 | |||
| b44b11ace7 | |||
| ebc91cea0e | |||
| 58106d791a | |||
| 56b51d4f97 | |||
| bafe540d86 | |||
| d78a0fd05d | |||
| 999bc91b4f | |||
| b3bd2ea9b3 | |||
| d3d9e2400d | |||
| 199407b2a1 | |||
| 5973d66e2d | |||
| d7ef74659b | |||
| ac86affecc | |||
| 2026cf8dad | |||
| 1d135492c3 | |||
| 1cfc5ca71f | |||
| 7ee533d620 | |||
| 28334c7a29 | |||
| 697e9386b3 | |||
| 0e787b731e | |||
| 612f364e6a | |||
| ceee4c379f | |||
| 36c981bc34 | |||
| fd941dad44 | |||
| 5f5b9f94d1 | |||
| 3f3c4acd71 | |||
| 00007dafaa | |||
| cbe2b2149d | |||
| 4cecde3fba | |||
| 8022a2a8c0 | |||
| 3328ce03d9 | |||
| 97b107f61c | |||
| 6f3be17c19 | |||
| dea7d00545 | |||
| 4512778569 | |||
| a7adb266ff | |||
| 2566f4f213 | |||
| ac0081eddd | |||
| d4056acfc3 | |||
| 1910543380 | |||
| 6332903f0d | |||
| 29d27b7c8d | |||
| 7136384384 | |||
| 2fe5c8de2e | |||
| e774e1b984 | |||
| 33b7414615 | |||
| 3c646e2485 | |||
| a5fcc91656 | |||
| d370e9241f | |||
| 3e254c06bf | |||
| 07537cd2e7 | |||
| a37f72da0e | |||
| ab11b168f0 | |||
| eac414d6d8 | |||
| bb725f5f50 | |||
| 5224551782 | |||
| 91146acfe5 | |||
| f64731ab34 | |||
| cd46cbd4b3 | |||
| 39780917af | |||
| 0f8f6d298e | |||
| f8e8b21f04 | |||
| 5c2f9b8239 | |||
| 1afc3d9b70 | |||
| 17a8f68d60 | |||
| 2b9a053504 | |||
| 6441aa1abb | |||
| 9b55b68934 | |||
| 83ef96a739 | |||
| b5337358cf | |||
| 2db3717e57 | |||
| 5395891966 | |||
| c32a5e261b | |||
| c0c80b71ca | |||
| d15a396d5a | |||
| e35ec09da1 | |||
| 5e44c9c9f9 | |||
| 0f6c36870c | |||
| 2ec2112cc5 | |||
| c86a38e18f | |||
| 6aa7b50e26 | |||
| c3c57940ba | |||
| 7aa2d64294 | |||
| 51fe77cdae | |||
| d5aafca1ae | |||
| 54b529c82d |
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +1,6 @@
|
||||
[submodule "ihk"]
|
||||
path = ihk
|
||||
url = https://github.com/RIKEN-SysSoft/ihk.git
|
||||
[submodule "executer/user/lib/libdwarf/libdwarf"]
|
||||
path = executer/user/lib/libdwarf/libdwarf
|
||||
url = https://github.com/bgerofi/libdwarf.git
|
||||
|
||||
@ -10,7 +10,7 @@ project(mckernel C ASM)
|
||||
set(MCKERNEL_VERSION "1.7.0")
|
||||
|
||||
# See "Fedora Packaging Guidlines -- Versioning"
|
||||
set(MCKERNEL_RELEASE "0.2")
|
||||
set(MCKERNEL_RELEASE "0.7")
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules)
|
||||
# for rpmbuild
|
||||
@ -34,6 +34,7 @@ include(GNUInstallDirs)
|
||||
include(CMakeParseArguments)
|
||||
include(Kbuild)
|
||||
include(CheckCCompilerFlag)
|
||||
include(AutoconfHelper)
|
||||
|
||||
CHECK_C_COMPILER_FLAG(-Wno-implicit-fallthrough IMPLICIT_FALLTHROUGH)
|
||||
if(IMPLICIT_FALLTHROUGH)
|
||||
@ -119,9 +120,36 @@ find_package(PkgConfig REQUIRED)
|
||||
set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH ON)
|
||||
|
||||
find_library(LIBRT rt)
|
||||
if (NOT LIBRT)
|
||||
message(FATAL_ERROR "error: couldn't find librt")
|
||||
endif()
|
||||
find_library(LIBNUMA numa)
|
||||
if (NOT LIBNUMA)
|
||||
message(FATAL_ERROR "error: couldn't find libnuma")
|
||||
endif()
|
||||
find_library(LIBBFD bfd)
|
||||
if (NOT LIBBFD)
|
||||
message(FATAL_ERROR "error: couldn't find libbfd")
|
||||
endif()
|
||||
find_library(LIBIBERTY iberty)
|
||||
if (NOT LIBIBERTY)
|
||||
message(FATAL_ERROR "error: couldn't find libiberty")
|
||||
endif()
|
||||
|
||||
find_library(LIBDWARF dwarf)
|
||||
|
||||
if (NOT LIBDWARF)
|
||||
if (CMAKE_CROSSCOMPILING)
|
||||
message(FATAL_ERROR "Could not find libdwarf.so, install libdwarf-devel to ${CMAKE_FIND_ROOT_PATH}")
|
||||
endif()
|
||||
message("WARNING: libdwarf will be compiled locally")
|
||||
enable_language(CXX)
|
||||
else()
|
||||
# Note that libdwarf-devel provides /usr/include/libdwarf/dwarf.h
|
||||
# but elfutils-devel provides /usr/include/dwarf.h
|
||||
# while mcinspect.c performs "#include <dwarf.h>"
|
||||
find_path(DWARF_H dwarf.h PATH_SUFFIXES libdwarf)
|
||||
endif()
|
||||
|
||||
if (ENABLE_QLMPI)
|
||||
find_package(MPI REQUIRED)
|
||||
@ -186,10 +214,14 @@ add_subdirectory(tools/crash)
|
||||
configure_file(scripts/mcreboot-smp.sh.in mcreboot.sh @ONLY)
|
||||
configure_file(scripts/mcstop+release-smp.sh.in mcstop+release.sh @ONLY)
|
||||
configure_file(scripts/mcreboot.1in mcreboot.1 @ONLY)
|
||||
configure_file(scripts/eclair-dump-backtrace.exp.in eclair-dump-backtrace.exp @ONLY)
|
||||
install(PROGRAMS
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/mcreboot.sh"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/mcstop+release.sh"
|
||||
DESTINATION "${CMAKE_INSTALL_SBINDIR}")
|
||||
install(PROGRAMS
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/eclair-dump-backtrace.exp"
|
||||
DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
install(FILES "scripts/irqbalance_mck.in"
|
||||
DESTINATION "${CMAKE_INSTALL_SYSCONFDIR}")
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/mcreboot.1"
|
||||
|
||||
6
NEWS.md
6
NEWS.md
@ -532,3 +532,9 @@ Restrictions on McKernel
|
||||
|
||||
24. ihk_os_getperfevent() could time-out when invoked from Fujitsu TCS
|
||||
(job-scheduler).
|
||||
|
||||
25. The behaviors of madvise and mbind are changed to do nothing and
|
||||
report success as a workaround for Fugaku.
|
||||
|
||||
26. mmap() allows unlimited overcommit. Note that it corresponds to
|
||||
setting sysctl ``vm.overcommit_memory`` to 1.
|
||||
|
||||
@ -1497,6 +1497,19 @@ struct thread *arch_switch_context(struct thread *prev, struct thread *next)
|
||||
}
|
||||
}
|
||||
#endif /*ENABLE_PERF*/
|
||||
|
||||
#ifdef PROFILE_ENABLE
|
||||
if (prev && prev->profile && prev->profile_start_ts != 0) {
|
||||
prev->profile_elapsed_ts +=
|
||||
(rdtsc() - prev->profile_start_ts);
|
||||
prev->profile_start_ts = 0;
|
||||
}
|
||||
|
||||
if (next->profile && next->profile_start_ts == 0) {
|
||||
next->profile_start_ts = rdtsc();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (likely(prev)) {
|
||||
tls_thread_switch(prev, next);
|
||||
|
||||
@ -1867,6 +1880,11 @@ int arch_cpu_read_write_register(
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
dkprintf("%s: MCCTRL_OS_CPU_%s_REGISTER: reg: 0x%lx, val: 0x%lx\n",
|
||||
__FUNCTION__,
|
||||
(op == MCCTRL_OS_CPU_READ_REGISTER ? "READ" : "WRITE"),
|
||||
desc->addr, desc->val);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -85,7 +85,11 @@ enum __rlimit_resource
|
||||
__RLIMIT_RTPRIO = 14,
|
||||
#define RLIMIT_RTPRIO __RLIMIT_RTPRIO
|
||||
|
||||
__RLIMIT_NLIMITS = 15,
|
||||
/* timeout for RT tasks in us */
|
||||
__RLIMIT_RTTIME = 15,
|
||||
#define RLIMIT_RTTIME __RLIMIT_RTTIME
|
||||
|
||||
__RLIMIT_NLIMITS = 16,
|
||||
__RLIM_NLIMITS = __RLIMIT_NLIMITS
|
||||
#define RLIMIT_NLIMITS __RLIMIT_NLIMITS
|
||||
#define RLIM_NLIMITS __RLIM_NLIMITS
|
||||
|
||||
@ -118,6 +118,7 @@ SYSCALL_HANDLED(241, perf_event_open)
|
||||
SYSCALL_DELEGATED(241, perf_event_open)
|
||||
#endif // PERF_ENABLE
|
||||
SYSCALL_HANDLED(260, wait4)
|
||||
SYSCALL_HANDLED(261, prlimit64)
|
||||
SYSCALL_HANDLED(270, process_vm_readv)
|
||||
SYSCALL_HANDLED(271, process_vm_writev)
|
||||
SYSCALL_HANDLED(281, execveat)
|
||||
@ -143,3 +144,9 @@ SYSCALL_HANDLED(1045, signalfd)
|
||||
SYSCALL_DELEGATED(1049, stat)
|
||||
SYSCALL_DELEGATED(1060, getpgrp)
|
||||
SYSCALL_HANDLED(1062, time)
|
||||
SYSCALL_DELEGATED(1069, epoll_wait)
|
||||
|
||||
/* Do not edit the lines including this comment and
|
||||
* EOF just after it because those are used as a
|
||||
* robust marker for the autotest patch.
|
||||
*/
|
||||
|
||||
@ -310,6 +310,9 @@ void handle_interrupt_gicv3(struct pt_regs *regs)
|
||||
{
|
||||
uint64_t irqnr;
|
||||
const int from_user = interrupt_from_user(regs);
|
||||
struct cpu_local_var *v = get_this_cpu_local_var();
|
||||
//unsigned long irqflags;
|
||||
int do_check = 0;
|
||||
|
||||
irqnr = gic_read_iar();
|
||||
cpu_enable_nmi();
|
||||
@ -323,10 +326,18 @@ void handle_interrupt_gicv3(struct pt_regs *regs)
|
||||
}
|
||||
set_cputime(from_user ? CPUTIME_MODE_K2U : CPUTIME_MODE_K2K_OUT);
|
||||
|
||||
/* for migration by IPI */
|
||||
if (get_this_cpu_local_var()->flags & CPU_FLAG_NEED_MIGRATE) {
|
||||
schedule();
|
||||
//irqflags = ihk_mc_spinlock_lock(&v->runq_lock);
|
||||
/* For migration by IPI or by timesharing */
|
||||
if (v->flags &
|
||||
(CPU_FLAG_NEED_MIGRATE | CPU_FLAG_NEED_RESCHED)) {
|
||||
v->flags &= ~CPU_FLAG_NEED_RESCHED;
|
||||
do_check = 1;
|
||||
}
|
||||
//ihk_mc_spinlock_unlock(&v->runq_lock, irqflags);
|
||||
|
||||
if (do_check) {
|
||||
check_signal(0, regs, 0);
|
||||
schedule();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ int ihk_mc_ikc_init_first_local(struct ihk_ikc_channel_desc *channel,
|
||||
|
||||
memset(channel, 0, sizeof(struct ihk_ikc_channel_desc));
|
||||
|
||||
mikc_queue_pages = ((4 * num_processors * MASTER_IKCQ_PKTSIZE)
|
||||
mikc_queue_pages = ((8 * num_processors * MASTER_IKCQ_PKTSIZE)
|
||||
+ (PAGE_SIZE - 1)) / PAGE_SIZE;
|
||||
|
||||
/* Place both sides in this side */
|
||||
|
||||
@ -590,7 +590,7 @@ static inline void armv8pmu_write_counter(int idx, uint32_t value)
|
||||
* count using the lower 32bits and we want an interrupt when
|
||||
* it overflows.
|
||||
*/
|
||||
uint64_t value64 = 0xffffffff00000000ULL | value;
|
||||
uint64_t value64 = (int32_t)value;
|
||||
|
||||
write_sysreg(value64, pmccntr_el0);
|
||||
}
|
||||
|
||||
@ -15,7 +15,6 @@
|
||||
#include <limits.h>
|
||||
#include <uio.h>
|
||||
#include <syscall.h>
|
||||
#include <bitops.h>
|
||||
#include <rusage_private.h>
|
||||
#include <ihk/debug.h>
|
||||
|
||||
@ -58,13 +57,34 @@ extern int num_processors;
|
||||
int obtain_clone_cpuid(cpu_set_t *cpu_set, int use_last)
|
||||
{
|
||||
int min_queue_len = -1;
|
||||
int cpu, min_cpu = -1, uti_cpu = -1;
|
||||
unsigned long irqstate;
|
||||
int cpu, min_cpu = -1;
|
||||
#if 0
|
||||
int uti_cpu = -1;
|
||||
#endif
|
||||
unsigned long irqstate = 0;
|
||||
|
||||
irqstate = ihk_mc_spinlock_lock(&runq_reservation_lock);
|
||||
int start, end, step;
|
||||
|
||||
if (use_last) {
|
||||
start = num_processors - 1;
|
||||
end = -1;
|
||||
step = -1;
|
||||
}
|
||||
else {
|
||||
start = 0;
|
||||
end = num_processors;
|
||||
step = 1;
|
||||
}
|
||||
|
||||
if (!cpu_local_var(current)->proc->nr_processes) {
|
||||
irqstate = ihk_mc_spinlock_lock(&runq_reservation_lock);
|
||||
}
|
||||
else {
|
||||
irqstate = cpu_disable_interrupt_save();
|
||||
}
|
||||
|
||||
/* Find the first allowed core with the shortest run queue */
|
||||
for (cpu = 0; cpu < num_processors; ++cpu) {
|
||||
for (cpu = start; cpu != end; cpu += step) {
|
||||
struct cpu_local_var *v;
|
||||
|
||||
if (!CPU_ISSET(cpu, cpu_set))
|
||||
@ -75,11 +95,14 @@ int obtain_clone_cpuid(cpu_set_t *cpu_set, int use_last)
|
||||
dkprintf("%s: cpu=%d,runq_len=%d,runq_reserved=%d\n",
|
||||
__func__, cpu, v->runq_len, v->runq_reserved);
|
||||
if (min_queue_len == -1 ||
|
||||
v->runq_len + v->runq_reserved < min_queue_len) {
|
||||
min_queue_len = v->runq_len + v->runq_reserved;
|
||||
//v->runq_len + v->runq_reserved < min_queue_len) {
|
||||
v->runq_len < min_queue_len) {
|
||||
//min_queue_len = v->runq_len + v->runq_reserved;
|
||||
min_queue_len = v->runq_len;
|
||||
min_cpu = cpu;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Record the last tie CPU */
|
||||
if (min_cpu != cpu &&
|
||||
v->runq_len + v->runq_reserved == min_queue_len) {
|
||||
@ -88,14 +111,15 @@ int obtain_clone_cpuid(cpu_set_t *cpu_set, int use_last)
|
||||
dkprintf("%s: cpu=%d,runq_len=%d,runq_reserved=%d,min_cpu=%d,uti_cpu=%d\n",
|
||||
__func__, cpu, v->runq_len, v->runq_reserved,
|
||||
min_cpu, uti_cpu);
|
||||
#else
|
||||
|
||||
ihk_mc_spinlock_unlock_noirq(&v->runq_lock);
|
||||
#if 0
|
||||
if (min_queue_len == 0)
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
min_cpu = use_last ? uti_cpu : min_cpu;
|
||||
if (min_cpu != -1) {
|
||||
if (get_cpu_local_var(min_cpu)->status != CPU_STATUS_RESERVED)
|
||||
@ -104,22 +128,20 @@ int obtain_clone_cpuid(cpu_set_t *cpu_set, int use_last)
|
||||
__sync_fetch_and_add(&get_cpu_local_var(min_cpu)->runq_reserved,
|
||||
1);
|
||||
}
|
||||
ihk_mc_spinlock_unlock(&runq_reservation_lock, irqstate);
|
||||
#else
|
||||
__sync_fetch_and_add(&get_cpu_local_var(min_cpu)->runq_reserved, 1);
|
||||
#endif
|
||||
|
||||
if (!cpu_local_var(current)->proc->nr_processes) {
|
||||
ihk_mc_spinlock_unlock(&runq_reservation_lock, irqstate);
|
||||
}
|
||||
else {
|
||||
cpu_restore_interrupt(irqstate);
|
||||
}
|
||||
|
||||
return min_cpu;
|
||||
}
|
||||
|
||||
int
|
||||
arch_clear_host_user_space()
|
||||
{
|
||||
struct thread *th = cpu_local_var(current);
|
||||
|
||||
/* XXX: might be unnecessary */
|
||||
clear_host_pte(th->vm->region.user_start,
|
||||
(th->vm->region.user_end - th->vm->region.user_start), 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* archtecture-depended syscall handlers */
|
||||
extern unsigned long do_fork(int clone_flags, unsigned long newsp,
|
||||
unsigned long parent_tidptr, unsigned long child_tidptr,
|
||||
@ -152,33 +174,6 @@ SYSCALL_DECLARE(clone)
|
||||
return ret;
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(rt_sigaction)
|
||||
{
|
||||
int sig = ihk_mc_syscall_arg0(ctx);
|
||||
const struct sigaction *act = (const struct sigaction *)ihk_mc_syscall_arg1(ctx);
|
||||
struct sigaction *oact = (struct sigaction *)ihk_mc_syscall_arg2(ctx);
|
||||
size_t sigsetsize = ihk_mc_syscall_arg3(ctx);
|
||||
struct k_sigaction new_sa, old_sa;
|
||||
int rc;
|
||||
|
||||
if (sigsetsize != sizeof(sigset_t))
|
||||
return -EINVAL;
|
||||
|
||||
if(act)
|
||||
if(copy_from_user(&new_sa.sa, act, sizeof new_sa.sa)){
|
||||
goto fault;
|
||||
}
|
||||
rc = do_sigaction(sig, act? &new_sa: NULL, oact? &old_sa: NULL);
|
||||
if(rc == 0 && oact)
|
||||
if(copy_to_user(oact, &old_sa.sa, sizeof old_sa.sa)){
|
||||
goto fault;
|
||||
}
|
||||
|
||||
return rc;
|
||||
fault:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(prctl)
|
||||
{
|
||||
struct process *proc = cpu_local_var(current)->proc;
|
||||
@ -1335,70 +1330,6 @@ out:
|
||||
return restart;
|
||||
}
|
||||
|
||||
static struct sig_pending *
|
||||
getsigpending(struct thread *thread, int delflag){
|
||||
struct list_head *head;
|
||||
mcs_rwlock_lock_t *lock;
|
||||
struct mcs_rwlock_node_irqsave mcs_rw_node;
|
||||
struct sig_pending *next;
|
||||
struct sig_pending *pending;
|
||||
__sigset_t w;
|
||||
|
||||
w = thread->sigmask.__val[0];
|
||||
|
||||
lock = &thread->sigcommon->lock;
|
||||
head = &thread->sigcommon->sigpending;
|
||||
for(;;) {
|
||||
if (delflag) {
|
||||
mcs_rwlock_writer_lock(lock, &mcs_rw_node);
|
||||
}
|
||||
else {
|
||||
mcs_rwlock_reader_lock(lock, &mcs_rw_node);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(pending, next, head, list){
|
||||
if(!(pending->sigmask.__val[0] & w)){
|
||||
if(delflag)
|
||||
list_del(&pending->list);
|
||||
|
||||
if (delflag) {
|
||||
mcs_rwlock_writer_unlock(lock, &mcs_rw_node);
|
||||
}
|
||||
else {
|
||||
mcs_rwlock_reader_unlock(lock, &mcs_rw_node);
|
||||
}
|
||||
return pending;
|
||||
}
|
||||
}
|
||||
|
||||
if (delflag) {
|
||||
mcs_rwlock_writer_unlock(lock, &mcs_rw_node);
|
||||
}
|
||||
else {
|
||||
mcs_rwlock_reader_unlock(lock, &mcs_rw_node);
|
||||
}
|
||||
|
||||
if(lock == &thread->sigpendinglock)
|
||||
return NULL;
|
||||
|
||||
lock = &thread->sigpendinglock;
|
||||
head = &thread->sigpending;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct sig_pending *
|
||||
hassigpending(struct thread *thread)
|
||||
{
|
||||
if (list_empty(&thread->sigpending) &&
|
||||
list_empty(&thread->sigcommon->sigpending)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return getsigpending(thread, 0);
|
||||
}
|
||||
|
||||
int
|
||||
interrupt_from_user(void *regs0)
|
||||
{
|
||||
@ -1422,191 +1353,6 @@ void save_syscall_return_value(int num, unsigned long rc)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
check_signal(unsigned long rc, void *regs0, int num)
|
||||
{
|
||||
__check_signal(rc, regs0, num, 0);
|
||||
}
|
||||
|
||||
void
|
||||
check_signal_irq_disabled(unsigned long rc, void *regs0, int num)
|
||||
{
|
||||
__check_signal(rc, regs0, num, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
__check_signal(unsigned long rc, void *regs0, int num, int irq_disabled)
|
||||
{
|
||||
ihk_mc_user_context_t *regs = regs0;
|
||||
struct thread *thread;
|
||||
struct sig_pending *pending;
|
||||
int irqstate;
|
||||
|
||||
if(clv == NULL)
|
||||
return;
|
||||
thread = cpu_local_var(current);
|
||||
|
||||
if(thread == NULL || thread->proc->pid == 0){
|
||||
struct thread *t;
|
||||
|
||||
irqstate = cpu_disable_interrupt_save();
|
||||
ihk_mc_spinlock_lock_noirq(&(cpu_local_var(runq_lock)));
|
||||
list_for_each_entry(t, &(cpu_local_var(runq)), sched_list){
|
||||
if(t->proc->pid <= 0)
|
||||
continue;
|
||||
if(t->status == PS_INTERRUPTIBLE &&
|
||||
hassigpending(t)){
|
||||
t->status = PS_RUNNING;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ihk_mc_spinlock_unlock_noirq(&(cpu_local_var(runq_lock)));
|
||||
cpu_restore_interrupt(irqstate);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(regs != NULL && !interrupt_from_user(regs)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (list_empty(&thread->sigpending) &&
|
||||
list_empty(&thread->sigcommon->sigpending)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
for(;;){
|
||||
/* When this function called from check_signal_irq_disabled,
|
||||
* return with interrupt invalid.
|
||||
* This is to eliminate signal loss.
|
||||
*/
|
||||
if (irq_disabled == 1) {
|
||||
irqstate = cpu_disable_interrupt_save();
|
||||
}
|
||||
pending = getsigpending(thread, 1);
|
||||
if(!pending) {
|
||||
dkprintf("check_signal,queue is empty\n");
|
||||
goto out;
|
||||
}
|
||||
if (irq_disabled == 1) {
|
||||
cpu_restore_interrupt(irqstate);
|
||||
}
|
||||
if (do_signal(rc, regs, thread, pending, num)) {
|
||||
num = -1;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
check_sig_pending_thread(struct thread *thread)
|
||||
{
|
||||
int found = 0;
|
||||
struct list_head *head;
|
||||
mcs_rwlock_lock_t *lock;
|
||||
struct mcs_rwlock_node_irqsave mcs_rw_node;
|
||||
struct sig_pending *next;
|
||||
struct sig_pending *pending;
|
||||
__sigset_t w;
|
||||
__sigset_t x;
|
||||
int sig = 0;
|
||||
struct k_sigaction *k;
|
||||
struct cpu_local_var *v;
|
||||
|
||||
v = get_this_cpu_local_var();
|
||||
w = thread->sigmask.__val[0];
|
||||
|
||||
lock = &thread->sigcommon->lock;
|
||||
head = &thread->sigcommon->sigpending;
|
||||
for (;;) {
|
||||
mcs_rwlock_reader_lock(lock, &mcs_rw_node);
|
||||
|
||||
list_for_each_entry_safe(pending, next, head, list) {
|
||||
for (x = pending->sigmask.__val[0], sig = 0; x;
|
||||
sig++, x >>= 1)
|
||||
;
|
||||
k = thread->sigcommon->action + sig - 1;
|
||||
if ((sig != SIGCHLD &&
|
||||
sig != SIGURG &&
|
||||
sig != SIGCONT) ||
|
||||
(k->sa.sa_handler != SIG_IGN &&
|
||||
k->sa.sa_handler != NULL)) {
|
||||
if (!(pending->sigmask.__val[0] & w)) {
|
||||
if (pending->interrupted == 0) {
|
||||
pending->interrupted = 1;
|
||||
found = 1;
|
||||
if (sig != SIGCHLD &&
|
||||
sig != SIGURG &&
|
||||
sig != SIGCONT &&
|
||||
!k->sa.sa_handler) {
|
||||
found = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mcs_rwlock_reader_unlock(lock, &mcs_rw_node);
|
||||
|
||||
if (found == 2) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (lock == &thread->sigpendinglock) {
|
||||
break;
|
||||
}
|
||||
|
||||
lock = &thread->sigpendinglock;
|
||||
head = &thread->sigpending;
|
||||
}
|
||||
|
||||
if (found == 2) {
|
||||
ihk_mc_spinlock_unlock(&v->runq_lock, v->runq_irqstate);
|
||||
terminate_mcexec(0, sig);
|
||||
return 1;
|
||||
}
|
||||
else if (found == 1) {
|
||||
ihk_mc_spinlock_unlock(&v->runq_lock, v->runq_irqstate);
|
||||
interrupt_syscall(thread, 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
check_sig_pending(void)
|
||||
{
|
||||
struct thread *thread;
|
||||
struct cpu_local_var *v;
|
||||
|
||||
if (clv == NULL)
|
||||
return;
|
||||
|
||||
v = get_this_cpu_local_var();
|
||||
repeat:
|
||||
v->runq_irqstate = ihk_mc_spinlock_lock(&v->runq_lock);
|
||||
list_for_each_entry(thread, &(v->runq), sched_list) {
|
||||
|
||||
if (thread == NULL || thread == &cpu_local_var(idle)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (thread->in_syscall_offload == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (thread->proc->group_exit_status & 0x0000000100000000L) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (check_sig_pending_thread(thread))
|
||||
goto repeat;
|
||||
}
|
||||
ihk_mc_spinlock_unlock(&v->runq_lock, v->runq_irqstate);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
do_kill(struct thread * thread, int pid, int tid, int sig, siginfo_t *info, int ptracecont)
|
||||
{
|
||||
@ -2043,7 +1789,7 @@ SYSCALL_DECLARE(mmap)
|
||||
goto out;
|
||||
}
|
||||
|
||||
addr = do_mmap(addr, len, prot, flags, fd, off0, 0, NULL);
|
||||
addr = do_mmap(addr, len, prot, flags, fd, off0);
|
||||
|
||||
error = 0;
|
||||
out:
|
||||
@ -2137,7 +1883,9 @@ int do_process_vm_read_writev(int pid,
|
||||
unsigned long lpage_left, rpage_left;
|
||||
unsigned long lpsize, rpsize;
|
||||
void *rva, *lva;
|
||||
#if 0
|
||||
struct vm_range *range;
|
||||
#endif
|
||||
struct mcs_rwlock_node_irqsave lock;
|
||||
struct mcs_rwlock_node update_lock;
|
||||
|
||||
@ -2150,8 +1898,9 @@ int do_process_vm_read_writev(int pid,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Check if parameters are okay */
|
||||
ihk_mc_spinlock_lock_noirq(<hread->vm->memory_range_lock);
|
||||
ihk_rwspinlock_read_lock_noirq(<hread->vm->memory_range_lock);
|
||||
|
||||
range = lookup_process_memory_range(lthread->vm,
|
||||
(uintptr_t)local_iov,
|
||||
@ -2173,11 +1922,12 @@ int do_process_vm_read_writev(int pid,
|
||||
|
||||
ret = 0;
|
||||
arg_out:
|
||||
ihk_mc_spinlock_unlock_noirq(<hread->vm->memory_range_lock);
|
||||
ihk_rwspinlock_read_unlock_noirq(<hread->vm->memory_range_lock);
|
||||
|
||||
if (ret != 0) {
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (li = 0; li < liovcnt; ++li) {
|
||||
llen += local_iov[li].iov_len;
|
||||
@ -2242,7 +1992,7 @@ arg_out:
|
||||
if (pli != li) {
|
||||
struct vm_range *range;
|
||||
|
||||
ihk_mc_spinlock_lock_noirq(<hread->vm->memory_range_lock);
|
||||
ihk_rwspinlock_read_lock_noirq(<hread->vm->memory_range_lock);
|
||||
|
||||
/* Is base valid? */
|
||||
range = lookup_process_memory_range(lthread->vm,
|
||||
@ -2272,7 +2022,7 @@ arg_out:
|
||||
|
||||
ret = 0;
|
||||
pli_out:
|
||||
ihk_mc_spinlock_unlock_noirq(<hread->vm->memory_range_lock);
|
||||
ihk_rwspinlock_read_unlock_noirq(<hread->vm->memory_range_lock);
|
||||
|
||||
if (ret != 0) {
|
||||
goto out;
|
||||
@ -2285,7 +2035,7 @@ pli_out:
|
||||
if (pri != ri) {
|
||||
struct vm_range *range;
|
||||
|
||||
ihk_mc_spinlock_lock_noirq(&rvm->memory_range_lock);
|
||||
ihk_rwspinlock_read_lock_noirq(&rvm->memory_range_lock);
|
||||
|
||||
/* Is base valid? */
|
||||
range = lookup_process_memory_range(rvm,
|
||||
@ -2315,7 +2065,7 @@ pli_out:
|
||||
|
||||
ret = 0;
|
||||
pri_out:
|
||||
ihk_mc_spinlock_unlock_noirq(&rvm->memory_range_lock);
|
||||
ihk_rwspinlock_read_unlock_noirq(&rvm->memory_range_lock);
|
||||
|
||||
if (ret != 0) {
|
||||
goto out;
|
||||
|
||||
@ -155,7 +155,7 @@ int arch_map_vdso(struct process_vm *vm)
|
||||
flag = VR_REMOTE | VR_PROT_READ;
|
||||
flag |= VRFLAG_PROT_TO_MAXPROT(flag);
|
||||
ret = add_process_memory_range(vm, start, end, vdso.vvar_phys, flag,
|
||||
NULL, 0, PAGE_SHIFT, NULL, &range);
|
||||
NULL, 0, PAGE_SHIFT, &range);
|
||||
if (ret != 0){
|
||||
dkprintf("ERROR: adding memory range for tod_data\n");
|
||||
goto exit;
|
||||
@ -167,7 +167,7 @@ int arch_map_vdso(struct process_vm *vm)
|
||||
flag = VR_REMOTE | VR_PROT_READ | VR_PROT_EXEC;
|
||||
flag |= VRFLAG_PROT_TO_MAXPROT(flag);
|
||||
ret = add_process_memory_range(vm, start, end, vdso.vdso_physlist[0], flag,
|
||||
NULL, 0, PAGE_SHIFT, NULL, &range);
|
||||
NULL, 0, PAGE_SHIFT, &range);
|
||||
if (ret != 0) {
|
||||
dkprintf("ERROR: adding memory range for vdso_text\n");
|
||||
|
||||
|
||||
@ -84,7 +84,11 @@ enum __rlimit_resource
|
||||
__RLIMIT_RTPRIO = 14,
|
||||
#define RLIMIT_RTPRIO __RLIMIT_RTPRIO
|
||||
|
||||
__RLIMIT_NLIMITS = 15,
|
||||
/* timeout for RT tasks in us */
|
||||
__RLIMIT_RTTIME = 15,
|
||||
#define RLIMIT_RTTIME __RLIMIT_RTTIME
|
||||
|
||||
__RLIMIT_NLIMITS = 16,
|
||||
__RLIM_NLIMITS = __RLIMIT_NLIMITS
|
||||
#define RLIMIT_NLIMITS __RLIMIT_NLIMITS
|
||||
#define RLIM_NLIMITS __RLIM_NLIMITS
|
||||
|
||||
@ -158,6 +158,7 @@ SYSCALL_HANDLED(289, signalfd4)
|
||||
#ifdef ENABLE_PERF
|
||||
SYSCALL_HANDLED(298, perf_event_open)
|
||||
#endif
|
||||
SYSCALL_HANDLED(302, prlimit64)
|
||||
#ifdef DCFA_KMOD
|
||||
SYSCALL_HANDLED(303, mod_call)
|
||||
#endif
|
||||
@ -180,4 +181,8 @@ SYSCALL_HANDLED(802, linux_mlock)
|
||||
SYSCALL_HANDLED(803, suspend_threads)
|
||||
SYSCALL_HANDLED(804, resume_threads)
|
||||
SYSCALL_HANDLED(811, linux_spawn)
|
||||
/**** End of File ****/
|
||||
|
||||
/* Do not edit the lines including this comment and
|
||||
* EOF just after it because those are used as a
|
||||
* robust marker for the autotest patch.
|
||||
*/
|
||||
|
||||
@ -31,7 +31,6 @@
|
||||
#include <page.h>
|
||||
#include <limits.h>
|
||||
#include <syscall.h>
|
||||
#include <bitops.h>
|
||||
#include <rusage_private.h>
|
||||
#include <ihk/debug.h>
|
||||
|
||||
@ -148,44 +147,6 @@ int obtain_clone_cpuid(cpu_set_t *cpu_set, int use_last) {
|
||||
return min_cpu;
|
||||
}
|
||||
|
||||
int
|
||||
arch_clear_host_user_space()
|
||||
{
|
||||
struct thread *th = cpu_local_var(current);
|
||||
|
||||
/* XXX: might be unnecessary */
|
||||
clear_host_pte(th->vm->region.user_start,
|
||||
(th->vm->region.user_end - th->vm->region.user_start), 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(rt_sigaction)
|
||||
{
|
||||
int sig = ihk_mc_syscall_arg0(ctx);
|
||||
const struct sigaction *act = (const struct sigaction *)ihk_mc_syscall_arg1(ctx);
|
||||
struct sigaction *oact = (struct sigaction *)ihk_mc_syscall_arg2(ctx);
|
||||
size_t sigsetsize = ihk_mc_syscall_arg3(ctx);
|
||||
struct k_sigaction new_sa, old_sa;
|
||||
int rc;
|
||||
|
||||
if (sigsetsize != sizeof(sigset_t))
|
||||
return -EINVAL;
|
||||
|
||||
if(act)
|
||||
if(copy_from_user(&new_sa.sa, act, sizeof new_sa.sa)){
|
||||
goto fault;
|
||||
}
|
||||
rc = do_sigaction(sig, act? &new_sa: NULL, oact? &old_sa: NULL);
|
||||
if(rc == 0 && oact)
|
||||
if(copy_to_user(oact, &old_sa.sa, sizeof old_sa.sa)){
|
||||
goto fault;
|
||||
}
|
||||
|
||||
return rc;
|
||||
fault:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(prctl)
|
||||
{
|
||||
struct process *proc = cpu_local_var(current)->proc;
|
||||
@ -1040,82 +1001,6 @@ out:
|
||||
return restart;
|
||||
}
|
||||
|
||||
static struct sig_pending *
|
||||
getsigpending(struct thread *thread, int delflag){
|
||||
struct list_head *head;
|
||||
mcs_rwlock_lock_t *lock;
|
||||
struct mcs_rwlock_node_irqsave mcs_rw_node;
|
||||
struct sig_pending *next;
|
||||
struct sig_pending *pending;
|
||||
__sigset_t w;
|
||||
__sigset_t x;
|
||||
int sig;
|
||||
struct k_sigaction *k;
|
||||
|
||||
w = thread->sigmask.__val[0];
|
||||
|
||||
lock = &thread->sigcommon->lock;
|
||||
head = &thread->sigcommon->sigpending;
|
||||
for(;;) {
|
||||
if (delflag) {
|
||||
mcs_rwlock_writer_lock(lock, &mcs_rw_node);
|
||||
}
|
||||
else {
|
||||
mcs_rwlock_reader_lock(lock, &mcs_rw_node);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(pending, next, head, list){
|
||||
for(x = pending->sigmask.__val[0], sig = 0; x; sig++, x >>= 1);
|
||||
k = thread->sigcommon->action + sig - 1;
|
||||
if(delflag ||
|
||||
(sig != SIGCHLD &&
|
||||
sig != SIGURG &&
|
||||
sig != SIGCONT) ||
|
||||
(k->sa.sa_handler != (void *)1 &&
|
||||
k->sa.sa_handler != NULL)){
|
||||
if(!(pending->sigmask.__val[0] & w)){
|
||||
if(delflag)
|
||||
list_del(&pending->list);
|
||||
|
||||
if (delflag) {
|
||||
mcs_rwlock_writer_unlock(lock, &mcs_rw_node);
|
||||
}
|
||||
else {
|
||||
mcs_rwlock_reader_unlock(lock, &mcs_rw_node);
|
||||
}
|
||||
return pending;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (delflag) {
|
||||
mcs_rwlock_writer_unlock(lock, &mcs_rw_node);
|
||||
}
|
||||
else {
|
||||
mcs_rwlock_reader_unlock(lock, &mcs_rw_node);
|
||||
}
|
||||
|
||||
if(lock == &thread->sigpendinglock)
|
||||
return NULL;
|
||||
|
||||
lock = &thread->sigpendinglock;
|
||||
head = &thread->sigpending;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct sig_pending *
|
||||
hassigpending(struct thread *thread)
|
||||
{
|
||||
if (list_empty(&thread->sigpending) &&
|
||||
list_empty(&thread->sigcommon->sigpending)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return getsigpending(thread, 0);
|
||||
}
|
||||
|
||||
int
|
||||
interrupt_from_user(void *regs0)
|
||||
{
|
||||
@ -1130,175 +1015,6 @@ void save_syscall_return_value(int num, unsigned long rc)
|
||||
return;
|
||||
}
|
||||
|
||||
/** \brief check arrived signals and processing
|
||||
*
|
||||
* @param rc return value of syscall
|
||||
* @param regs0 context
|
||||
* @param num syscall number (-1: Not called on exiting system call)
|
||||
*/
|
||||
void
|
||||
check_signal(unsigned long rc, void *regs0, int num)
|
||||
{
|
||||
struct x86_user_context *regs = regs0;
|
||||
struct thread *thread;
|
||||
struct sig_pending *pending;
|
||||
int irqstate;
|
||||
|
||||
if(clv == NULL)
|
||||
return;
|
||||
thread = cpu_local_var(current);
|
||||
|
||||
if(thread == NULL || thread == &cpu_local_var(idle)){
|
||||
struct thread *t;
|
||||
|
||||
irqstate = cpu_disable_interrupt_save();
|
||||
ihk_mc_spinlock_lock_noirq(&(cpu_local_var(runq_lock)));
|
||||
list_for_each_entry(t, &(cpu_local_var(runq)), sched_list){
|
||||
if(t == &cpu_local_var(idle))
|
||||
continue;
|
||||
if(t->status == PS_INTERRUPTIBLE &&
|
||||
hassigpending(t)){
|
||||
t->status = PS_RUNNING;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ihk_mc_spinlock_unlock_noirq(&(cpu_local_var(runq_lock)));
|
||||
cpu_restore_interrupt(irqstate);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(regs != NULL && !interrupt_from_user(regs)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (list_empty(&thread->sigpending) &&
|
||||
list_empty(&thread->sigcommon->sigpending)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
for(;;){
|
||||
pending = getsigpending(thread, 1);
|
||||
if(!pending) {
|
||||
dkprintf("check_signal,queue is empty\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (do_signal(rc, regs, thread, pending, num)) {
|
||||
num = -1;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
check_sig_pending_thread(struct thread *thread)
|
||||
{
|
||||
int found = 0;
|
||||
struct list_head *head;
|
||||
mcs_rwlock_lock_t *lock;
|
||||
struct mcs_rwlock_node_irqsave mcs_rw_node;
|
||||
struct sig_pending *next;
|
||||
struct sig_pending *pending;
|
||||
__sigset_t w;
|
||||
__sigset_t x;
|
||||
int sig = 0;
|
||||
struct k_sigaction *k;
|
||||
struct cpu_local_var *v;
|
||||
|
||||
v = get_this_cpu_local_var();
|
||||
w = thread->sigmask.__val[0];
|
||||
|
||||
lock = &thread->sigcommon->lock;
|
||||
head = &thread->sigcommon->sigpending;
|
||||
for (;;) {
|
||||
mcs_rwlock_reader_lock(lock, &mcs_rw_node);
|
||||
|
||||
list_for_each_entry_safe(pending, next, head, list){
|
||||
for (x = pending->sigmask.__val[0], sig = 0; x;
|
||||
sig++, x >>= 1);
|
||||
k = thread->sigcommon->action + sig - 1;
|
||||
if ((sig != SIGCHLD &&
|
||||
sig != SIGURG &&
|
||||
sig != SIGCONT) ||
|
||||
(k->sa.sa_handler != (void *)1 &&
|
||||
k->sa.sa_handler != NULL)) {
|
||||
if (!(pending->sigmask.__val[0] & w)) {
|
||||
if (pending->interrupted == 0) {
|
||||
pending->interrupted = 1;
|
||||
found = 1;
|
||||
if (sig != SIGCHLD &&
|
||||
sig != SIGURG &&
|
||||
sig != SIGCONT &&
|
||||
!k->sa.sa_handler) {
|
||||
found = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mcs_rwlock_reader_unlock(lock, &mcs_rw_node);
|
||||
|
||||
if (found == 2) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (lock == &thread->sigpendinglock) {
|
||||
break;
|
||||
}
|
||||
|
||||
lock = &thread->sigpendinglock;
|
||||
head = &thread->sigpending;
|
||||
}
|
||||
|
||||
if (found == 2) {
|
||||
ihk_mc_spinlock_unlock(&v->runq_lock, v->runq_irqstate);
|
||||
terminate_mcexec(0, sig);
|
||||
return 1;
|
||||
}
|
||||
else if (found == 1) {
|
||||
ihk_mc_spinlock_unlock(&v->runq_lock, v->runq_irqstate);
|
||||
interrupt_syscall(thread, 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
check_sig_pending(void)
|
||||
{
|
||||
struct thread *thread;
|
||||
struct cpu_local_var *v;
|
||||
|
||||
if (clv == NULL)
|
||||
return;
|
||||
|
||||
v = get_this_cpu_local_var();
|
||||
repeat:
|
||||
v->runq_irqstate = ihk_mc_spinlock_lock(&v->runq_lock);
|
||||
list_for_each_entry(thread, &(v->runq), sched_list) {
|
||||
|
||||
if (thread == NULL || thread == &cpu_local_var(idle)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (thread->in_syscall_offload == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (thread->proc->group_exit_status & 0x0000000100000000L) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (check_sig_pending_thread(thread))
|
||||
goto repeat;
|
||||
}
|
||||
ihk_mc_spinlock_unlock(&v->runq_lock, v->runq_irqstate);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
do_kill(struct thread *thread, int pid, int tid, int sig, siginfo_t *info,
|
||||
int ptracecont)
|
||||
@ -1786,7 +1502,7 @@ recheck:
|
||||
goto out;
|
||||
}
|
||||
|
||||
addr = do_mmap(addr, len, prot, flags, fd, off0, 0, NULL);
|
||||
addr = do_mmap(addr, len, prot, flags, fd, off0);
|
||||
|
||||
error = 0;
|
||||
out:
|
||||
@ -2115,7 +1831,7 @@ int arch_map_vdso(struct process_vm *vm)
|
||||
vrflags |= VR_PROT_READ | VR_PROT_EXEC;
|
||||
vrflags |= VRFLAG_PROT_TO_MAXPROT(vrflags);
|
||||
error = add_process_memory_range(vm, (intptr_t)s, (intptr_t)e,
|
||||
NOPHYS, vrflags, NULL, 0, PAGE_SHIFT, NULL, &range);
|
||||
NOPHYS, vrflags, NULL, 0, PAGE_SHIFT, &range);
|
||||
if (error) {
|
||||
ekprintf("ERROR: adding memory range for vdso. %d\n", error);
|
||||
goto out;
|
||||
@ -2147,8 +1863,7 @@ int arch_map_vdso(struct process_vm *vm)
|
||||
vrflags |= VR_PROT_READ;
|
||||
vrflags |= VRFLAG_PROT_TO_MAXPROT(vrflags);
|
||||
error = add_process_memory_range(vm, (intptr_t)s, (intptr_t)e,
|
||||
NOPHYS, vrflags, NULL, 0,
|
||||
PAGE_SHIFT, NULL, &range);
|
||||
NOPHYS, vrflags, NULL, 0, PAGE_SHIFT, &range);
|
||||
if (error) {
|
||||
ekprintf("ERROR: adding memory range for vvar. %d\n", error);
|
||||
goto out;
|
||||
@ -2290,7 +2005,7 @@ int do_process_vm_read_writev(int pid,
|
||||
}
|
||||
|
||||
/* Check if parameters are okay */
|
||||
ihk_mc_spinlock_lock_noirq(<hread->vm->memory_range_lock);
|
||||
ihk_rwspinlock_read_lock_noirq(<hread->vm->memory_range_lock);
|
||||
|
||||
range = lookup_process_memory_range(lthread->vm,
|
||||
(uintptr_t)local_iov,
|
||||
@ -2312,7 +2027,7 @@ int do_process_vm_read_writev(int pid,
|
||||
|
||||
ret = 0;
|
||||
arg_out:
|
||||
ihk_mc_spinlock_unlock_noirq(<hread->vm->memory_range_lock);
|
||||
ihk_rwspinlock_read_unlock_noirq(<hread->vm->memory_range_lock);
|
||||
|
||||
if (ret != 0) {
|
||||
goto out;
|
||||
@ -2381,7 +2096,7 @@ arg_out:
|
||||
if (pli != li) {
|
||||
struct vm_range *range;
|
||||
|
||||
ihk_mc_spinlock_lock_noirq(<hread->vm->memory_range_lock);
|
||||
ihk_rwspinlock_read_lock_noirq(<hread->vm->memory_range_lock);
|
||||
|
||||
/* Is base valid? */
|
||||
range = lookup_process_memory_range(lthread->vm,
|
||||
@ -2411,7 +2126,7 @@ arg_out:
|
||||
|
||||
ret = 0;
|
||||
pli_out:
|
||||
ihk_mc_spinlock_unlock_noirq(<hread->vm->memory_range_lock);
|
||||
ihk_rwspinlock_read_unlock_noirq(<hread->vm->memory_range_lock);
|
||||
|
||||
if (ret != 0) {
|
||||
goto out;
|
||||
@ -2424,7 +2139,7 @@ pli_out:
|
||||
if (pri != ri) {
|
||||
struct vm_range *range;
|
||||
|
||||
ihk_mc_spinlock_lock_noirq(&rvm->memory_range_lock);
|
||||
ihk_rwspinlock_read_lock_noirq(&rvm->memory_range_lock);
|
||||
|
||||
/* Is base valid? */
|
||||
range = lookup_process_memory_range(rvm,
|
||||
@ -2454,7 +2169,7 @@ pli_out:
|
||||
|
||||
ret = 0;
|
||||
pri_out:
|
||||
ihk_mc_spinlock_unlock_noirq(&rvm->memory_range_lock);
|
||||
ihk_rwspinlock_read_unlock_noirq(&rvm->memory_range_lock);
|
||||
|
||||
if (ret != 0) {
|
||||
goto out;
|
||||
|
||||
383
cmake/modules/AutoconfHelper.cmake
Normal file
383
cmake/modules/AutoconfHelper.cmake
Normal file
@ -0,0 +1,383 @@
|
||||
# Helper functions for translating autoconf projects. Several functions
|
||||
# are lifted from the Mono sources
|
||||
|
||||
include (CheckCSourceCompiles)
|
||||
include (CheckIncludeFile)
|
||||
include (TestBigEndian)
|
||||
include (CheckFunctionExists)
|
||||
include (CheckTypeSize)
|
||||
include (CheckCSourceRuns)
|
||||
|
||||
|
||||
# Function to get the version information from the configure.ac file in the
|
||||
# current directory. Its argument is the name of the library as passed to
|
||||
# AC_INIT. It will set the variables ${LIBNAME}_VERSION and ${LIBNAME}_SOVERSION
|
||||
function (ac_get_version libname)
|
||||
string(TOUPPER "${libname}" libname_upper)
|
||||
|
||||
# Read the relevant content from configure.ac
|
||||
file (STRINGS configure.ac tmp_configure_ac
|
||||
REGEX "${libname_upper}_[_A-Z]+=[ \\t]*[0-9]+")
|
||||
|
||||
# Product version
|
||||
string (REGEX REPLACE ".+MAJOR[_A-Z]+=([0-9]+).+MINOR[_A-Z]+=([0-9]+).+MICRO[_A-Z]+=([0-9]+).*"
|
||||
"\\1.\\2.\\3" ${libname_upper}_VERSION "${tmp_configure_ac}")
|
||||
|
||||
# Library version for libtool
|
||||
string (REGEX REPLACE ".+CURRENT=([0-9]+).+REVISION=([0-9]+).+AGE=([0-9]+).*"
|
||||
"\\1.\\2.\\3" ${libname_upper}_SOVERSION "${tmp_configure_ac}")
|
||||
|
||||
# Checks if the string needs to be displayed
|
||||
set (${libname_upper}_DISPLAYSTR_AUX
|
||||
"Found ${libname} version ${${libname_upper}_VERSION}, soversion ${${libname_upper}_SOVERSION} from configure.ac"
|
||||
)
|
||||
if ((NOT ${libname_upper}_DISPLAYSTR) OR (NOT ${libname_upper}_DISPLAYSTR STREQUAL ${libname_upper}_DISPLAYSTR_AUX))
|
||||
set (${libname_upper}_DISPLAYSTR ${${libname_upper}_DISPLAYSTR_AUX}
|
||||
CACHE INTERNAL "Version string from ${libname}" FORCE)
|
||||
message (STATUS ${${libname_upper}_DISPLAYSTR})
|
||||
endif ()
|
||||
|
||||
# Export the result to the caller
|
||||
set(${libname_upper}_VERSION "${${libname_upper}_VERSION}" PARENT_SCOPE)
|
||||
set(${libname_upper}_SOVERSION "${${libname_upper}_SOVERSION}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
|
||||
# Also from mono's source code
|
||||
# Implementation of AC_CHECK_HEADERS
|
||||
# In addition, it also records the list of variables in the variable
|
||||
# 'autoheader_vars', and for each variable, a documentation string in the
|
||||
# variable ${var}_doc
|
||||
function(ac_check_headers)
|
||||
foreach (header ${ARGV})
|
||||
string(TOUPPER ${header} header_var)
|
||||
string(REPLACE "." "_" header_var ${header_var})
|
||||
string(REPLACE "/" "_" header_var ${header_var})
|
||||
set(header_var "HAVE_${header_var}")
|
||||
check_include_file (${header} ${header_var})
|
||||
set("${header_var}_doc" "Define to 1 if you have the <${header}> header file." PARENT_SCOPE)
|
||||
if (${header_var})
|
||||
set("${header_var}_defined" "1" PARENT_SCOPE)
|
||||
endif()
|
||||
set("${header_var}_val" "1" PARENT_SCOPE)
|
||||
set (autoheader_vars ${autoheader_vars} ${header_var})
|
||||
endforeach()
|
||||
set (autoheader_vars ${autoheader_vars} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Function taken from mono's source code
|
||||
function (ac_check_funcs)
|
||||
foreach (func ${ARGV})
|
||||
string(TOUPPER ${func} var)
|
||||
set(var "HAVE_${var}")
|
||||
set(${var})
|
||||
check_function_exists (${func} ${var})
|
||||
set("${var}_doc" "Define to 1 if you have the '${func}' function." PARENT_SCOPE)
|
||||
if (${var})
|
||||
set("${var}_defined" "1" PARENT_SCOPE)
|
||||
set(${var} yes PARENT_SCOPE)
|
||||
endif()
|
||||
set("${var}_val" "1" PARENT_SCOPE)
|
||||
set (autoheader_vars ${autoheader_vars} ${var})
|
||||
endforeach()
|
||||
set (autoheader_vars ${autoheader_vars} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
|
||||
# Specifically, this macro checks for stdlib.h', stdarg.h',
|
||||
# string.h', and float.h'; if the system has those, it probably
|
||||
# has the rest of the ANSI C header files. This macro also checks
|
||||
# whether string.h' declares memchr' (and thus presumably the
|
||||
# other mem' functions), whether stdlib.h' declare free' (and
|
||||
# thus presumably malloc' and other related functions), and whether
|
||||
# the ctype.h' macros work on characters with the high bit set, as
|
||||
# ANSI C requires.
|
||||
function (ac_header_stdc)
|
||||
if (STDC_HEADERS)
|
||||
return()
|
||||
endif()
|
||||
message(STATUS "Looking for ANSI-C headers")
|
||||
set(code "
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <float.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *ptr;
|
||||
free((void*)1);
|
||||
ptr = memchr((void*)1, 0, 0);
|
||||
|
||||
return (int)ptr;
|
||||
}
|
||||
")
|
||||
# FIXME Check the ctype.h high bit
|
||||
CHECK_C_SOURCE_COMPILES("${code}" STDC_HEADERS)
|
||||
if (STDC_HEADERS)
|
||||
set(STDC_HEADERS 1 PARENT_SCOPE)
|
||||
message(STATUS "Looking for ANSI-C headers - found")
|
||||
else()
|
||||
message(STATUS "Looking for ANSI-C headers - not found")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
|
||||
# Also from the mono sources, kind of implements AC_SYS_LARGEFILE
|
||||
function (ac_sys_largefile)
|
||||
CHECK_C_SOURCE_RUNS("
|
||||
#include <sys/types.h>
|
||||
#define BIG_OFF_T (((off_t)1<<62)-1+((off_t)1<<62))
|
||||
int main (int argc, char **argv) {
|
||||
int big_off_t=((BIG_OFF_T%2147483629==721) &&
|
||||
(BIG_OFF_T%2147483647==1));
|
||||
return big_off ? 0 : 1;
|
||||
}
|
||||
" HAVE_LARGE_FILE_SUPPORT)
|
||||
|
||||
# Check if it makes sense to define _LARGE_FILES or _FILE_OFFSET_BITS
|
||||
if (HAVE_LARGE_FILE_SUPPORT)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set (_LARGE_FILE_EXTRA_SRC "
|
||||
#include <sys/types.h>
|
||||
int main (int argc, char **argv) {
|
||||
return sizeof(off_t) == 8 ? 0 : 1;
|
||||
}
|
||||
")
|
||||
CHECK_C_SOURCE_RUNS ("#define _LARGE_FILES\n${_LARGE_FILE_EXTRA_SRC}"
|
||||
HAVE_USEFUL_D_LARGE_FILES)
|
||||
if (NOT HAVE_USEFUL_D_LARGE_FILES)
|
||||
if (NOT DEFINED HAVE_USEFUL_D_FILE_OFFSET_BITS)
|
||||
set (SHOW_LARGE_FILE_WARNING TRUE)
|
||||
endif ()
|
||||
CHECK_C_SOURCE_RUNS ("#define _FILE_OFFSET_BITS 64\n${_LARGE_FILE_EXTRA_SRC}"
|
||||
HAVE_USEFUL_D_FILE_OFFSET_BITS)
|
||||
if (HAVE_USEFUL_D_FILE_OFFSET_BITS)
|
||||
set (_FILE_OFFSET_BITS 64 PARENT_SCOPE)
|
||||
elseif (SHOW_LARGE_FILE_WARNING)
|
||||
message (WARNING "No 64 bit file support through off_t available.")
|
||||
endif ()
|
||||
else ()
|
||||
set (_LARGE_FILES 1 PARENT_SCOPE)
|
||||
endif ()
|
||||
endfunction ()
|
||||
|
||||
|
||||
# Quick way to set some basic variables
|
||||
# FIXME add support for variable number of arguments: only package and version are mandatory
|
||||
# arguments are package version bug_report tarname url
|
||||
function (ac_init)
|
||||
set(package ${ARGV0})
|
||||
set(version ${ARGV1})
|
||||
set(bug_report ${ARGV2})
|
||||
set(tarname ${ARGV3})
|
||||
set(url ${ARGV4})
|
||||
set(PACKAGE_NAME "\"${package}\"" PARENT_SCOPE)
|
||||
set(PACKAGE_VERSION "\"${version}\"" PARENT_SCOPE)
|
||||
set(VERSION "\"${version}\"" PARENT_SCOPE)
|
||||
if(version)
|
||||
set(PACKAGE_STRING "\"${package} ${version}\"" PARENT_SCOPE)
|
||||
else()
|
||||
set(PACKAGE_STRING "\"${package}\"" PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
set(PACKAGE_BUGREPORT "\"${bug_report}\"" PARENT_SCOPE)
|
||||
|
||||
if(NOT tarname)
|
||||
string(REGEX REPLACE "[^a-zA-Z0-9_]" "-" tarname "${package}")
|
||||
endif()
|
||||
set(PACKAGE_TARNAME "\"${tarname}\"" PARENT_SCOPE)
|
||||
|
||||
set(PACKAGE_URL "\"${url}\"" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
|
||||
# Checks for the const keyword, defining "HAS_CONST_SUPPORT"
|
||||
# If it does not have support, defines "const" to 0 in the parent scope
|
||||
function (ac_c_const)
|
||||
CHECK_C_SOURCE_COMPILES(
|
||||
"int main(int argc, char **argv){const int r = 0;return r;}"
|
||||
HAS_CONST_SUPPORT)
|
||||
if (NOT HAS_CONST_SUPPORT)
|
||||
set(const 0 PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
|
||||
# Inline keyword support. Defines "inline" in the parent scope to the
|
||||
# compiler internal keyword for inline in C
|
||||
# TODO write a better test!
|
||||
function (ac_c_inline)
|
||||
if (MSVC)
|
||||
set (inline __inline)
|
||||
elseif(CMAKE_COMPILER_IS_GNUC)
|
||||
set (inline __inline__)
|
||||
endif()
|
||||
set(inline "${inline}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
|
||||
# Test if you can safely include both <sys/time.h> and <time.h>
|
||||
function (ac_header_time)
|
||||
CHECK_C_SOURCE_COMPILES(
|
||||
"#include <sys/time.h>\n#include <time.h>\nint main(int argc, char **argv) { return 0; }"
|
||||
TIME_WITH_SYS_TIME)
|
||||
set(TIME_WITH_SYS_TIME ${TIME_WITH_SYS_TIME} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
|
||||
# Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian
|
||||
# (Intel), setting "WORDS_BIGENDIAN" to 1 if big endian
|
||||
function (ac_c_bigendian)
|
||||
TEST_BIG_ENDIAN(HOST_BIGENDIAN)
|
||||
if (HOST_BIGENDIAN)
|
||||
set(WORDS_BIGENDIAN 1 PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
|
||||
# Check for off_t, setting "off_t" in the parent scope
|
||||
function(ac_type_off_t)
|
||||
CHECK_TYPE_SIZE("off_t" SIZEOF_OFF_T)
|
||||
if (NOT SIZEOF_OFF_T)
|
||||
set(off_t "long int")
|
||||
endif()
|
||||
set(off_t ${off_t} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
|
||||
# Check for size_t, setting "size_t" in the parent scope
|
||||
function(ac_type_size_t)
|
||||
CHECK_TYPE_SIZE("size_t" SIZEOF_SIZE_T)
|
||||
if (NOT SIZEOF_SIZE_T)
|
||||
set(size_t "unsigned int")
|
||||
endif()
|
||||
set(size_t ${size_t} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
|
||||
# Define "TM_IN_SYS_TIME" to 1 if <sys/time.h> declares "struct tm"
|
||||
function(ac_struct_tm)
|
||||
CHECK_C_SOURCE_COMPILES(
|
||||
"#include <sys/time.h>\nint main(int argc, char **argv) { struct tm x; return 0; }"
|
||||
TM_IN_SYS_TIME
|
||||
)
|
||||
if (TM_IN_SYS_TIME)
|
||||
set (TM_IN_SYS_TIME 1 PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
|
||||
# Obtain size of an 'type' and define as SIZEOF_TYPE
|
||||
function (ac_check_sizeof typename)
|
||||
string(TOUPPER "SIZEOF_${typename}" varname)
|
||||
string(REPLACE " " "_" varname "${varname}")
|
||||
string(REPLACE "*" "p" varname "${varname}")
|
||||
CHECK_TYPE_SIZE("${typename}" ${varname} BUILTIN_TYPES_ONLY)
|
||||
if(NOT ${varname})
|
||||
set(${varname} 0 PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
|
||||
# Check if the type exists, defines HAVE_<type>
|
||||
function (ac_check_type typename)
|
||||
string(TOUPPER "${typename}" varname)
|
||||
string(REPLACE " " "_" varname "${varname}")
|
||||
string(REPLACE "*" "p" varname "${varname}")
|
||||
CHECK_TYPE_SIZE("${typename}" ${varname})
|
||||
if (NOT "${varname}" STREQUAL "")
|
||||
set("HAVE_${varname}" 1 PARENT_SCOPE)
|
||||
set("${varname}" "${typename}" PARENT_SCOPE)
|
||||
else()
|
||||
set("${varname}" "unknown" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
|
||||
# Verifies if each type on the list exists, using the given prelude
|
||||
function (ac_check_types type_list prelude)
|
||||
foreach(typename ${type_list})
|
||||
string(TOUPPER "HAVE_${typename}" varname)
|
||||
string(REPLACE " " "_" varname "${varname}")
|
||||
string(REPLACE "*" "p" varname "${varname}")
|
||||
CHECK_C_SOURCE_COMPILES("${prelude}\n ${typename} foo;" ${varname})
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(ac_path_prog variable prog_to_check_for value_if_not_found env_var)
|
||||
find_program(${variable} NAMES ${prog_to_check_for} PATHS ENV ${env_var} NO_DEFAULT_PATH)
|
||||
if(NOT ${variable})
|
||||
message(STATUS "Looking for ${prog_to_check_for} - not found")
|
||||
set(${variable} ${value_if_not_fount} PARENT_SCOPE)
|
||||
else()
|
||||
message(STATUS "Looking for ${prog_to_check_for} - ${variable}")
|
||||
set(${variable} ${${variable}} PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# check if function func exists in library lib
|
||||
function(ac_check_lib lib func)
|
||||
string(TOUPPER "HAVE_${func}" varname)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${lib})
|
||||
check_function_exists(${func} ${varname})
|
||||
set(CMAKE_REQUIRED_LIBRARIES)
|
||||
endfunction()
|
||||
|
||||
# check if source compiles without linking
|
||||
function(ac_try_compile SOURCE VAR)
|
||||
set(CMAKE_TMP_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp)
|
||||
if(NOT DEFINED "${VAR}")
|
||||
file(WRITE
|
||||
"${CMAKE_TMP_DIR}/src.c"
|
||||
"${SOURCE}\n"
|
||||
)
|
||||
|
||||
if(NOT CMAKE_REQUIRED_QUIET)
|
||||
message(STATUS "Performing Test ${VAR}")
|
||||
endif()
|
||||
# Set up CMakeLists.txt for static library:
|
||||
file(WRITE
|
||||
${CMAKE_TMP_DIR}/CMakeLists.txt
|
||||
"add_library(compile STATIC src.c)"
|
||||
)
|
||||
|
||||
# Configure:
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
|
||||
WORKING_DIRECTORY ${CMAKE_TMP_DIR}
|
||||
)
|
||||
|
||||
# Build:
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_TMP_DIR}
|
||||
RESULT_VARIABLE RESVAR
|
||||
OUTPUT_VARIABLE OUTPUT
|
||||
ERROR_VARIABLE OUTPUT
|
||||
)
|
||||
|
||||
# Set up result:
|
||||
if(RESVAR EQUAL 0)
|
||||
set(${VAR} 1 CACHE INTERNAL "Test ${VAR}")
|
||||
if(NOT CMAKE_REQUIRED_QUIET)
|
||||
message(STATUS "Performing Test ${VAR} - Success")
|
||||
endif()
|
||||
|
||||
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
|
||||
"Performing C SOURCE FILE Test ${VAR} succeded with the following output:\n"
|
||||
"${OUTPUT}\n"
|
||||
"Source file was:\n${SOURCE}\n")
|
||||
else()
|
||||
if(NOT CMAKE_REQUIRED_QUIET)
|
||||
message(STATUS "Performing Test ${VAR} - Failed")
|
||||
endif()
|
||||
set(${VAR} "" CACHE INTERNAL "Test ${VAR}")
|
||||
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
|
||||
"Performing C SOURCE FILE Test ${VAR} failed with the following output:\n"
|
||||
"${OUTPUT}\n"
|
||||
"Source file was:\n${SOURCE}\n")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
64
cmake/modules/FindLibElf.cmake
Normal file
64
cmake/modules/FindLibElf.cmake
Normal file
@ -0,0 +1,64 @@
|
||||
# - Try to find libelf
|
||||
# Once done this will define
|
||||
#
|
||||
# LIBELF_FOUND - system has libelf
|
||||
# LIBELF_INCLUDE_DIRS - the libelf include directory
|
||||
# LIBELF_LIBRARIES - Link these to use libelf
|
||||
# LIBELF_DEFINITIONS - Compiler switches required for using libelf
|
||||
#
|
||||
# This module reads hints about search locations from variables:
|
||||
#
|
||||
# LIBELF_ROOT - Preferred installation prefix
|
||||
#
|
||||
# Copyright (c) 2008 Bernhard Walle <bernhard.walle@gmx.de>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
|
||||
if (LIBELF_LIBRARIES AND LIBELF_INCLUDE_DIRS)
|
||||
set (LibElf_FIND_QUIETLY TRUE)
|
||||
endif (LIBELF_LIBRARIES AND LIBELF_INCLUDE_DIRS)
|
||||
|
||||
find_path (LIBELF_INCLUDE_DIRS
|
||||
NAMES
|
||||
libelf/libelf.h libelf.h
|
||||
HINTS
|
||||
${LIBELF_ROOT}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
libelf/include
|
||||
)
|
||||
|
||||
find_library (LIBELF_LIBRARIES
|
||||
NAMES
|
||||
elf libelf
|
||||
HINTS
|
||||
${LIBELF_ROOT}
|
||||
PATH_SUFFIXES
|
||||
lib
|
||||
libelf/lib
|
||||
)
|
||||
|
||||
include (FindPackageHandleStandardArgs)
|
||||
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set LIBELF_FOUND to TRUE if all listed variables are TRUE
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibElf DEFAULT_MSG
|
||||
LIBELF_LIBRARIES
|
||||
LIBELF_INCLUDE_DIRS)
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES elf)
|
||||
include(CheckCXXSourceCompiles)
|
||||
check_cxx_source_compiles("#include <libelf.h>
|
||||
int main() {
|
||||
Elf *e = (Elf*)0;
|
||||
size_t sz;
|
||||
elf_getshdrstrndx(e, &sz);
|
||||
return 0;
|
||||
}" ELF_GETSHDRSTRNDX)
|
||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
||||
|
||||
mark_as_advanced(LIBELF_INCLUDE_DIRS LIBELF_LIBRARIES ELF_GETSHDRSTRNDX)
|
||||
@ -91,6 +91,8 @@ struct program_image_section {
|
||||
|
||||
struct get_cpu_set_arg {
|
||||
int nr_processes;
|
||||
char *req_cpu_list; // Requested by user-space
|
||||
int req_cpu_list_len; // Lenght of request string
|
||||
int *process_rank;
|
||||
pid_t ppid;
|
||||
void *cpu_set;
|
||||
|
||||
@ -620,6 +620,78 @@ static long mcexec_get_cpuset(ihk_os_t os, unsigned long arg)
|
||||
goto put_out;
|
||||
}
|
||||
|
||||
/* User requested CPU mask? */
|
||||
if (req.req_cpu_list && req.req_cpu_list_len) {
|
||||
char *cpu_list = NULL;
|
||||
|
||||
cpu_list = kmalloc(req.req_cpu_list_len, GFP_KERNEL);
|
||||
if (!cpu_list) {
|
||||
printk("%s: error: allocating CPU list\n", __FUNCTION__);
|
||||
ret = -ENOMEM;
|
||||
goto put_out;
|
||||
}
|
||||
|
||||
if (copy_from_user(cpu_list,
|
||||
req.req_cpu_list, req.req_cpu_list_len)) {
|
||||
printk("%s: error copying CPU list request\n", __FUNCTION__);
|
||||
kfree(cpu_list);
|
||||
ret = -EINVAL;
|
||||
goto put_out;
|
||||
}
|
||||
|
||||
cpus_used = kmalloc(sizeof(cpumask_t), GFP_KERNEL);
|
||||
cpus_to_use = kmalloc(sizeof(cpumask_t), GFP_KERNEL);
|
||||
if (!cpus_to_use || !cpus_used) {
|
||||
printk("%s: error: allocating CPU mask\n", __FUNCTION__);
|
||||
ret = -ENOMEM;
|
||||
kfree(cpu_list);
|
||||
goto put_out;
|
||||
}
|
||||
memset(cpus_used, 0, sizeof(cpumask_t));
|
||||
memset(cpus_to_use, 0, sizeof(cpumask_t));
|
||||
|
||||
/* Parse CPU list */
|
||||
if (cpulist_parse(cpu_list, cpus_to_use) < 0) {
|
||||
printk("%s: invalid CPUs requested: %s\n",
|
||||
__FUNCTION__, cpu_list);
|
||||
ret = -EINVAL;
|
||||
kfree(cpu_list);
|
||||
goto put_out;
|
||||
}
|
||||
|
||||
memcpy(cpus_used, cpus_to_use, sizeof(cpumask_t));
|
||||
|
||||
/* Copy mask to user-space */
|
||||
if (copy_to_user(req.cpu_set, cpus_used,
|
||||
(req.cpu_set_size < sizeof(cpumask_t) ?
|
||||
req.cpu_set_size : sizeof(cpumask_t)))) {
|
||||
printk("%s: error copying mask to user\n", __FUNCTION__);
|
||||
ret = -EINVAL;
|
||||
kfree(cpu_list);
|
||||
goto put_out;
|
||||
}
|
||||
|
||||
/* Copy IKC target core */
|
||||
cpu = cpumask_next(-1, cpus_used);
|
||||
if (copy_to_user(req.target_core, &cpu, sizeof(cpu))) {
|
||||
printk("%s: error copying target core to user\n",
|
||||
__FUNCTION__);
|
||||
ret = -EINVAL;
|
||||
kfree(cpu_list);
|
||||
goto put_out;
|
||||
}
|
||||
|
||||
/* Save in per-process structure */
|
||||
memcpy(&ppd->cpu_set, cpus_used, sizeof(cpumask_t));
|
||||
ppd->ikc_target_cpu = cpu;
|
||||
printk("%s: %s -> target McKernel CPU: %d\n",
|
||||
__func__, cpu_list, cpu);
|
||||
|
||||
ret = 0;
|
||||
kfree(cpu_list);
|
||||
goto put_out;
|
||||
}
|
||||
|
||||
mutex_lock(&udp->part_exec_lock);
|
||||
/* Find part_exec having same node_proxy */
|
||||
list_for_each_entry_reverse(pe_itr, &udp->part_exec_list, chain) {
|
||||
@ -1237,7 +1309,7 @@ int mcexec_syscall(struct mcctrl_usrdata *ud, struct ikc_scd_packet *packet)
|
||||
ppd = mcctrl_get_per_proc_data(ud, pid);
|
||||
|
||||
if (unlikely(!ppd)) {
|
||||
kprintf("%s: ERROR: no per-process structure for PID %d, "
|
||||
dprintk("%s: ERROR: no per-process structure for PID %d, "
|
||||
"syscall nr: %lu\n",
|
||||
__FUNCTION__, pid, packet->req.number);
|
||||
|
||||
@ -1452,7 +1524,7 @@ retry_alloc:
|
||||
__FUNCTION__, task_pid_vnr(current), packet->ref);
|
||||
|
||||
mb();
|
||||
if (!packet->req.valid) {
|
||||
if (!smp_load_acquire(&packet->req.valid)) {
|
||||
printk("%s: ERROR: stray wakeup pid: %d, tid: %d: SC %lu\n",
|
||||
__FUNCTION__,
|
||||
task_tgid_vnr(current),
|
||||
@ -1462,7 +1534,7 @@ retry_alloc:
|
||||
goto retry;
|
||||
}
|
||||
|
||||
packet->req.valid = 0; /* ack */
|
||||
smp_store_release(&packet->req.valid, 0); /* ack */
|
||||
dprintk("%s: system call: %d, args[0]: %lu, args[1]: %lu, args[2]: %lu, "
|
||||
"args[3]: %lu, args[4]: %lu, args[5]: %lu\n",
|
||||
__FUNCTION__,
|
||||
@ -3399,14 +3471,6 @@ long __mcctrl_control(ihk_os_t os, unsigned int req, unsigned long arg,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Per-CPU register manipulation functions */
|
||||
struct mcctrl_os_cpu_response {
|
||||
int done;
|
||||
unsigned long val;
|
||||
int err;
|
||||
wait_queue_head_t wq;
|
||||
};
|
||||
|
||||
int mcctrl_get_request_os_cpu(ihk_os_t os, int *ret_cpu)
|
||||
{
|
||||
struct mcctrl_usrdata *usrdata;
|
||||
@ -3470,31 +3534,14 @@ out_put_ppd:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mcctrl_os_read_write_cpu_response(ihk_os_t os,
|
||||
struct ikc_scd_packet *pisp)
|
||||
{
|
||||
struct mcctrl_os_cpu_response *resp;
|
||||
|
||||
/* XXX: What if caller thread is unblocked by a signal
|
||||
* before this message arrives? */
|
||||
resp = pisp->resp;
|
||||
if (!resp) {
|
||||
return;
|
||||
}
|
||||
|
||||
resp->val = pisp->desc.val;
|
||||
resp->done = 1;
|
||||
resp->err = pisp->err;
|
||||
wake_up_interruptible(&resp->wq);
|
||||
}
|
||||
|
||||
int __mcctrl_os_read_write_cpu_register(ihk_os_t os, int cpu,
|
||||
struct ihk_os_cpu_register *desc,
|
||||
enum mcctrl_os_cpu_operation op)
|
||||
{
|
||||
struct mcctrl_usrdata *udp = ihk_host_os_get_usrdata(os);
|
||||
struct ikc_scd_packet isp;
|
||||
struct mcctrl_os_cpu_response resp;
|
||||
struct ihk_os_cpu_register *ldesc = NULL;
|
||||
int do_free = 0;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!udp) {
|
||||
@ -3511,50 +3558,43 @@ int __mcctrl_os_read_write_cpu_register(ihk_os_t os, int cpu,
|
||||
|
||||
}
|
||||
|
||||
/* Keep a dynamic structure around that can
|
||||
* survive an early return due to a signal */
|
||||
ldesc = kmalloc(sizeof(*ldesc), GFP_KERNEL);
|
||||
if (!ldesc) {
|
||||
printk("%s: ERROR: allocating cpu register desc\n", __FUNCTION__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
*ldesc = *desc;
|
||||
|
||||
memset(&isp, '\0', sizeof(struct ikc_scd_packet));
|
||||
isp.msg = SCD_MSG_CPU_RW_REG;
|
||||
isp.op = op;
|
||||
isp.desc = *desc;
|
||||
isp.resp = &resp;
|
||||
isp.pdesc = virt_to_phys(ldesc);
|
||||
|
||||
resp.done = 0;
|
||||
resp.err = 0;
|
||||
init_waitqueue_head(&resp.wq);
|
||||
|
||||
mb();
|
||||
ret = mcctrl_ikc_send(os, cpu, &isp);
|
||||
if (ret < 0) {
|
||||
ret = mcctrl_ikc_send_wait(os, cpu, &isp, 0, NULL, &do_free, 1, ldesc);
|
||||
if (ret != 0) {
|
||||
printk("%s: ERROR sending IKC msg: %d\n", __FUNCTION__, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Wait for response */
|
||||
ret = wait_event_interruptible(resp.wq, resp.done);
|
||||
if (ret < 0) {
|
||||
printk("%s: ERROR after wait: %d\n", __FUNCTION__, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = resp.err;
|
||||
if (ret != 0) {
|
||||
printk("%s: ERROR receive: %d\n", __FUNCTION__, resp.err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Update if read */
|
||||
if (ret == 0 && op == MCCTRL_OS_CPU_READ_REGISTER) {
|
||||
desc->val = resp.val;
|
||||
if (op == MCCTRL_OS_CPU_READ_REGISTER) {
|
||||
desc->val = ldesc->val;
|
||||
}
|
||||
|
||||
/* Notify caller (for future async implementation) */
|
||||
atomic_set(&desc->sync, 1);
|
||||
|
||||
dprintk("%s: MCCTRL_OS_CPU_%s_REGISTER: reg: 0x%lx, val: 0x%lx\n",
|
||||
dprintk("%s: MCCTRL_OS_CPU_%s_REGISTER: CPU: %d, addr_ext: 0x%lx, val: 0x%lx\n",
|
||||
__FUNCTION__,
|
||||
(op == MCCTRL_OS_CPU_READ_REGISTER ? "READ" : "WRITE"),
|
||||
desc->addr, desc->val);
|
||||
(op == MCCTRL_OS_CPU_READ_REGISTER ? "READ" : "WRITE"), cpu,
|
||||
desc->addr_ext, desc->val);
|
||||
|
||||
out:
|
||||
if (do_free) {
|
||||
kfree(ldesc);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -209,6 +209,7 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c,
|
||||
case SCD_MSG_SEND_SIGNAL_ACK:
|
||||
case SCD_MSG_PROCFS_ANSWER:
|
||||
case SCD_MSG_REMOTE_PAGE_FAULT_ANSWER:
|
||||
case SCD_MSG_CPU_RW_REG_RESP:
|
||||
mcctrl_wakeup_cb(__os, pisp);
|
||||
break;
|
||||
|
||||
@ -239,10 +240,6 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c,
|
||||
get_vdso_info(__os, pisp->arg);
|
||||
break;
|
||||
|
||||
case SCD_MSG_CPU_RW_REG_RESP:
|
||||
mcctrl_os_read_write_cpu_response(__os, pisp);
|
||||
break;
|
||||
|
||||
case SCD_MSG_EVENTFD:
|
||||
dkprintf("%s: SCD_MSG_EVENTFD,pisp->eventfd_type=%d\n", __FUNCTION__, pisp->eventfd_type);
|
||||
mcctrl_eventfd(__os, pisp);
|
||||
@ -465,7 +462,7 @@ int prepare_ikc_channels(ihk_os_t os)
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
usrdata = kzalloc(sizeof(struct mcctrl_usrdata), GFP_KERNEL);
|
||||
usrdata = kzalloc(sizeof(struct mcctrl_usrdata), GFP_ATOMIC);
|
||||
if (!usrdata) {
|
||||
printk("%s: error: allocating mcctrl_usrdata\n", __FUNCTION__);
|
||||
ret = -ENOMEM;
|
||||
@ -491,7 +488,7 @@ int prepare_ikc_channels(ihk_os_t os)
|
||||
usrdata->num_channels = usrdata->cpu_info->n_cpus;
|
||||
usrdata->channels = kzalloc(sizeof(struct mcctrl_channel) *
|
||||
usrdata->num_channels,
|
||||
GFP_KERNEL);
|
||||
GFP_ATOMIC);
|
||||
|
||||
if (!usrdata->channels) {
|
||||
printk("Error: cannot allocate channels.\n");
|
||||
@ -500,7 +497,7 @@ int prepare_ikc_channels(ihk_os_t os)
|
||||
}
|
||||
|
||||
usrdata->ikc2linux = kzalloc(sizeof(struct ihk_ikc_channel_desc *) *
|
||||
nr_cpu_ids, GFP_KERNEL);
|
||||
nr_cpu_ids, GFP_ATOMIC);
|
||||
|
||||
if (!usrdata->ikc2linux) {
|
||||
printk("Error: cannot allocate ikc2linux channels.\n");
|
||||
|
||||
@ -154,7 +154,7 @@ struct ikc_scd_packet {
|
||||
|
||||
/* SCD_MSG_CPU_RW_REG */
|
||||
struct {
|
||||
struct ihk_os_cpu_register desc;
|
||||
unsigned long pdesc; /* Physical addr of the descriptor */
|
||||
enum mcctrl_os_cpu_operation op;
|
||||
void *resp;
|
||||
};
|
||||
@ -298,7 +298,6 @@ struct mcctrl_cpu_topology {
|
||||
//struct mcctrl_usrdata *udp;
|
||||
struct ihk_cpu_topology *saved;
|
||||
int mckernel_cpu_id;
|
||||
int mckernel_core_id;
|
||||
cpumask_t core_siblings;
|
||||
cpumask_t thread_siblings;
|
||||
|
||||
|
||||
@ -1130,7 +1130,6 @@ static const struct procfs_entry base_entry_stuff[] = {
|
||||
// PROC_REG("cpuinfo", S_IRUGO, NULL),
|
||||
#endif /* POSTK_DEBUG_ARCH_DEP_42 */
|
||||
// PROC_REG("meminfo", S_IRUGO, NULL),
|
||||
PROC_REG("meminfo", S_IRUGO, &mckernel_buff_io),
|
||||
// PROC_REG("pagetypeinfo",S_IRUGO, NULL),
|
||||
// PROC_REG("softirq", S_IRUGO, NULL),
|
||||
PROC_REG("stat", 0444, &mckernel_buff_io),
|
||||
|
||||
@ -228,18 +228,19 @@ static int __notify_syscall_requester(ihk_os_t os, struct ikc_scd_packet *packet
|
||||
c = (usrdata->channels + packet->ref)->c;
|
||||
|
||||
/* If spinning, no need for IKC message */
|
||||
if (__sync_bool_compare_and_swap(&res->req_thread_status,
|
||||
if (cmpxchg(&res->req_thread_status,
|
||||
IHK_SCD_REQ_THREAD_SPINNING,
|
||||
IHK_SCD_REQ_THREAD_TO_BE_WOKEN)) {
|
||||
IHK_SCD_REQ_THREAD_TO_BE_WOKEN) ==
|
||||
IHK_SCD_REQ_THREAD_SPINNING) {
|
||||
dprintk("%s: no need to send IKC message for PID %d\n",
|
||||
__FUNCTION__, packet->pid);
|
||||
__FUNCTION__, packet->pid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Wait until the status goes back to IHK_SCD_REQ_THREAD_SPINNING or
|
||||
IHK_SCD_REQ_THREAD_DESCHEDULED because two wake-up attempts are competing.
|
||||
Note that mcexec_terminate_thread() and returning EINTR would compete. */
|
||||
if (res->req_thread_status == IHK_SCD_REQ_THREAD_TO_BE_WOKEN) {
|
||||
if (smp_load_acquire(&res->req_thread_status) == IHK_SCD_REQ_THREAD_TO_BE_WOKEN) {
|
||||
printk("%s: INFO: someone else is waking up the McKernel thread, "
|
||||
"pid: %d, req status: %lu, syscall nr: %lu\n",
|
||||
__FUNCTION__, packet->pid,
|
||||
@ -247,9 +248,10 @@ static int __notify_syscall_requester(ihk_os_t os, struct ikc_scd_packet *packet
|
||||
}
|
||||
|
||||
/* The thread is not spinning any more, make sure it's descheduled */
|
||||
if (!__sync_bool_compare_and_swap(&res->req_thread_status,
|
||||
if (cmpxchg(&res->req_thread_status,
|
||||
IHK_SCD_REQ_THREAD_DESCHEDULED,
|
||||
IHK_SCD_REQ_THREAD_TO_BE_WOKEN)) {
|
||||
IHK_SCD_REQ_THREAD_TO_BE_WOKEN) !=
|
||||
IHK_SCD_REQ_THREAD_DESCHEDULED) {
|
||||
printk("%s: WARNING: inconsistent requester status, "
|
||||
"pid: %d, req status: %lu, syscall nr: %lu\n",
|
||||
__FUNCTION__, packet->pid,
|
||||
@ -537,7 +539,11 @@ retry_alloc:
|
||||
#define USE_VM_INSERT_PFN 1
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
|
||||
#if defined(RHEL_RELEASE_CODE) && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(8, 2)
|
||||
static vm_fault_t rus_vm_fault(struct vm_fault *vmf)
|
||||
#else
|
||||
static int rus_vm_fault(struct vm_fault *vmf)
|
||||
#endif
|
||||
{
|
||||
struct vm_area_struct *vma = vmf->vma;
|
||||
#else
|
||||
@ -970,6 +976,30 @@ static int pager_req_create(ihk_os_t os, int fd, uintptr_t result_pa)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Shared memory hack */
|
||||
{
|
||||
char *pathbuf, *fullpath;
|
||||
pathbuf = kmalloc(PATH_MAX, GFP_ATOMIC);
|
||||
if (pathbuf) {
|
||||
fullpath = d_path(&file->f_path, pathbuf, PATH_MAX);
|
||||
if (!IS_ERR(fullpath)) {
|
||||
if (!strncmp("/tmp/ompi.", fullpath, 10) ||
|
||||
!strncmp("/dev/shm/", fullpath, 9) ||
|
||||
(!strncmp("/var/opt/FJSVtcs/ple/daemonif/",
|
||||
fullpath, 30) && !strstr(fullpath, "dstore_sm.lock"))) {
|
||||
printk("%s: treating %s as a device file..\n",
|
||||
__func__, fullpath);
|
||||
kfree(pathbuf);
|
||||
|
||||
error = -ESRCH;
|
||||
goto out;
|
||||
}
|
||||
|
||||
kfree(pathbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inode = file->f_path.dentry->d_inode;
|
||||
if (!inode) {
|
||||
error = -EBADF;
|
||||
@ -1029,7 +1059,7 @@ static int pager_req_create(ihk_os_t os, int fd, uintptr_t result_pa)
|
||||
pager = newpager;
|
||||
newpager = NULL;
|
||||
|
||||
/* Intel MPI library and shared memory "prefetch" */
|
||||
/* Shared libraries prefetch */
|
||||
{
|
||||
char *pathbuf, *fullpath;
|
||||
|
||||
@ -1037,15 +1067,7 @@ static int pager_req_create(ihk_os_t os, int fd, uintptr_t result_pa)
|
||||
if (pathbuf) {
|
||||
fullpath = d_path(&file->f_path, pathbuf, PATH_MAX);
|
||||
if (!IS_ERR(fullpath)) {
|
||||
if (!strncmp("/dev/shm/Intel_MPI", fullpath, 18)) {
|
||||
mf_flags = (MF_PREMAP | MF_ZEROFILL);
|
||||
dprintk("%s: filename: %s, premap & zerofill\n",
|
||||
__FUNCTION__, fullpath);
|
||||
}
|
||||
else if (strstr(fullpath, "libmpi") ||
|
||||
strstr(fullpath, "libiomp") ||
|
||||
strstr(fullpath, "libpthread") ||
|
||||
strstr(fullpath, "libc.so")) {
|
||||
if (strstr(fullpath, ".so")) {
|
||||
mf_flags = MF_PREFETCH;
|
||||
dprintk("%s: filename: %s, prefetch\n",
|
||||
__FUNCTION__, fullpath);
|
||||
@ -1417,6 +1439,26 @@ static int pager_req_map(ihk_os_t os, int fd, size_t len, off_t off,
|
||||
#define ANY_WHERE 0
|
||||
if (prot_and_flags & MAP_LOCKED) prot_and_flags |= MAP_POPULATE;
|
||||
|
||||
/* Shared memory hack */
|
||||
{
|
||||
char *pathbuf, *fullpath;
|
||||
pathbuf = kmalloc(PATH_MAX, GFP_ATOMIC);
|
||||
if (pathbuf) {
|
||||
fullpath = d_path(&file->f_path, pathbuf, PATH_MAX);
|
||||
if (!IS_ERR(fullpath)) {
|
||||
if (!strncmp("/tmp/ompi.", fullpath, 10) ||
|
||||
!strncmp("/dev/shm/", fullpath, 9) ||
|
||||
!strncmp("/var/opt/FJSVtcs/ple/daemonif/",
|
||||
fullpath, 30)) {
|
||||
dprintk("%s: pre-populating %s..\n",
|
||||
__func__, fullpath);
|
||||
prot_and_flags |= MAP_POPULATE;
|
||||
}
|
||||
kfree(pathbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
|
||||
down_write(¤t->mm->mmap_sem);
|
||||
|
||||
@ -1430,7 +1472,12 @@ static int pager_req_map(ihk_os_t os, int fd, size_t len, off_t off,
|
||||
#endif
|
||||
|
||||
if (IS_ERR_VALUE(va)) {
|
||||
printk("pager_req_map(%p,%d,%lx,%lx,%lx):do_mmap_pgoff failed. %d\n", os, fd, len, off, result_rpa, (int)va);
|
||||
if ((int)va != -ENOTSUPP) {
|
||||
pr_err("%s(%p,%d,%lx,%lx,%lx): "
|
||||
"do_mmap_pgoff failed. %d\n",
|
||||
__func__, os, fd, len, off, result_rpa,
|
||||
(int)va);
|
||||
}
|
||||
error = va;
|
||||
goto out;
|
||||
}
|
||||
@ -1579,10 +1626,27 @@ retry:
|
||||
#else
|
||||
fault = handle_mm_fault(current->mm, vma, va, flags);
|
||||
#endif
|
||||
#ifdef SC_DEBUG
|
||||
if (fault != 0) {
|
||||
printk("%s: error: faulting %lx at off: %lu\n",
|
||||
__FUNCTION__, va, off);
|
||||
char *pathbuf = NULL;
|
||||
char *fullpath;
|
||||
|
||||
if (vma->vm_file) {
|
||||
pathbuf = kmalloc(PATH_MAX, GFP_ATOMIC);
|
||||
if (pathbuf) {
|
||||
fullpath = d_path(&vma->vm_file->f_path,
|
||||
pathbuf, PATH_MAX);
|
||||
if (!IS_ERR(fullpath)) {
|
||||
printk("%s: WARNING: couldn't fault 0x%lx"
|
||||
" at off: %lu in %s\n",
|
||||
__FUNCTION__, va, off, fullpath);
|
||||
}
|
||||
|
||||
kfree(pathbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
page_fault_attempted = 1;
|
||||
goto retry;
|
||||
|
||||
@ -12,7 +12,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/hashtable.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/version.h>
|
||||
@ -24,14 +23,6 @@
|
||||
#define wprintk(...) do { if (1) printk(KERN_WARNING __VA_ARGS__); } while (0)
|
||||
#define eprintk(...) do { if (1) printk(KERN_ERR __VA_ARGS__); } while (0)
|
||||
|
||||
struct physical_core_id {
|
||||
int linux_core_id;
|
||||
int mckernel_core_id;
|
||||
struct hlist_node next;
|
||||
};
|
||||
|
||||
DEFINE_HASHTABLE(physical_core_id_map, 10);
|
||||
|
||||
static ssize_t
|
||||
show_int(struct sysfsm_ops *ops, void *instance, void *buf, size_t size)
|
||||
{
|
||||
@ -197,9 +188,6 @@ static void free_cpu_topology(struct mcctrl_usrdata *udp)
|
||||
void free_topology_info(ihk_os_t os)
|
||||
{
|
||||
struct mcctrl_usrdata *udp = ihk_host_os_get_usrdata(os);
|
||||
int bkt;
|
||||
struct hlist_node *tmp;
|
||||
struct physical_core_id *cur;
|
||||
|
||||
if (!udp) {
|
||||
pr_warn("%s: warning: mcctrl_usrdata not found\n", __func__);
|
||||
@ -209,11 +197,6 @@ void free_topology_info(ihk_os_t os)
|
||||
free_node_topology(udp);
|
||||
free_cpu_topology(udp);
|
||||
|
||||
hash_for_each_safe(physical_core_id_map, bkt, tmp, cur, next) {
|
||||
hash_del(&cur->next);
|
||||
kfree(cur);
|
||||
}
|
||||
|
||||
return;
|
||||
} /* free_topology_info() */
|
||||
|
||||
@ -365,11 +348,6 @@ static struct mcctrl_cpu_topology *get_one_cpu_topology(struct mcctrl_usrdata *u
|
||||
struct mcctrl_cpu_topology *topology = NULL;
|
||||
struct cache_topology *cache;
|
||||
struct ihk_cache_topology *saved_cache;
|
||||
int linux_core_id;
|
||||
int mckernel_core_id;
|
||||
struct physical_core_id *entry;
|
||||
struct physical_core_id *cur;
|
||||
static int nr_mckernel_core;
|
||||
|
||||
dprintk("get_one_cpu_topology(%p,%d)\n", udp, index);
|
||||
topology = kmalloc(sizeof(*topology), GFP_KERNEL);
|
||||
@ -413,22 +391,6 @@ static struct mcctrl_cpu_topology *get_one_cpu_topology(struct mcctrl_usrdata *u
|
||||
goto out;
|
||||
}
|
||||
|
||||
linux_core_id = topology->saved->core_id;
|
||||
mckernel_core_id = -1;
|
||||
hash_for_each_possible(physical_core_id_map, cur, next, linux_core_id) {
|
||||
mckernel_core_id = cur->mckernel_core_id;
|
||||
break;
|
||||
}
|
||||
if (mckernel_core_id < 0) {
|
||||
mckernel_core_id = nr_mckernel_core++;
|
||||
entry = kmalloc(sizeof(struct physical_core_id), GFP_KERNEL);
|
||||
entry->linux_core_id = linux_core_id;
|
||||
entry->mckernel_core_id = mckernel_core_id;
|
||||
hash_add(physical_core_id_map,
|
||||
&entry->next, entry->linux_core_id);
|
||||
}
|
||||
topology->mckernel_core_id = mckernel_core_id;
|
||||
|
||||
list_for_each_entry(saved_cache,
|
||||
&topology->saved->cache_topology_list, chain) {
|
||||
cache = get_cache_topology(udp, topology, saved_cache);
|
||||
@ -550,7 +512,7 @@ static void setup_cpu_sysfs_files(struct mcctrl_usrdata *udp,
|
||||
"%s/cpu%d/topology/physical_package_id",
|
||||
prefix, cpu_number);
|
||||
sysfsm_createf(udp->os, SYSFS_SNOOPING_OPS_d32,
|
||||
&cpu->mckernel_core_id, 0444,
|
||||
&cpu->saved->core_id, 0444,
|
||||
"%s/cpu%d/topology/core_id",
|
||||
prefix, cpu_number);
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ include_directories(
|
||||
"${PROJECT_BINARY_DIR}/ihk/linux/include"
|
||||
)
|
||||
|
||||
|
||||
add_subdirectory(lib)
|
||||
add_library(libmcexec STATIC arch/${ARCH}/archdep.S)
|
||||
SET_TARGET_PROPERTIES(libmcexec PROPERTIES OUTPUT_NAME mcexec)
|
||||
set_property(TARGET libmcexec PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
@ -20,6 +20,18 @@ target_include_directories(mcexec PUBLIC "${KERNEL_DIR}")
|
||||
set_property(TARGET mcexec PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
set_property(TARGET mcexec PROPERTY LINK_FLAGS "-fPIE -pie")
|
||||
|
||||
add_executable(mcinspect mcinspect.c)
|
||||
if (NOT LIBDWARF)
|
||||
target_include_directories(mcinspect PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/lib/")
|
||||
target_include_directories(mcinspect PRIVATE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/lib/libdwarf/libdwarf/libdwarf/")
|
||||
target_link_libraries(mcinspect dwarf z elf)
|
||||
else()
|
||||
target_include_directories(mcinspect PRIVATE ${DWARF_H})
|
||||
target_link_libraries(mcinspect ${LIBDWARF})
|
||||
endif()
|
||||
target_link_libraries(mcinspect ${LIBBFD})
|
||||
|
||||
add_executable(eclair eclair.c arch/${ARCH}/arch-eclair.c)
|
||||
target_link_libraries(eclair ${LIBBFD})
|
||||
|
||||
@ -74,10 +86,13 @@ add_library(ldump2mcdump SHARED ldump2mcdump.c)
|
||||
configure_file(vmcore2mckdump.in vmcore2mckdump @ONLY)
|
||||
|
||||
configure_file(mcexec.1in mcexec.1 @ONLY)
|
||||
configure_file(mcps.in mcps @ONLY)
|
||||
|
||||
install(TARGETS mcexec eclair
|
||||
install(TARGETS mcexec eclair mcinspect
|
||||
DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/vmcore2mckdump"
|
||||
install(PROGRAMS
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/vmcore2mckdump"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/mcps"
|
||||
DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
install(TARGETS sched_yield ldump2mcdump
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
|
||||
3
executer/user/lib/CMakeLists.txt
Normal file
3
executer/user/lib/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
if (NOT LIBDWARF)
|
||||
add_subdirectory(libdwarf)
|
||||
endif()
|
||||
144
executer/user/lib/libdwarf/CMakeLists.txt
Normal file
144
executer/user/lib/libdwarf/CMakeLists.txt
Normal file
@ -0,0 +1,144 @@
|
||||
if (NOT LIBDWARF)
|
||||
# view folders on supported IDEs
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
# used when finding libelf
|
||||
set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS TRUE)
|
||||
|
||||
find_package(LibElf REQUIRED)
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES ${LIBELF_INCLUDE_DIRS})
|
||||
include(AutoconfHelper)
|
||||
|
||||
ac_init()
|
||||
ac_c_bigendian()
|
||||
ac_check_headers(sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h inttypes.h stdint.h unistd.h)
|
||||
ac_check_headers(alloca.h elf.h elfaccess.h libelf.h libelf/libelf.h sys/types.h sys/elf_386.h sys/elf_amd64.h sys/elf_sparc.h sys/ia64/elf.h)
|
||||
|
||||
# The default libdwarf is the one with struct Elf
|
||||
message(STATUS "Assuming struct Elf for the default libdwarf.h")
|
||||
|
||||
# Find out where the elf header is.
|
||||
if(HAVE_ELF_H)
|
||||
set(HAVE_LOCATION_OF_LIBELFHEADER "<elf.h>")
|
||||
elseif(HAVE_LIBELF_H)
|
||||
set(HAVE_LOCATION_OF_LIBELFHEADER "<libelf.h>")
|
||||
elseif(HAVE_LIBELF_LIBELF_H)
|
||||
set(HAVE_LOCATION_OF_LIBELFHEADER "<libelf/libelf.h>")
|
||||
endif()
|
||||
|
||||
ac_check_lib(${LIBELF_LIBRARIES} elf64_getehdr)
|
||||
ac_check_lib(${LIBELF_LIBRARIES} elf64_getshdr)
|
||||
|
||||
ac_try_compile("
|
||||
int main()
|
||||
{
|
||||
__uint32_t p;
|
||||
p = 3;
|
||||
return 0;
|
||||
}"
|
||||
HAVE___UINT32_T)
|
||||
|
||||
ac_try_compile("
|
||||
int main()
|
||||
{
|
||||
__uint64_t p;
|
||||
p = 3;
|
||||
return 0;
|
||||
}"
|
||||
HAVE___UINT64_T)
|
||||
|
||||
ac_try_compile("
|
||||
#include <sys/types.h>
|
||||
int main()
|
||||
{
|
||||
__uint32_t p;
|
||||
p = 3;
|
||||
return 0;
|
||||
}"
|
||||
HAVE___UINT32_T_IN_SYS_TYPES_H)
|
||||
|
||||
ac_try_compile("
|
||||
#include <sys/types.h>
|
||||
int main()
|
||||
{
|
||||
__uint64_t p;
|
||||
p = 3;
|
||||
return 0;
|
||||
}"
|
||||
HAVE___UINT64_T_IN_SYS_TYPES_H)
|
||||
|
||||
check_c_source_runs("
|
||||
static unsigned foo( unsigned x, __attribute__ ((unused)) int y)
|
||||
{
|
||||
unsigned x2 = x + 1;
|
||||
return x2;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
unsigned y = 0;
|
||||
y = foo(12,y);
|
||||
return 0;
|
||||
}"
|
||||
HAVE_UNUSED_ATTRIBUTE)
|
||||
|
||||
message(STATUS "Checking compiler supports __attribute__ unused... ${HAVE_UNUSED_ATTRIBUTE}")
|
||||
|
||||
ac_try_compile("
|
||||
#include <zlib.h>
|
||||
int main()
|
||||
{
|
||||
Bytef dest[100];
|
||||
uLongf destlen = 100;
|
||||
Bytef *src = 0;
|
||||
uLong srclen = 3;
|
||||
int res = uncompress(dest,&destlen,src,srclen);
|
||||
if (res == Z_OK) {
|
||||
/* ALL IS WELL */
|
||||
}
|
||||
return 0;
|
||||
}"
|
||||
HAVE_ZLIB)
|
||||
message(STATUS "Checking zlib.h usability... ${HAVE_ZLIB}")
|
||||
set(dwfzlib $<$<BOOL:${HAVE_ZIB}>:"z")
|
||||
|
||||
configure_file(libdwarf/libdwarf/libdwarf.h.in libdwarf.h COPYONLY)
|
||||
configure_file(libdwarf/libdwarf/config.h.in.cmake config.h)
|
||||
set(DWARF_CONFIGURATION_FILES ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
|
||||
set(DWARF_SOURCES dwarf_abbrev.c dwarf_alloc.c dwarf_arange.c dwarf_die_deliv.c dwarf_dnames.c dwarf_dsc.c dwarf_elf_access.c dwarf_error.c
|
||||
dwarf_form.c dwarf_frame.c dwarf_frame2.c dwarf_funcs.c dwarf_gdbindex.c dwarf_global.c dwarf_groups.c dwarf_harmless.c dwarf_init_finish.c dwarf_leb.c
|
||||
dwarf_line.c dwarf_loc.c dwarf_macro.c dwarf_macro5.c dwarf_original_elf_init.c dwarf_pubtypes.c dwarf_query.c dwarf_ranges.c dwarf_string.c dwarf_tied.c
|
||||
dwarf_str_offsets.c
|
||||
dwarf_tsearchhash.c dwarf_types.c dwarf_util.c dwarf_vars.c dwarf_weaks.c dwarf_xu_index.c dwarf_print_lines.c malloc_check.c pro_alloc.c pro_arange.c
|
||||
pro_die.c pro_encode_nm.c pro_error.c pro_expr.c pro_finish.c pro_forms.c pro_funcs.c pro_frame.c pro_init.c pro_line.c pro_reloc.c pro_reloc_stream.c
|
||||
pro_reloc_symbolic.c pro_pubnames.c pro_section.c pro_types.c pro_vars.c pro_macinfo.c pro_weaks.c)
|
||||
|
||||
set(DWARF_HEADERS dwarf.h dwarf_abbrev.h dwarf_alloc.h dwarf_arange.h dwarf_base_types.h dwarf_die_deliv.h dwarf_dnames.h dwarf_dsc.h
|
||||
dwarf_elf_access.h dwarf_error.h dwarf_frame.h dwarf_funcs.h dwarf_gdbindex.h dwarf_global.h dwarf_harmless.h dwarf_incl.h dwarf_line.h dwarf_loc.h
|
||||
dwarf_macro.h dwarf_macro5.h dwarf_opaque.h dwarf_reloc_arm.h dwarf_reloc_mips.h dwarf_reloc_ppc.h dwarf_reloc_ppc64.h dwarf_reloc_x86_64.h dwarf_tsearch.h
|
||||
dwarf_str_offsets.h
|
||||
dwarf_types.h dwarf_util.h dwarf_vars.h dwarf_weaks.h dwarf_xu_index.h dwgetopt.h libdwarfdefs.h malloc_check.h pro_alloc.h pro_arange.h pro_die.h
|
||||
pro_encode_nm.h pro_error.h pro_expr.h pro_frame.h pro_incl.h pro_line.h pro_macinfo.h pro_opaque.h pro_reloc.h pro_reloc_stream.h pro_reloc_symbolic.h
|
||||
pro_section.h pro_types.h pro_util.h)
|
||||
|
||||
SET(__SRCS "")
|
||||
FOREACH(f ${DWARF_SOURCES})
|
||||
LIST(APPEND __SRCS "libdwarf/libdwarf/${f}")
|
||||
ENDFOREACH(f)
|
||||
SET(DWARF_SOURCES ${__SRCS})
|
||||
|
||||
set(GENNAMES_SOURCES
|
||||
libdwarf/libdwarf/gennames.c
|
||||
libdwarf/libdwarf/dwgetopt.c
|
||||
libdwarf/libdwarf/dwarf.h)
|
||||
add_executable(gennames ${GENNAMES_SOURCES})
|
||||
set(GENNAMES_OUTPUT dwarf_names.c dwarf_names.h dwarf_names_enum.h dwarf_names_new.h)
|
||||
|
||||
add_custom_command(OUTPUT ${GENNAMES_OUTPUT}
|
||||
COMMAND gennames -s -i ${CMAKE_CURRENT_SOURCE_DIR}/libdwarf/libdwarf/ -o .
|
||||
DEPENDS gennames libdwarf/libdwarf/libdwarf.h.in)
|
||||
|
||||
add_library(dwarf STATIC ${DWARF_SOURCES} ${GENNAMES_OUTPUT} ${DWARF_CONFIGURATION_FILES})
|
||||
target_include_directories(dwarf PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/libdwarf/libdwarf/")
|
||||
target_include_directories(dwarf BEFORE PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endif()
|
||||
1
executer/user/lib/libdwarf/libdwarf
Submodule
1
executer/user/lib/libdwarf/libdwarf
Submodule
Submodule executer/user/lib/libdwarf/libdwarf added at ab9230b2b8
@ -1,6 +1,7 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <dlfcn.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sched.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
@ -27,3 +28,110 @@ int sched_yield(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef pthread_create
|
||||
|
||||
typedef int (*__pthread_create_fn)(pthread_t *thread,
|
||||
const pthread_attr_t *attr,
|
||||
void *(*start_routine) (void *),
|
||||
void *arg);
|
||||
|
||||
static __pthread_create_fn orig_pthread_create = 0;
|
||||
|
||||
|
||||
int pthread_create(pthread_t *thread,
|
||||
const pthread_attr_t *attr,
|
||||
void *(*start_routine) (void *),
|
||||
void *arg)
|
||||
{
|
||||
if (!orig_pthread_create) {
|
||||
orig_pthread_create =
|
||||
(__pthread_create_fn)dlsym(RTLD_NEXT, "pthread_create");
|
||||
}
|
||||
|
||||
/* CLONE_VM and newsp == parent_tidptr impiles pthread start routine addr */
|
||||
syscall(__NR_clone, CLONE_VM, start_routine, start_routine, 0, 0, 0);
|
||||
|
||||
return orig_pthread_create(thread, attr, start_routine, arg);
|
||||
}
|
||||
|
||||
#if 0
|
||||
#define PROCMAPS_MAX_LEN 131072
|
||||
|
||||
char *addr_to_lib(void *addr, unsigned long *offset_in_lib)
|
||||
{
|
||||
char maps_path[PATH_MAX];
|
||||
char buf[PROCMAPS_MAX_LEN];
|
||||
int fd;
|
||||
void *start, *end;
|
||||
char perms[4];
|
||||
unsigned long offset;
|
||||
unsigned long dev[2];
|
||||
int inode;
|
||||
char path[PATH_MAX];
|
||||
char *line;
|
||||
|
||||
sprintf(maps_path,"/proc/self/maps");
|
||||
fd = open(maps_path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr,"error: cannot open the memory maps, %s\n",
|
||||
strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(buf, 0, PROCMAPS_MAX_LEN);
|
||||
read(fd, buf, PROCMAPS_MAX_LEN);
|
||||
line = strtok(buf, "\n");
|
||||
while (line) {
|
||||
memset(path, 0, sizeof(path));
|
||||
sscanf(line, "%012lx-%012lx %4s %lx %lx:%lx %d\t\t\t%[^\n]",
|
||||
&start, &end, perms, &offset, &dev[0], &dev[1], &inode, path);
|
||||
|
||||
if (start <= addr && end > addr) {
|
||||
close(fd);
|
||||
if (offset_in_lib)
|
||||
*offset_in_lib = (unsigned long)(addr - start);
|
||||
return strlen(path) > 0 ? strdup(path) : NULL;
|
||||
}
|
||||
|
||||
line = strtok(NULL, "\n");
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int pthread_create(pthread_t *thread,
|
||||
const pthread_attr_t *attr,
|
||||
void *(*start_routine) (void *),
|
||||
void *arg)
|
||||
{
|
||||
char *lib = NULL;
|
||||
int util_thread = 1;
|
||||
unsigned long offset;
|
||||
|
||||
if (!orig_pthread_create) {
|
||||
orig_pthread_create =
|
||||
(__pthread_create_fn)dlsym(RTLD_NEXT, "pthread_create");
|
||||
}
|
||||
|
||||
lib = addr_to_lib(start_routine, &offset);
|
||||
if (lib)
|
||||
printf("%s: 0x%lx is in %s @ 0x%lx\n",
|
||||
__func__, start_routine, lib, offset);
|
||||
|
||||
if (lib && (strstr(lib, "iomp") || strstr(lib, "psm"))) {
|
||||
util_thread = 0;
|
||||
}
|
||||
|
||||
if (util_thread) {
|
||||
/* McKernel util_indicate_clone() */
|
||||
syscall(731);
|
||||
}
|
||||
|
||||
if (lib)
|
||||
free(lib);
|
||||
|
||||
return orig_pthread_create(thread, attr, start_routine, arg);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1322,7 +1322,8 @@ void init_sigaction(void)
|
||||
|
||||
master_tid = gettid();
|
||||
for (i = 1; i <= 64; i++) {
|
||||
if (i != SIGKILL && i != SIGSTOP && i != SIGCHLD) {
|
||||
if (i != SIGKILL && i != SIGSTOP && i != SIGCHLD &&
|
||||
i != SIGTSTP && i != SIGTTIN && i != SIGTTOU) {
|
||||
struct sigaction act;
|
||||
|
||||
sigaction(i, NULL, &act);
|
||||
@ -2211,6 +2212,64 @@ int main(int argc, char **argv)
|
||||
|
||||
pthread_spin_init(&overlay_fd_lock, 0);
|
||||
|
||||
/* XXX: Fugaku: Fujitsu process placement fix */
|
||||
if (getenv("FLIB_AFFINITY_ON_PROCESS")) {
|
||||
char *cpu_s;
|
||||
int flib_size;
|
||||
char *flib_aff_orig, *flib_aff;
|
||||
int cpu, off = 0;
|
||||
|
||||
flib_aff_orig = strdup(getenv("FLIB_AFFINITY_ON_PROCESS"));
|
||||
if (!flib_aff_orig) {
|
||||
fprintf(stderr, "error: dupping FLIB_AFFINITY_ON_PROCESS\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
flib_size = strlen(flib_aff_orig) * 2;
|
||||
|
||||
flib_aff = malloc(flib_size);
|
||||
if (!flib_aff) {
|
||||
fprintf(stderr, "error: allocating memory for "
|
||||
"FLIB_AFFINITY_ON_PROCESS\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
memset(flib_aff, 0, flib_size);
|
||||
|
||||
cpu_s = strtok(flib_aff_orig, ",");
|
||||
while (cpu_s) {
|
||||
int ret;
|
||||
|
||||
/* "Shift" left by 12 CPUs */
|
||||
cpu = atoi(cpu_s) - 12;
|
||||
|
||||
/* Prepend "," */
|
||||
if (off > 0) {
|
||||
ret = snprintf(flib_aff + off, flib_size - off, "%s", ",");
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "error: constructing "
|
||||
"FLIB_AFFINITY_ON_PROCESS\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
off += ret;
|
||||
}
|
||||
|
||||
ret = snprintf(flib_aff + off, flib_size - off, "%d", cpu);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "error: constructing "
|
||||
"FLIB_AFFINITY_ON_PROCESS\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
off += ret;
|
||||
cpu_s = strtok(NULL, ",");
|
||||
}
|
||||
|
||||
__dprintf("FLIB_AFFINITY_ON_PROCESS: %s -> %s\n",
|
||||
getenv("FLIB_AFFINITY_ON_PROCESS"), flib_aff);
|
||||
setenv("FLIB_AFFINITY_ON_PROCESS", flib_aff, 1);
|
||||
}
|
||||
|
||||
ld_preload_init();
|
||||
|
||||
#ifdef ADD_ENVS_OPTION
|
||||
@ -2483,6 +2542,8 @@ int main(int argc, char **argv)
|
||||
|
||||
CPU_ZERO(&mcexec_cpu_set);
|
||||
|
||||
cpu_set_arg.req_cpu_list = NULL;
|
||||
cpu_set_arg.req_cpu_list_len = 0;
|
||||
cpu_set_arg.cpu_set = (void *)&desc->cpu_set;
|
||||
cpu_set_arg.cpu_set_size = sizeof(desc->cpu_set);
|
||||
cpu_set_arg.nr_processes = nr_processes;
|
||||
@ -2494,6 +2555,16 @@ int main(int argc, char **argv)
|
||||
cpu_set_arg.mcexec_cpu_set_size = sizeof(mcexec_cpu_set);
|
||||
cpu_set_arg.ikc_mapped = &ikc_mapped;
|
||||
|
||||
/* Fugaku specific: Fujitsu CPU binding */
|
||||
if (getenv("FLIB_AFFINITY_ON_PROCESS")) {
|
||||
cpu_set_arg.req_cpu_list =
|
||||
getenv("FLIB_AFFINITY_ON_PROCESS");
|
||||
cpu_set_arg.req_cpu_list_len =
|
||||
strlen(cpu_set_arg.req_cpu_list) + 1;
|
||||
__dprintf("%s: requesting CPUs: %s\n",
|
||||
__func__, cpu_set_arg.req_cpu_list);
|
||||
}
|
||||
|
||||
if (ioctl(fd, MCEXEC_UP_GET_CPUSET, (void *)&cpu_set_arg) != 0) {
|
||||
perror("getting CPU set for partitioned execution");
|
||||
close(fd);
|
||||
@ -2502,6 +2573,12 @@ int main(int argc, char **argv)
|
||||
|
||||
desc->cpu = target_core;
|
||||
desc->process_rank = process_rank;
|
||||
/* Fugaku specific: Fujitsu node-local rank */
|
||||
if (getenv("PLE_RANK_ON_NODE")) {
|
||||
desc->process_rank = atoi(getenv("PLE_RANK_ON_NODE"));
|
||||
__dprintf("%s: rank: %d, target CPU: %d\n",
|
||||
__func__, desc->process_rank, desc->cpu);
|
||||
}
|
||||
|
||||
/* Bind to CPU cores where the LWK process' IKC target maps to */
|
||||
if (ikc_mapped && !no_bind_ikc_map) {
|
||||
|
||||
1348
executer/user/mcinspect.c
Normal file
1348
executer/user/mcinspect.c
Normal file
File diff suppressed because it is too large
Load Diff
10
executer/user/mcps.in
Normal file
10
executer/user/mcps.in
Normal file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
# IHK/McKernel mcps script.
|
||||
# author: Balazs Gerofi <bgerofi@riken.jp>
|
||||
# Copyright (C) 2019 RIKEN
|
||||
#
|
||||
prefix="@prefix@"
|
||||
BINDIR="${prefix}/bin"
|
||||
KERNDIR="@MCKERNELDIR@"
|
||||
|
||||
${BINDIR}/mcinspect --kernel=${KERNDIR}/mckernel.img --ps
|
||||
2
ihk
2
ihk
Submodule ihk updated: b680d18588...df12c9102c
@ -170,7 +170,7 @@ static void devobj_free(struct memobj *memobj)
|
||||
|
||||
error = syscall_generic_forwarding(__NR_mmap, &ctx);
|
||||
if (error) {
|
||||
kprintf("%s(%p %lx): release failed. %d\n",
|
||||
dkprintf("%s(%p %lx): release failed. %d\n",
|
||||
__func__, obj, handle, error);
|
||||
/* through */
|
||||
}
|
||||
|
||||
@ -398,8 +398,9 @@ static void fileobj_free(struct memobj *memobj)
|
||||
}
|
||||
}
|
||||
|
||||
/* Pre-mapped? */
|
||||
if (to_memobj(obj)->flags & MF_PREMAP) {
|
||||
/* Pre-mapped zerofilled? */
|
||||
if (to_memobj(obj)->flags & MF_PREMAP &&
|
||||
to_memobj(obj)->flags & MF_ZEROFILL) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < to_memobj(obj)->nr_pages; ++i) {
|
||||
@ -440,7 +441,7 @@ static void fileobj_free(struct memobj *memobj)
|
||||
|
||||
error = syscall_generic_forwarding(__NR_mmap, &ctx);
|
||||
if (error) {
|
||||
kprintf("%s(%p %lx): free failed. %d\n", __func__,
|
||||
dkprintf("%s(%p %lx): free failed. %d\n", __func__,
|
||||
obj, obj->handle, error);
|
||||
/* through */
|
||||
}
|
||||
@ -473,20 +474,24 @@ static void fileobj_do_pageio(void *args0)
|
||||
ssize_t ss;
|
||||
struct mcs_lock_node mcs_node;
|
||||
int hash = (off >> PAGE_SHIFT) & FILEOBJ_PAGE_HASH_MASK;
|
||||
int attempts = 0;
|
||||
|
||||
mcs_lock_lock_noirq(&obj->page_hash_locks[hash],
|
||||
&mcs_node);
|
||||
mcs_lock_lock(&obj->page_hash_locks[hash], &mcs_node);
|
||||
page = __fileobj_page_hash_lookup(obj, hash, off);
|
||||
if (!page) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (page->mode == PM_PAGEIO) {
|
||||
mcs_lock_unlock_noirq(&obj->page_hash_locks[hash],
|
||||
&mcs_node);
|
||||
mcs_lock_unlock(&obj->page_hash_locks[hash], &mcs_node);
|
||||
++attempts;
|
||||
if (attempts > 49) {
|
||||
dkprintf("%s: %s:%lu PM_PAGEIO loop %d -> schedule()\n",
|
||||
__func__, to_memobj(obj)->path, off, attempts);
|
||||
schedule();
|
||||
}
|
||||
cpu_pause();
|
||||
mcs_lock_lock_noirq(&obj->page_hash_locks[hash],
|
||||
&mcs_node);
|
||||
mcs_lock_lock(&obj->page_hash_locks[hash], &mcs_node);
|
||||
}
|
||||
|
||||
if (page->mode == PM_WILL_PAGEIO) {
|
||||
@ -499,8 +504,7 @@ static void fileobj_do_pageio(void *args0)
|
||||
}
|
||||
else {
|
||||
page->mode = PM_PAGEIO;
|
||||
mcs_lock_unlock_noirq(&obj->page_hash_locks[hash],
|
||||
&mcs_node);
|
||||
mcs_lock_unlock(&obj->page_hash_locks[hash], &mcs_node);
|
||||
|
||||
ihk_mc_syscall_arg0(&ctx) = PAGER_REQ_READ;
|
||||
ihk_mc_syscall_arg1(&ctx) = obj->handle;
|
||||
@ -512,8 +516,7 @@ static void fileobj_do_pageio(void *args0)
|
||||
__FUNCTION__, obj->handle);
|
||||
ss = syscall_generic_forwarding(__NR_mmap, &ctx);
|
||||
|
||||
mcs_lock_lock_noirq(&obj->page_hash_locks[hash],
|
||||
&mcs_node);
|
||||
mcs_lock_lock(&obj->page_hash_locks[hash], &mcs_node);
|
||||
if (page->mode != PM_PAGEIO) {
|
||||
kprintf("fileobj_do_pageio(%p,%lx,%lx):"
|
||||
"invalid mode %x\n",
|
||||
@ -539,8 +542,7 @@ static void fileobj_do_pageio(void *args0)
|
||||
page->mode = PM_DONE_PAGEIO;
|
||||
}
|
||||
out:
|
||||
mcs_lock_unlock_noirq(&obj->page_hash_locks[hash],
|
||||
&mcs_node);
|
||||
mcs_lock_unlock(&obj->page_hash_locks[hash], &mcs_node);
|
||||
memobj_unref(&obj->memobj); /* got fileobj_get_page() */
|
||||
kfree(args0);
|
||||
dkprintf("fileobj_do_pageio(%p,%lx,%lx):\n", obj, off, pgsize);
|
||||
@ -570,7 +572,8 @@ static int fileobj_get_page(struct memobj *memobj, off_t off,
|
||||
profile_event_add(PROFILE_page_fault_file, PAGE_SIZE);
|
||||
#endif // PROFILE_ENABLE
|
||||
|
||||
if (memobj->flags & MF_PREMAP) {
|
||||
if (memobj->flags & MF_PREMAP &&
|
||||
memobj->flags & MF_ZEROFILL) {
|
||||
int page_ind = off >> PAGE_SHIFT;
|
||||
|
||||
if (!memobj->pages[page_ind]) {
|
||||
@ -587,8 +590,7 @@ static int fileobj_get_page(struct memobj *memobj, off_t off,
|
||||
|
||||
/* Update the array but see if someone did it already and use
|
||||
* that if so */
|
||||
if (!__sync_bool_compare_and_swap(&memobj->pages[page_ind],
|
||||
NULL, virt)) {
|
||||
if (cmpxchg(&memobj->pages[page_ind], NULL, virt) != NULL) {
|
||||
ihk_mc_free_pages_user(virt, 1);
|
||||
}
|
||||
else {
|
||||
@ -609,8 +611,7 @@ static int fileobj_get_page(struct memobj *memobj, off_t off,
|
||||
goto out_nolock;
|
||||
}
|
||||
|
||||
mcs_lock_lock_noirq(&obj->page_hash_locks[hash],
|
||||
&mcs_node);
|
||||
mcs_lock_lock(&obj->page_hash_locks[hash], &mcs_node);
|
||||
page = __fileobj_page_hash_lookup(obj, hash, off);
|
||||
if (!page || (page->mode == PM_WILL_PAGEIO)
|
||||
|| (page->mode == PM_PAGEIO)) {
|
||||
@ -688,8 +689,7 @@ static int fileobj_get_page(struct memobj *memobj, off_t off,
|
||||
*physp = page_to_phys(page);
|
||||
virt = NULL;
|
||||
out:
|
||||
mcs_lock_unlock_noirq(&obj->page_hash_locks[hash],
|
||||
&mcs_node);
|
||||
mcs_lock_unlock(&obj->page_hash_locks[hash], &mcs_node);
|
||||
out_nolock:
|
||||
if (virt) {
|
||||
ihk_mc_free_pages_user(virt, npages);
|
||||
@ -767,8 +767,7 @@ static int fileobj_lookup_page(struct memobj *memobj, off_t off,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mcs_lock_lock_noirq(&obj->page_hash_locks[hash],
|
||||
&mcs_node);
|
||||
mcs_lock_lock(&obj->page_hash_locks[hash], &mcs_node);
|
||||
|
||||
page = __fileobj_page_hash_lookup(obj, hash, off);
|
||||
if (!page) {
|
||||
@ -779,8 +778,7 @@ static int fileobj_lookup_page(struct memobj *memobj, off_t off,
|
||||
error = 0;
|
||||
|
||||
out:
|
||||
mcs_lock_unlock_noirq(&obj->page_hash_locks[hash],
|
||||
&mcs_node);
|
||||
mcs_lock_unlock(&obj->page_hash_locks[hash], &mcs_node);
|
||||
|
||||
dkprintf("fileobj_lookup_page(%p,%lx,%x,%p): %d \n",
|
||||
obj, off, p2align, physp, error);
|
||||
|
||||
@ -311,6 +311,7 @@ static int futex_wake(uint32_t *uaddr, int fshared, int nr_wake, uint32_t bitset
|
||||
struct plist_head *head;
|
||||
union futex_key key = FUTEX_KEY_INIT;
|
||||
int ret;
|
||||
unsigned long irqstate;
|
||||
|
||||
if (!bitset)
|
||||
return -EINVAL;
|
||||
@ -320,7 +321,7 @@ static int futex_wake(uint32_t *uaddr, int fshared, int nr_wake, uint32_t bitset
|
||||
goto out;
|
||||
|
||||
hb = hash_futex(&key);
|
||||
ihk_mc_spinlock_lock_noirq(&hb->lock);
|
||||
irqstate = ihk_mc_spinlock_lock(&hb->lock);
|
||||
head = &hb->chain;
|
||||
|
||||
plist_for_each_entry_safe(this, next, head, list) {
|
||||
@ -337,7 +338,7 @@ static int futex_wake(uint32_t *uaddr, int fshared, int nr_wake, uint32_t bitset
|
||||
}
|
||||
}
|
||||
|
||||
ihk_mc_spinlock_unlock_noirq(&hb->lock);
|
||||
ihk_mc_spinlock_unlock(&hb->lock, irqstate);
|
||||
put_futex_key(fshared, &key);
|
||||
out:
|
||||
return ret;
|
||||
|
||||
@ -142,7 +142,7 @@ int prepare_process_ranges_args_envs(struct thread *thread,
|
||||
if (add_process_memory_range(vm, s, e, NOPHYS, flags, NULL, 0,
|
||||
pn->sections[i].len > LARGE_PAGE_SIZE ?
|
||||
LARGE_PAGE_SHIFT : PAGE_SHIFT,
|
||||
NULL, &range) != 0) {
|
||||
&range) != 0) {
|
||||
kprintf("ERROR: adding memory range for ELF section %i\n", i);
|
||||
goto err;
|
||||
}
|
||||
@ -284,7 +284,7 @@ int prepare_process_ranges_args_envs(struct thread *thread,
|
||||
dkprintf("%s: args_envs: %d pages\n",
|
||||
__func__, argenv_page_count);
|
||||
if(add_process_memory_range(vm, addr, e, args_envs_p,
|
||||
flags, NULL, 0, PAGE_SHIFT, NULL, NULL) != 0){
|
||||
flags, NULL, 0, PAGE_SHIFT, NULL) != 0){
|
||||
ihk_mc_free_pages_user(args_envs, argenv_page_count);
|
||||
kprintf("ERROR: adding memory range for args/envs\n");
|
||||
goto err;
|
||||
@ -500,6 +500,7 @@ static int process_msg_prepare_process(unsigned long rphys)
|
||||
ihk_mc_unmap_memory(NULL, phys, sz);
|
||||
return -ENOMEM;
|
||||
}
|
||||
sprintf(thread->pthread_routine, "%s", "[main]");
|
||||
proc = thread->proc;
|
||||
vm = thread->vm;
|
||||
|
||||
@ -619,6 +620,7 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c,
|
||||
{
|
||||
struct ikc_scd_packet *packet = __packet;
|
||||
struct ikc_scd_packet pckt;
|
||||
struct ihk_os_cpu_register *cpu_desc;
|
||||
struct ihk_ikc_channel_desc *resp_channel = cpu_local_var(ikc2linux);
|
||||
int rc;
|
||||
struct thread *thread;
|
||||
@ -689,11 +691,11 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c,
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
thread_unlock(thread);
|
||||
|
||||
dkprintf("%s: SCD_MSG_WAKE_UP_SYSCALL_THREAD: waking up tid %d\n",
|
||||
__FUNCTION__, packet->ttid);
|
||||
waitq_wakeup(&thread->scd_wq);
|
||||
thread_unlock(thread);
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
@ -717,9 +719,11 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c,
|
||||
dkprintf("remote page fault,pid=%d,va=%lx,reason=%x\n",
|
||||
thread->proc->pid, packet->fault_address,
|
||||
packet->fault_reason|PF_POPULATE);
|
||||
preempt_disable();
|
||||
pckt.err = page_fault_process_vm(thread->vm,
|
||||
(void *)packet->fault_address,
|
||||
packet->fault_reason|PF_POPULATE);
|
||||
preempt_enable();
|
||||
|
||||
#ifdef PROFILE_ENABLE
|
||||
if (thread->profile) {
|
||||
@ -839,12 +843,17 @@ out_remote_pf:
|
||||
break;
|
||||
|
||||
case SCD_MSG_CPU_RW_REG:
|
||||
pp = ihk_mc_map_memory(NULL, packet->pdesc,
|
||||
sizeof(struct ihk_os_cpu_register));
|
||||
cpu_desc = (struct ihk_os_cpu_register *)ihk_mc_map_virtual(
|
||||
pp, 1, PTATTR_WRITABLE | PTATTR_ACTIVE);
|
||||
|
||||
pckt.msg = SCD_MSG_CPU_RW_REG_RESP;
|
||||
memcpy(&pckt.desc, &packet->desc,
|
||||
sizeof(struct ihk_os_cpu_register));
|
||||
pckt.resp = packet->resp;
|
||||
pckt.err = arch_cpu_read_write_register(&pckt.desc, packet->op);
|
||||
pckt.reply = packet->reply;
|
||||
pckt.err = arch_cpu_read_write_register(cpu_desc, packet->op);
|
||||
|
||||
ihk_mc_unmap_virtual(cpu_desc, 1);
|
||||
ihk_mc_unmap_memory(NULL, pp, sizeof(struct ihk_os_cpu_register));
|
||||
|
||||
ihk_ikc_send(resp_channel, &pckt, 0);
|
||||
break;
|
||||
@ -895,7 +904,7 @@ void init_host_ikc2linux(int linux_cpu)
|
||||
param.port = 503;
|
||||
param.intr_cpu = linux_cpu;
|
||||
param.pkt_size = sizeof(struct ikc_scd_packet);
|
||||
param.queue_size = 2 * num_processors * sizeof(struct ikc_scd_packet);
|
||||
param.queue_size = 4 * num_processors * sizeof(struct ikc_scd_packet);
|
||||
if (param.queue_size < PAGE_SIZE * 4) {
|
||||
param.queue_size = PAGE_SIZE * 4;
|
||||
}
|
||||
|
||||
@ -139,7 +139,6 @@ static void hugefileobj_free(struct memobj *memobj)
|
||||
struct memobj_ops hugefileobj_ops = {
|
||||
.free = hugefileobj_free,
|
||||
.get_page = hugefileobj_get_page,
|
||||
|
||||
};
|
||||
|
||||
void hugefileobj_cleanup(void)
|
||||
|
||||
@ -100,6 +100,7 @@ struct cpu_local_var {
|
||||
int in_interrupt;
|
||||
int no_preempt;
|
||||
int timer_enabled;
|
||||
unsigned long nr_ctx_switches;
|
||||
int kmalloc_initialized;
|
||||
struct ihk_os_cpu_monitor *monitor;
|
||||
struct rusage_percpu *rusage;
|
||||
|
||||
@ -72,4 +72,11 @@
|
||||
#define MS_INVALIDATE 0x02
|
||||
#define MS_SYNC 0x04
|
||||
|
||||
/* include/uapi/linux/mman.h */
|
||||
#define OVERCOMMIT_GUESS 0
|
||||
#define OVERCOMMIT_ALWAYS 1
|
||||
#define OVERCOMMIT_NEVER 2
|
||||
|
||||
extern int sysctl_overcommit_memory;
|
||||
|
||||
#endif /* HEADER_MMAN_H */
|
||||
|
||||
@ -55,7 +55,6 @@
|
||||
#define VR_MEMTYPE_MASK 0x0f000000
|
||||
#define VR_PAGEOUT 0x10000000
|
||||
#define VR_DONTDUMP 0x20000000
|
||||
#define VR_XPMEM 0x40000000
|
||||
#define VR_WIPEONFORK 0x80000000
|
||||
|
||||
#define PROT_TO_VR_FLAG(prot) (((unsigned long)(prot) << 16) & VR_PROT_MASK)
|
||||
@ -506,10 +505,12 @@ struct process {
|
||||
// PS_STOPPED -----+
|
||||
// (PS_TRACED)
|
||||
|
||||
/* Store exit_status for a group of threads when stopped by SIGSTOP.
|
||||
exit_status can't be used because values of exit_status of threads
|
||||
might divert while the threads are exiting by group_exit(). */
|
||||
int group_exit_status;
|
||||
/* Store exit_status for a group of threads when stopped by SIGSTOP. */
|
||||
/* exit_status can't be used because values of exit_status of threads */
|
||||
/* might divert while the threads are exiting by group_exit(). */
|
||||
/* The upper 4 bytes of group_exit_status is the confirmation flag of */
|
||||
/* exit status. The lower 4 bytes is the exit status. */
|
||||
unsigned long group_exit_status;
|
||||
|
||||
/* Manage ptraced processes in the separate list to make it easy to
|
||||
restore the orginal parent child relationship when
|
||||
@ -609,6 +610,7 @@ struct thread {
|
||||
// thread info
|
||||
int cpu_id;
|
||||
int tid;
|
||||
char pthread_routine[PATH_MAX + 64];
|
||||
int status; // PS_RUNNING -> PS_EXITED (-> ZOMBIE / ptrace)
|
||||
// | ^ ^
|
||||
// | | |
|
||||
@ -718,6 +720,7 @@ struct thread {
|
||||
/* Syscall offload wait queue head */
|
||||
struct waitq scd_wq;
|
||||
|
||||
unsigned long clone_pthread_start_routine;
|
||||
int uti_state;
|
||||
int mod_clone;
|
||||
struct uti_attr *mod_clone_arg;
|
||||
@ -749,7 +752,7 @@ struct process_vm {
|
||||
void *vvar_addr;
|
||||
|
||||
ihk_spinlock_t page_table_lock;
|
||||
ihk_spinlock_t memory_range_lock;
|
||||
ihk_rwspinlock_t memory_range_lock;
|
||||
// to protect the followings:
|
||||
// 1. addition of process "memory range" (extend_process_region, add_process_memory_range)
|
||||
// 2. addition of process page table (allocate_pages, update_process_page_table)
|
||||
@ -805,7 +808,7 @@ int add_process_memory_range(struct process_vm *vm,
|
||||
unsigned long start, unsigned long end,
|
||||
unsigned long phys, unsigned long flag,
|
||||
struct memobj *memobj, off_t offset,
|
||||
int pgshift, void *private_data, struct vm_range **rp);
|
||||
int pgshift, struct vm_range **rp);
|
||||
int remove_process_memory_range(struct process_vm *vm, unsigned long start,
|
||||
unsigned long end, int *ro_freedp);
|
||||
int split_process_memory_range(struct process_vm *vm,
|
||||
|
||||
@ -5,10 +5,9 @@
|
||||
#define PROFILE_ENABLE
|
||||
|
||||
#ifdef PROFILE_ENABLE
|
||||
#define PROFILE_SYSCALL_MAX 300
|
||||
#define PROFILE_SYSCALL_MAX 2000
|
||||
#define PROFILE_OFFLOAD_MAX (PROFILE_SYSCALL_MAX << 1)
|
||||
#define PROFILE_EVENT_MIN PROFILE_OFFLOAD_MAX
|
||||
#define __NR_profile 701
|
||||
|
||||
#define PROF_JOB 0x40000000
|
||||
#define PROF_PROC 0x80000000
|
||||
@ -47,6 +46,8 @@ enum profile_event_type {
|
||||
PROFILE_EVENT_MAX /* Should be the last event type */
|
||||
};
|
||||
|
||||
#define __NR_profile PROFILE_EVENT_MAX
|
||||
|
||||
struct thread;
|
||||
struct process;
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include <ihk/ihk_monitor.h>
|
||||
#include <ihk/debug.h>
|
||||
#include <memory.h>
|
||||
#include <mman.h>
|
||||
|
||||
#ifdef ENABLE_RUSAGE
|
||||
|
||||
@ -27,30 +28,17 @@ static inline int rusage_pgsize_to_pgtype(size_t pgsize)
|
||||
case 12:
|
||||
ret = IHK_OS_PGSIZE_4KB;
|
||||
break;
|
||||
case 16:
|
||||
ret = IHK_OS_PGSIZE_64KB;
|
||||
break;
|
||||
case 21:
|
||||
ret = IHK_OS_PGSIZE_2MB;
|
||||
break;
|
||||
case 25:
|
||||
ret = IHK_OS_PGSIZE_32MB;
|
||||
break;
|
||||
case 30:
|
||||
ret = IHK_OS_PGSIZE_1GB;
|
||||
break;
|
||||
case 34:
|
||||
ret = IHK_OS_PGSIZE_16GB;
|
||||
break;
|
||||
case 29:
|
||||
ret = IHK_OS_PGSIZE_512MB;
|
||||
break;
|
||||
case 42:
|
||||
ret = IHK_OS_PGSIZE_4TB;
|
||||
break;
|
||||
default:
|
||||
#if 0 /* 64KB page goes here when using mckernel_rusage-compatible ihk_os_rusage */
|
||||
kprintf("%s: Error: Unknown pgsize=%ld\n",
|
||||
__func__, pgsize);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
@ -324,6 +312,9 @@ rusage_check_overmap(size_t len, int pgshift)
|
||||
{
|
||||
int npages = 0, remain_pages = 0;
|
||||
|
||||
if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS)
|
||||
return 0;
|
||||
|
||||
npages = (len + (1UL << pgshift) - 1) >> pgshift;
|
||||
remain_pages = (rusage.total_memory - rusage.total_memory_usage)
|
||||
>> pgshift;
|
||||
|
||||
@ -287,7 +287,7 @@ struct ikc_scd_packet {
|
||||
|
||||
/* SCD_MSG_CPU_RW_REG */
|
||||
struct {
|
||||
struct ihk_os_cpu_register desc;
|
||||
unsigned long pdesc; /* Physical addr of the descriptor */
|
||||
enum mcctrl_os_cpu_operation op;
|
||||
void *resp;
|
||||
};
|
||||
@ -508,7 +508,7 @@ enum set_cputime_mode {
|
||||
void set_cputime(enum set_cputime_mode mode);
|
||||
int do_munmap(void *addr, size_t len, int holding_memory_range_lock);
|
||||
intptr_t do_mmap(uintptr_t addr0, size_t len0, int prot, int flags, int fd,
|
||||
off_t off0, const int vrf0, void *private_data);
|
||||
off_t off0);
|
||||
void clear_host_pte(uintptr_t addr, size_t len, int holding_memory_range_lock);
|
||||
typedef int32_t key_t;
|
||||
int do_shmget(key_t key, size_t size, int shmflg);
|
||||
@ -651,4 +651,6 @@ extern int (*linux_clock_gettime)(clockid_t clk_id, struct timespec *tp);
|
||||
#define COREDUMP_TO_BE_WOKEN 2
|
||||
|
||||
extern void terminate_host(int pid, struct thread *thread);
|
||||
struct sig_pending *getsigpending(struct thread *thread, int delflag);
|
||||
int interrupt_from_user(void *regs0);
|
||||
#endif
|
||||
|
||||
@ -27,20 +27,6 @@ int xpmem_remove_process_memory_range(struct process_vm *vm,
|
||||
struct vm_range *vmr);
|
||||
int xpmem_fault_process_memory_range(struct process_vm *vm,
|
||||
struct vm_range *vmr, unsigned long vaddr, uint64_t reason);
|
||||
int xpmem_update_process_page_table(struct process_vm *vm,
|
||||
struct vm_range *vmr);
|
||||
|
||||
struct xpmem_attachment {
|
||||
mcs_rwlock_lock_t at_lock; /* att lock */
|
||||
unsigned long vaddr; /* starting address of seg attached */
|
||||
unsigned long at_vaddr; /* address where seg is attached */
|
||||
size_t at_size; /* size of seg attachment */
|
||||
struct vm_range *at_vmr; /* vm_range where seg is attachment */
|
||||
int flags; /* att attributes and state */
|
||||
ihk_atomic_t refcnt; /* references to att */
|
||||
struct xpmem_access_permit *ap; /* associated access permit */
|
||||
struct list_head att_list; /* atts linked to access permit */
|
||||
struct process_vm *vm; /* process_vm attached to */
|
||||
};
|
||||
#endif /* _XPMEM_H */
|
||||
|
||||
|
||||
@ -177,6 +177,19 @@ struct xpmem_access_permit {
|
||||
struct list_head ap_hashlist; /* access permit hash list */
|
||||
};
|
||||
|
||||
struct xpmem_attachment {
|
||||
mcs_rwlock_lock_t at_lock; /* att lock */
|
||||
unsigned long vaddr; /* starting address of seg attached */
|
||||
unsigned long at_vaddr; /* address where seg is attached */
|
||||
size_t at_size; /* size of seg attachment */
|
||||
struct vm_range *at_vmr; /* vm_range where seg is attachment */
|
||||
volatile int flags; /* att attributes and state */
|
||||
ihk_atomic_t refcnt; /* references to att */
|
||||
struct xpmem_access_permit *ap; /* associated access permit */
|
||||
struct list_head att_list; /* atts linked to access permit */
|
||||
struct process_vm *vm; /* process_vm attached to */
|
||||
};
|
||||
|
||||
struct xpmem_partition {
|
||||
ihk_atomic_t n_opened; /* # of /dev/xpmem opened */
|
||||
struct xpmem_hashlist tg_hashtable[]; /* locks + tg hash lists */
|
||||
@ -318,7 +331,6 @@ static void xpmem_ap_deref(struct xpmem_access_permit *ap);
|
||||
static void xpmem_att_deref(struct xpmem_attachment *att);
|
||||
static int xpmem_validate_access(struct xpmem_access_permit *, off_t, size_t,
|
||||
int, unsigned long *);
|
||||
static int is_remote_vm(struct process_vm *vm);
|
||||
|
||||
/*
|
||||
* Inlines that mark an internal driver structure as being destroyable or not.
|
||||
|
||||
12
kernel/mem.c
12
kernel/mem.c
@ -62,6 +62,7 @@ extern int interrupt_from_user(void *);
|
||||
struct tlb_flush_entry tlb_flush_vector[IHK_TLB_FLUSH_IRQ_VECTOR_SIZE];
|
||||
|
||||
int anon_on_demand = 0;
|
||||
int sysctl_overcommit_memory = OVERCOMMIT_ALWAYS;
|
||||
|
||||
static struct ihk_mc_pa_ops *pa_ops;
|
||||
|
||||
@ -1276,8 +1277,9 @@ static void unhandled_page_fault(struct thread *thread, void *fault_addr,
|
||||
|
||||
range = lookup_process_memory_range(vm, address, address+1);
|
||||
if (range) {
|
||||
__kprintf("address is in range, flag: 0x%lx\n",
|
||||
range->flag);
|
||||
__kprintf("address is in range, flag: 0x%lx (%s)\n",
|
||||
range->flag,
|
||||
range->memobj ? range->memobj->path : "");
|
||||
ihk_mc_pt_print_pte(vm->address_space->page_table,
|
||||
(void *)address);
|
||||
} else {
|
||||
@ -1600,9 +1602,11 @@ static void numa_distances_init()
|
||||
static ssize_t numa_sysfs_show_meminfo(struct sysfs_ops *ops,
|
||||
void *instance, void *buf, size_t size)
|
||||
{
|
||||
#ifdef IHK_RBTREE_ALLOCATOR
|
||||
struct ihk_mc_numa_node *node =
|
||||
(struct ihk_mc_numa_node *)instance;
|
||||
char *sbuf = (char *)buf;
|
||||
#endif
|
||||
int len = 0;
|
||||
|
||||
#ifdef IHK_RBTREE_ALLOCATOR
|
||||
@ -2559,7 +2563,7 @@ void ihk_mc_query_mem_user_page(void *dump_pase_info) {
|
||||
}
|
||||
|
||||
void ihk_mc_query_mem_free_page(void *dump_pase_info) {
|
||||
|
||||
#ifdef IHK_RBTREE_ALLOCATOR
|
||||
struct free_chunk *chunk;
|
||||
struct rb_node *node;
|
||||
struct rb_root *free_chunks;
|
||||
@ -2629,7 +2633,7 @@ void ihk_mc_query_mem_free_page(void *dump_pase_info) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
152
kernel/process.c
152
kernel/process.c
@ -91,7 +91,7 @@ ihk_spinlock_t runq_reservation_lock;
|
||||
|
||||
int idle_halt = 0;
|
||||
int allow_oversubscribe = 0;
|
||||
int time_sharing = 0;
|
||||
int time_sharing = 1;
|
||||
|
||||
void
|
||||
init_process(struct process *proc, struct process *parent)
|
||||
@ -243,7 +243,7 @@ static int
|
||||
init_process_vm(struct process *owner, struct address_space *asp, struct process_vm *vm)
|
||||
{
|
||||
int i;
|
||||
ihk_mc_spinlock_init(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_init(&vm->memory_range_lock);
|
||||
ihk_mc_spinlock_init(&vm->page_table_lock);
|
||||
|
||||
ihk_atomic_set(&vm->refcount, 1);
|
||||
@ -792,7 +792,7 @@ static int copy_user_ranges(struct process_vm *vm, struct process_vm *orgvm)
|
||||
struct vm_range *last_insert;
|
||||
struct copy_args args;
|
||||
|
||||
ihk_mc_spinlock_lock_noirq(&orgvm->memory_range_lock);
|
||||
ihk_rwspinlock_read_lock_noirq(&orgvm->memory_range_lock);
|
||||
|
||||
/* Iterate original process' vm_range list and take a copy one-by-one */
|
||||
last_insert = NULL;
|
||||
@ -854,7 +854,7 @@ static int copy_user_ranges(struct process_vm *vm, struct process_vm *orgvm)
|
||||
// memory_stat_rss_add() is called in child-node, i.e. copy_user_pte()
|
||||
}
|
||||
|
||||
ihk_mc_spinlock_unlock_noirq(&orgvm->memory_range_lock);
|
||||
ihk_rwspinlock_read_unlock_noirq(&orgvm->memory_range_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -881,7 +881,7 @@ err_rollback:
|
||||
}
|
||||
}
|
||||
|
||||
ihk_mc_spinlock_unlock_noirq(&orgvm->memory_range_lock);
|
||||
ihk_rwspinlock_read_unlock_noirq(&orgvm->memory_range_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1316,7 +1316,7 @@ int add_process_memory_range(struct process_vm *vm,
|
||||
unsigned long start, unsigned long end,
|
||||
unsigned long phys, unsigned long flag,
|
||||
struct memobj *memobj, off_t offset,
|
||||
int pgshift, void *private_data, struct vm_range **rp)
|
||||
int pgshift, struct vm_range **rp)
|
||||
{
|
||||
dkprintf("%s: start=%lx,end=%lx,phys=%lx,flag=%lx\n", __FUNCTION__, start, end, phys, flag);
|
||||
struct vm_range *range;
|
||||
@ -1344,7 +1344,7 @@ int add_process_memory_range(struct process_vm *vm,
|
||||
range->memobj = memobj;
|
||||
range->objoff = offset;
|
||||
range->pgshift = pgshift;
|
||||
range->private_data = private_data;
|
||||
range->private_data = NULL;
|
||||
|
||||
rc = 0;
|
||||
if (phys == NOPHYS) {
|
||||
@ -1356,10 +1356,6 @@ int add_process_memory_range(struct process_vm *vm,
|
||||
else if (flag & VR_IO_NOCACHE) {
|
||||
rc = update_process_page_table(vm, range, phys, PTATTR_UNCACHABLE);
|
||||
}
|
||||
else if (flag & VR_XPMEM) {
|
||||
range->memobj->flags |= MF_XPMEM;
|
||||
rc = xpmem_update_process_page_table(vm, range);
|
||||
}
|
||||
else if (flag & VR_DEMAND_PAGING) {
|
||||
dkprintf("%s: range: 0x%lx - 0x%lx is demand paging\n",
|
||||
__FUNCTION__, range->start, range->end);
|
||||
@ -1387,8 +1383,7 @@ int add_process_memory_range(struct process_vm *vm,
|
||||
}
|
||||
|
||||
/* Clear content! */
|
||||
if (phys != NOPHYS
|
||||
&& !(flag & (VR_REMOTE | VR_DEMAND_PAGING | VR_XPMEM))
|
||||
if (phys != NOPHYS && !(flag & (VR_REMOTE | VR_DEMAND_PAGING))
|
||||
&& ((flag & VR_PROT_MASK) != VR_PROT_NONE)) {
|
||||
#if 1
|
||||
memset((void *)phys_to_virt(phys), 0, end - start);
|
||||
@ -2181,16 +2176,65 @@ static int do_page_fault_process_vm(struct process_vm *vm, void *fault_addr0, ui
|
||||
{
|
||||
int error;
|
||||
const uintptr_t fault_addr = (uintptr_t)fault_addr0;
|
||||
struct vm_range *range;
|
||||
struct vm_range *range = NULL;
|
||||
struct thread *thread = cpu_local_var(current);
|
||||
int locked = 0;
|
||||
|
||||
dkprintf("[%d]do_page_fault_process_vm(%p,%lx,%lx)\n",
|
||||
ihk_mc_get_processor_id(), vm, fault_addr0, reason);
|
||||
|
||||
/* grow stack */
|
||||
if (fault_addr >= thread->vm->region.stack_start &&
|
||||
fault_addr < thread->vm->region.stack_end) {
|
||||
range = lookup_process_memory_range(vm,
|
||||
thread->vm->region.stack_end - 1,
|
||||
thread->vm->region.stack_end);
|
||||
if (range == NULL) {
|
||||
error = -EFAULT;
|
||||
ekprintf("%s: vm: %p, addr: %p, reason: %lx):"
|
||||
"stack not found: %d\n",
|
||||
__func__, vm, fault_addr0, reason, error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* don't grow if replaced with hugetlbfs */
|
||||
if (range->memobj) {
|
||||
goto skip;
|
||||
}
|
||||
|
||||
if (fault_addr >= range->start) {
|
||||
goto skip;
|
||||
}
|
||||
|
||||
if (thread->vm->is_memory_range_lock_taken == -1 ||
|
||||
thread->vm->is_memory_range_lock_taken !=
|
||||
ihk_mc_get_processor_id()) {
|
||||
ihk_rwspinlock_write_lock_noirq(&vm->memory_range_lock);
|
||||
locked = 1;
|
||||
}
|
||||
|
||||
if (range->pgshift) {
|
||||
range->start = fault_addr &
|
||||
~((1UL << range->pgshift) - 1);
|
||||
} else {
|
||||
range->start = fault_addr & PAGE_MASK;
|
||||
}
|
||||
|
||||
if (locked) {
|
||||
ihk_rwspinlock_write_unlock_noirq(&vm->memory_range_lock);
|
||||
locked = 0;
|
||||
}
|
||||
|
||||
dkprintf("%s: addr: %lx, reason: %lx, range: %lx-%lx:"
|
||||
"stack found\n",
|
||||
__func__, (unsigned long)fault_addr, reason,
|
||||
range->start, range->end);
|
||||
}
|
||||
skip:
|
||||
|
||||
if (thread->vm->is_memory_range_lock_taken == -1 ||
|
||||
thread->vm->is_memory_range_lock_taken != ihk_mc_get_processor_id()) {
|
||||
ihk_mc_spinlock_lock_noirq(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_read_lock_noirq(&vm->memory_range_lock);
|
||||
locked = 1;
|
||||
} else {
|
||||
dkprintf("%s: INFO: skip locking of memory_range_lock,pid=%d,tid=%d\n",
|
||||
@ -2202,13 +2246,16 @@ static int do_page_fault_process_vm(struct process_vm *vm, void *fault_addr0, ui
|
||||
goto out;
|
||||
}
|
||||
|
||||
range = lookup_process_memory_range(vm, fault_addr, fault_addr+1);
|
||||
if (range == NULL) {
|
||||
error = -EFAULT;
|
||||
dkprintf("do_page_fault_process_vm(): vm: %p, addr: %p, reason: %lx):"
|
||||
"out of range: %d\n",
|
||||
vm, fault_addr0, reason, error);
|
||||
goto out;
|
||||
if (!range) {
|
||||
range = lookup_process_memory_range(vm, fault_addr,
|
||||
fault_addr+1);
|
||||
if (range == NULL) {
|
||||
error = -EFAULT;
|
||||
dkprintf("%s: vm: %p, addr: %p, reason: %lx):"
|
||||
"out of range: %d\n",
|
||||
__func__, vm, fault_addr0, reason, error);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (((range->flag & VR_PROT_MASK) == VR_PROT_NONE)
|
||||
@ -2305,7 +2352,7 @@ static int do_page_fault_process_vm(struct process_vm *vm, void *fault_addr0, ui
|
||||
error = 0;
|
||||
out:
|
||||
if (locked) {
|
||||
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_read_unlock_noirq(&vm->memory_range_lock);
|
||||
}
|
||||
dkprintf("[%d]do_page_fault_process_vm(%p,%lx,%lx): %d\n",
|
||||
ihk_mc_get_processor_id(), vm, fault_addr0,
|
||||
@ -2324,10 +2371,12 @@ int page_fault_process_vm(struct process_vm *fault_vm, void *fault_addr, uint64_
|
||||
break;
|
||||
}
|
||||
|
||||
preempt_enable();
|
||||
if (thread->pgio_fp) {
|
||||
(*thread->pgio_fp)(thread->pgio_arg);
|
||||
thread->pgio_fp = NULL;
|
||||
}
|
||||
preempt_disable();
|
||||
}
|
||||
|
||||
return error;
|
||||
@ -2370,16 +2419,15 @@ int init_process_stack(struct thread *thread, struct program_load_desc *pn,
|
||||
size = minsz;
|
||||
}
|
||||
size = (size + USER_STACK_PREPAGE_SIZE - 1) & USER_STACK_PAGE_MASK;
|
||||
dkprintf("%s: stack_premap: %lu, rlim_cur: %lu, minsz: %lu, size: %lu\n",
|
||||
__FUNCTION__,
|
||||
pn->stack_premap,
|
||||
proc->rlimit[MCK_RLIMIT_STACK].rlim_cur,
|
||||
minsz, size);
|
||||
start = (end - size) & USER_STACK_PAGE_MASK;
|
||||
dkprintf("%s: stack_premap: %lu, rlim_cur: %lu, minsz: %lu, size: %lu, maxsz: %lx\n",
|
||||
__func__, pn->stack_premap,
|
||||
proc->rlimit[MCK_RLIMIT_STACK].rlim_cur,
|
||||
minsz, size, maxsz);
|
||||
start = (end - minsz) & USER_STACK_PAGE_MASK;
|
||||
|
||||
/* Apply user allocation policy to stacks */
|
||||
/* TODO: make threshold kernel or mcexec argument */
|
||||
ap_flag = (size >= proc->mpol_threshold &&
|
||||
ap_flag = (minsz >= proc->mpol_threshold &&
|
||||
!(proc->mpol_flags & MPOL_NO_STACK)) ? IHK_MC_AP_USER : 0;
|
||||
dkprintf("%s: max size: %lu, mapped size: %lu %s\n",
|
||||
__FUNCTION__, size, minsz,
|
||||
@ -2404,8 +2452,7 @@ int init_process_stack(struct thread *thread, struct program_load_desc *pn,
|
||||
vrflag |= VR_MAXPROT_READ | VR_MAXPROT_WRITE | VR_MAXPROT_EXEC;
|
||||
#define NOPHYS ((uintptr_t)-1)
|
||||
if ((rc = add_process_memory_range(thread->vm, start, end, NOPHYS,
|
||||
vrflag, NULL, 0, USER_STACK_PAGE_SHIFT,
|
||||
NULL, &range)) != 0) {
|
||||
vrflag, NULL, 0, USER_STACK_PAGE_SHIFT, &range)) != 0) {
|
||||
ihk_mc_free_pages_user(stack, minsz >> PAGE_SHIFT);
|
||||
kprintf("%s: error addding process memory range: %d\n", rc);
|
||||
return rc;
|
||||
@ -2512,7 +2559,7 @@ int init_process_stack(struct thread *thread, struct program_load_desc *pn,
|
||||
ihk_mc_modify_user_context(thread->uctx, IHK_UCR_STACK_POINTER,
|
||||
end + sizeof(unsigned long) * s_ind);
|
||||
thread->vm->region.stack_end = end;
|
||||
thread->vm->region.stack_start = start;
|
||||
thread->vm->region.stack_start = (end - size) & USER_STACK_PAGE_MASK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2569,7 +2616,7 @@ unsigned long extend_process_region(struct process_vm *vm,
|
||||
|
||||
if ((rc = add_process_memory_range(vm, end_allocated, new_end_allocated,
|
||||
(p == 0 ? 0 : virt_to_phys(p)), flag, NULL, 0,
|
||||
align_shift, NULL, NULL)) != 0) {
|
||||
align_shift, NULL)) != 0) {
|
||||
ihk_mc_free_pages_user(p, (new_end_allocated - end_allocated) >> PAGE_SHIFT);
|
||||
return end_allocated;
|
||||
}
|
||||
@ -2609,7 +2656,7 @@ void flush_process_memory(struct process_vm *vm)
|
||||
int error;
|
||||
|
||||
dkprintf("flush_process_memory(%p)\n", vm);
|
||||
ihk_mc_spinlock_lock_noirq(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_write_lock_noirq(&vm->memory_range_lock);
|
||||
/* Let concurrent page faults know the VM will be gone */
|
||||
vm->exiting = 1;
|
||||
while ((node = next)) {
|
||||
@ -2627,7 +2674,7 @@ void flush_process_memory(struct process_vm *vm)
|
||||
}
|
||||
}
|
||||
}
|
||||
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_write_unlock_noirq(&vm->memory_range_lock);
|
||||
dkprintf("flush_process_memory(%p):\n", vm);
|
||||
return;
|
||||
}
|
||||
@ -2642,7 +2689,7 @@ void free_process_memory_ranges(struct process_vm *vm)
|
||||
return;
|
||||
}
|
||||
|
||||
ihk_mc_spinlock_lock_noirq(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_write_lock_noirq(&vm->memory_range_lock);
|
||||
while ((node = next)) {
|
||||
range = rb_entry(node, struct vm_range, vm_rb_node);
|
||||
next = rb_next(node);
|
||||
@ -2655,7 +2702,7 @@ void free_process_memory_ranges(struct process_vm *vm)
|
||||
/* through */
|
||||
}
|
||||
}
|
||||
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_write_unlock_noirq(&vm->memory_range_lock);
|
||||
}
|
||||
|
||||
static void free_thread_pages(struct thread *thread)
|
||||
@ -2745,7 +2792,7 @@ free_all_process_memory_range(struct process_vm *vm)
|
||||
struct rb_node *node, *next = rb_first(&vm->vm_range_tree);
|
||||
int error;
|
||||
|
||||
ihk_mc_spinlock_lock_noirq(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_write_lock_noirq(&vm->memory_range_lock);
|
||||
while ((node = next)) {
|
||||
range = rb_entry(node, struct vm_range, vm_rb_node);
|
||||
next = rb_next(node);
|
||||
@ -2758,7 +2805,7 @@ free_all_process_memory_range(struct process_vm *vm)
|
||||
/* through */
|
||||
}
|
||||
}
|
||||
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_write_unlock_noirq(&vm->memory_range_lock);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2814,6 +2861,7 @@ int populate_process_memory(struct process_vm *vm, void *start, size_t len)
|
||||
uintptr_t addr;
|
||||
|
||||
end = (uintptr_t)start + len;
|
||||
preempt_disable();
|
||||
for (addr = (uintptr_t)start; addr < end; addr += PAGE_SIZE) {
|
||||
error = page_fault_process_vm(vm, (void *)addr, reason);
|
||||
if (error) {
|
||||
@ -2827,6 +2875,7 @@ int populate_process_memory(struct process_vm *vm, void *start, size_t len)
|
||||
|
||||
error = 0;
|
||||
out:
|
||||
preempt_enable();
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -3189,7 +3238,7 @@ void sched_init(void)
|
||||
&idle_thread->proc->children_list);
|
||||
|
||||
ihk_mc_init_context(&idle_thread->ctx, NULL, idle);
|
||||
ihk_mc_spinlock_init(&idle_thread->vm->memory_range_lock);
|
||||
ihk_rwspinlock_init(&idle_thread->vm->memory_range_lock);
|
||||
idle_thread->vm->vm_range_tree = RB_ROOT;
|
||||
idle_thread->vm->vm_range_numa_policy_tree = RB_ROOT;
|
||||
idle_thread->proc->pid = 0;
|
||||
@ -3299,8 +3348,11 @@ static void do_migrate(void)
|
||||
|
||||
dkprintf("%s: migrated TID %d from CPU %d to CPU %d\n",
|
||||
__FUNCTION__, req->thread->tid, old_cpu_id, cpu_id);
|
||||
|
||||
|
||||
v->flags |= CPU_FLAG_NEED_RESCHED;
|
||||
/* Kick scheduler on target CPU */
|
||||
ihk_mc_interrupt_cpu(cpu_id, ihk_mc_get_vector(IHK_GV_IKC));
|
||||
|
||||
waitq_wakeup(&req->wq);
|
||||
double_rq_unlock(cur_v, v, irqstate);
|
||||
continue;
|
||||
@ -3326,7 +3378,7 @@ void set_timer(int runq_locked)
|
||||
}
|
||||
|
||||
list_for_each_entry(thread, &v->runq, sched_list) {
|
||||
if (thread->status != PS_RUNNING) {
|
||||
if (thread->status != PS_RUNNING && !thread->spin_sleep) {
|
||||
continue;
|
||||
}
|
||||
num_running++;
|
||||
@ -3336,7 +3388,7 @@ void set_timer(int runq_locked)
|
||||
if (num_running > 1 || v->current->itimer_enabled ||
|
||||
!list_empty(&v->backlog_list)) {
|
||||
if (!cpu_local_var(timer_enabled)) {
|
||||
lapic_timer_enable(/*10000000*/1000000);
|
||||
lapic_timer_enable(1000000);
|
||||
cpu_local_var(timer_enabled) = 1;
|
||||
}
|
||||
}
|
||||
@ -3516,8 +3568,11 @@ void schedule(void)
|
||||
set_timer(1);
|
||||
|
||||
if (switch_ctx) {
|
||||
dkprintf("schedule: %d => %d \n",
|
||||
prev ? prev->tid : 0, next ? next->tid : 0);
|
||||
++cpu_local_var(nr_ctx_switches);
|
||||
dkprintf("%s: %d => %d [ctx sws: %lu]\n",
|
||||
__func__,
|
||||
prev ? prev->tid : 0, next ? next->tid : 0,
|
||||
cpu_local_var(nr_ctx_switches));
|
||||
|
||||
if (prev && prev->ptrace_debugreg) {
|
||||
save_debugreg(prev->ptrace_debugreg);
|
||||
@ -3677,6 +3732,11 @@ int __sched_wakeup_thread(struct thread *thread,
|
||||
|
||||
/* Make interrupt_exit() call schedule() */
|
||||
v->flags |= CPU_FLAG_NEED_RESCHED;
|
||||
|
||||
/* Make sure to check if timer needs to be re-enabled */
|
||||
if (thread->cpu_id == ihk_mc_get_processor_id()) {
|
||||
set_timer(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
status = -EINVAL;
|
||||
|
||||
@ -26,7 +26,6 @@
|
||||
#include <mman.h>
|
||||
#include <bitmap.h>
|
||||
#include <init.h>
|
||||
#include <rusage_private.h>
|
||||
|
||||
//#define DEBUG_PRINT_PROCFS
|
||||
|
||||
@ -360,28 +359,6 @@ static int _process_procfs_request(struct ikc_scd_packet *rpacket, int *result)
|
||||
goto end;
|
||||
}
|
||||
#endif /* POSTK_DEBUG_ARCH_DEP_42 */
|
||||
else if (!strcmp(p, "meminfo")) {
|
||||
ans = snprintf(buf, count,
|
||||
"MemTotal: %10d kB\n"
|
||||
"MemFree: %10d kB\n"
|
||||
"SwapTotal: %10d kB\n"
|
||||
"SwapFree: %10d kB\n"
|
||||
"CommitLimit: %10d kB\n"
|
||||
"Committed_AS: %10d kB\n",
|
||||
rusage_get_total_memory() >> 10,
|
||||
rusage_get_free_memory() >> 10,
|
||||
0, 0,
|
||||
rusage_get_free_memory() >> 10,
|
||||
rusage_get_usage_memory() >> 10);
|
||||
|
||||
if (ans < 0 || ans > count ||
|
||||
buf_add(&buf_top, &buf_cur, buf, ans) < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
ans = 0;
|
||||
goto end;
|
||||
}
|
||||
else {
|
||||
kprintf("unsupported procfs entry: %s\n", p);
|
||||
goto end;
|
||||
@ -459,7 +436,7 @@ static int _process_procfs_request(struct ikc_scd_packet *rpacket, int *result)
|
||||
if (strcmp(p, "maps") == 0) {
|
||||
struct vm_range *range;
|
||||
|
||||
if (!ihk_mc_spinlock_trylock_noirq(&vm->memory_range_lock)) {
|
||||
if (!ihk_rwspinlock_read_trylock_noirq(&vm->memory_range_lock)) {
|
||||
if (!result) {
|
||||
if ((err = procfs_backlog(vm, rpacket))) {
|
||||
goto err;
|
||||
@ -505,14 +482,14 @@ static int _process_procfs_request(struct ikc_scd_packet *rpacket, int *result)
|
||||
|
||||
if (ans < 0 || ans > count ||
|
||||
buf_add(&buf_top, &buf_cur, buf, ans) < 0) {
|
||||
ihk_mc_spinlock_unlock_noirq(
|
||||
ihk_rwspinlock_read_unlock_noirq(
|
||||
&vm->memory_range_lock);
|
||||
goto err;
|
||||
}
|
||||
range = next_process_memory_range(vm, range);
|
||||
}
|
||||
|
||||
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_read_unlock_noirq(&vm->memory_range_lock);
|
||||
|
||||
ans = 0;
|
||||
goto end;
|
||||
@ -535,7 +512,7 @@ static int _process_procfs_request(struct ikc_scd_packet *rpacket, int *result)
|
||||
start = (offset / sizeof(uint64_t)) << PAGE_SHIFT;
|
||||
end = start + ((count / sizeof(uint64_t)) << PAGE_SHIFT);
|
||||
|
||||
if (!ihk_mc_spinlock_trylock_noirq(&vm->memory_range_lock)) {
|
||||
if (!ihk_rwspinlock_read_trylock_noirq(&vm->memory_range_lock)) {
|
||||
if (!result) {
|
||||
if ((err = procfs_backlog(vm, rpacket))) {
|
||||
goto err;
|
||||
@ -555,7 +532,7 @@ static int _process_procfs_request(struct ikc_scd_packet *rpacket, int *result)
|
||||
++_buf;
|
||||
}
|
||||
|
||||
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_read_unlock_noirq(&vm->memory_range_lock);
|
||||
|
||||
dprintf("/proc/pagemap: 0x%lx - 0x%lx, count: %d\n",
|
||||
start, end, count);
|
||||
@ -587,7 +564,7 @@ static int _process_procfs_request(struct ikc_scd_packet *rpacket, int *result)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!ihk_mc_spinlock_trylock_noirq(&vm->memory_range_lock)) {
|
||||
if (!ihk_rwspinlock_read_trylock_noirq(&vm->memory_range_lock)) {
|
||||
if (!result) {
|
||||
if ((err = procfs_backlog(vm, rpacket))) {
|
||||
goto err;
|
||||
@ -604,7 +581,7 @@ static int _process_procfs_request(struct ikc_scd_packet *rpacket, int *result)
|
||||
lockedsize += range->end - range->start;
|
||||
range = next_process_memory_range(vm, range);
|
||||
}
|
||||
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_read_unlock_noirq(&vm->memory_range_lock);
|
||||
|
||||
cpu_bitmask = &bitmasks[bitmasks_offset];
|
||||
bitmasks_offset += bitmap_scnprintf(cpu_bitmask,
|
||||
|
||||
267
kernel/profile.c
267
kernel/profile.c
@ -106,153 +106,108 @@ void profile_event_add(enum profile_event_type type, uint64_t tsc)
|
||||
event->tsc += tsc;
|
||||
}
|
||||
|
||||
void profile_print_thread_stats(struct thread *thread)
|
||||
static void print_profile_events(struct profile_event *profile_events,
|
||||
char *full_hdr_fmt,
|
||||
char *hdr_prefix,
|
||||
int id,
|
||||
unsigned long elapsed_ts)
|
||||
{
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
flags = kprintf_lock();
|
||||
__kprintf(full_hdr_fmt, id, elapsed_ts / 1000);
|
||||
|
||||
__kprintf("%3s: %5s (%3s,%20s): %6s %7s offl: %6s %7s (%6s)\n",
|
||||
"ID", "<num>", "num", "(syscall/event) name", "cnt",
|
||||
"cycles", "cnt", "cycles", "perc");
|
||||
|
||||
for (i = 0; i < PROFILE_SYSCALL_MAX; ++i) {
|
||||
if (!profile_events[i].cnt &&
|
||||
!profile_events[i + PROFILE_SYSCALL_MAX].cnt)
|
||||
continue;
|
||||
|
||||
__kprintf("%s: %4d (%3d,%20s): %6u %6luk "
|
||||
"offl: %6u %6luk (%2d.%2d%%)\n",
|
||||
hdr_prefix,
|
||||
id,
|
||||
i,
|
||||
syscall_name[i],
|
||||
profile_events[i].cnt,
|
||||
profile_events[i].tsc / 1000,
|
||||
profile_events[i + PROFILE_SYSCALL_MAX].cnt,
|
||||
profile_events[i + PROFILE_SYSCALL_MAX].tsc /
|
||||
1000,
|
||||
(profile_events[i].tsc ?
|
||||
profile_events[i].tsc * 100
|
||||
/ elapsed_ts : 0),
|
||||
(profile_events[i].tsc ?
|
||||
(profile_events[i].tsc * 10000
|
||||
/ elapsed_ts) % 100 : 0)
|
||||
);
|
||||
}
|
||||
|
||||
for (i = PROFILE_EVENT_MIN; i < PROFILE_EVENT_MAX; ++i) {
|
||||
if (!profile_events[i].cnt)
|
||||
continue;
|
||||
|
||||
__kprintf("%s: %4d (%24s): %6u %6lu\n",
|
||||
hdr_prefix,
|
||||
id,
|
||||
profile_event_names[i - PROFILE_EVENT_MIN],
|
||||
profile_events[i].cnt,
|
||||
(profile_events[i].tsc /
|
||||
(profile_events[i].cnt ?
|
||||
profile_events[i].cnt : 1))
|
||||
,
|
||||
(profile_events[i].tsc &&
|
||||
elapsed_ts ?
|
||||
profile_events[i].tsc * 100
|
||||
/ elapsed_ts : 0),
|
||||
(profile_events[i].tsc &&
|
||||
elapsed_ts ?
|
||||
(profile_events[i].tsc * 10000
|
||||
/ elapsed_ts) % 100 : 0)
|
||||
);
|
||||
}
|
||||
|
||||
kprintf_unlock(flags);
|
||||
}
|
||||
|
||||
|
||||
void profile_print_thread_stats(struct thread *thread)
|
||||
{
|
||||
if (!thread->profile_events)
|
||||
return;
|
||||
|
||||
/* Not yet accumulated period? */
|
||||
if (thread->profile_start_ts) {
|
||||
thread->profile_elapsed_ts += (rdtsc() - thread->profile_start_ts);
|
||||
thread->profile_elapsed_ts += (rdtsc() -
|
||||
thread->profile_start_ts);
|
||||
}
|
||||
|
||||
flags = kprintf_lock();
|
||||
|
||||
__kprintf("TID: %4d elapsed cycles (excluding idle): %luk\n",
|
||||
thread->tid,
|
||||
thread->profile_elapsed_ts / 1000);
|
||||
|
||||
for (i = 0; i < PROFILE_SYSCALL_MAX; ++i) {
|
||||
if (!thread->profile_events[i].cnt &&
|
||||
!thread->profile_events[i + PROFILE_SYSCALL_MAX].cnt)
|
||||
continue;
|
||||
|
||||
__kprintf("TID: %4d (%3d,%20s): %6u %6luk offl: %6u %6luk (%2d.%2d%%)\n",
|
||||
thread->tid,
|
||||
i,
|
||||
syscall_name[i],
|
||||
thread->profile_events[i].cnt,
|
||||
(thread->profile_events[i].tsc /
|
||||
(thread->profile_events[i].cnt ?
|
||||
thread->profile_events[i].cnt : 1))
|
||||
/ 1000,
|
||||
thread->profile_events[i + PROFILE_SYSCALL_MAX].cnt,
|
||||
(thread->profile_events[i + PROFILE_SYSCALL_MAX].tsc /
|
||||
(thread->profile_events[i + PROFILE_SYSCALL_MAX].cnt ?
|
||||
thread->profile_events[i + PROFILE_SYSCALL_MAX].cnt : 1))
|
||||
/ 1000,
|
||||
(thread->profile_events[i].tsc ?
|
||||
thread->profile_events[i].tsc * 100
|
||||
/ thread->profile_elapsed_ts : 0),
|
||||
(thread->profile_events[i].tsc ?
|
||||
(thread->profile_events[i].tsc * 10000
|
||||
/ thread->profile_elapsed_ts) % 100 : 0)
|
||||
);
|
||||
}
|
||||
|
||||
for (i = PROFILE_EVENT_MIN; i < PROFILE_EVENT_MAX; ++i) {
|
||||
|
||||
if (!thread->profile_events[i].cnt)
|
||||
continue;
|
||||
|
||||
__kprintf("TID: %4d (%24s): %6u %6luk \n",
|
||||
thread->tid,
|
||||
profile_event_names[i - PROFILE_EVENT_MIN],
|
||||
thread->profile_events[i].cnt,
|
||||
(thread->profile_events[i].tsc /
|
||||
(thread->profile_events[i].cnt ?
|
||||
thread->profile_events[i].cnt : 1))
|
||||
/ 1000,
|
||||
(thread->profile_events[i].tsc ?
|
||||
thread->profile_events[i].tsc * 100
|
||||
/ thread->profile_elapsed_ts : 0),
|
||||
(thread->profile_events[i].tsc ?
|
||||
(thread->profile_events[i].tsc * 10000
|
||||
/ thread->profile_elapsed_ts) % 100 : 0)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
kprintf_unlock(flags);
|
||||
print_profile_events(thread->profile_events,
|
||||
"TID: %4d elapsed cycles (excluding idle): %luk\n",
|
||||
"TID",
|
||||
thread->tid,
|
||||
thread->profile_elapsed_ts);
|
||||
}
|
||||
|
||||
void profile_print_proc_stats(struct process *proc)
|
||||
{
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
if (!proc->profile_events || !proc->profile_elapsed_ts)
|
||||
return;
|
||||
|
||||
flags = kprintf_lock();
|
||||
__kprintf("PID: %4d elapsed cycles for all threads (excluding idle): %luk\n",
|
||||
proc->pid,
|
||||
proc->profile_elapsed_ts / 1000);
|
||||
|
||||
for (i = 0; i < PROFILE_SYSCALL_MAX; ++i) {
|
||||
if (!proc->profile_events[i].cnt &&
|
||||
!proc->profile_events[i + PROFILE_SYSCALL_MAX].cnt)
|
||||
continue;
|
||||
|
||||
__kprintf("PID: %4d (%3d,%20s): %6u %6luk offl: %6u %6luk (%2d.%2d%%)\n",
|
||||
proc->pid,
|
||||
i,
|
||||
syscall_name[i],
|
||||
proc->profile_events[i].cnt,
|
||||
(proc->profile_events[i].tsc /
|
||||
(proc->profile_events[i].cnt ?
|
||||
proc->profile_events[i].cnt : 1))
|
||||
/ 1000,
|
||||
proc->profile_events[i + PROFILE_SYSCALL_MAX].cnt,
|
||||
(proc->profile_events[i + PROFILE_SYSCALL_MAX].tsc /
|
||||
(proc->profile_events[i + PROFILE_SYSCALL_MAX].cnt ?
|
||||
proc->profile_events[i + PROFILE_SYSCALL_MAX].cnt : 1))
|
||||
/ 1000,
|
||||
(proc->profile_events[i].tsc ?
|
||||
proc->profile_events[i].tsc * 100
|
||||
/ proc->profile_elapsed_ts : 0),
|
||||
(proc->profile_events[i].tsc ?
|
||||
(proc->profile_events[i].tsc * 10000
|
||||
/ proc->profile_elapsed_ts) % 100 : 0)
|
||||
);
|
||||
}
|
||||
|
||||
for (i = PROFILE_EVENT_MIN; i < PROFILE_EVENT_MAX; ++i) {
|
||||
|
||||
if (!proc->profile_events[i].cnt)
|
||||
continue;
|
||||
|
||||
// __kprintf("PID: %4d (%24s): %6u %6luk \n",
|
||||
__kprintf("PID: %4d (%24s): %6u %6lu \n",
|
||||
proc->pid,
|
||||
profile_event_names[i - PROFILE_EVENT_MIN],
|
||||
proc->profile_events[i].cnt,
|
||||
(proc->profile_events[i].tsc /
|
||||
(proc->profile_events[i].cnt ?
|
||||
proc->profile_events[i].cnt : 1))
|
||||
// / 1000
|
||||
,
|
||||
(proc->profile_events[i].tsc &&
|
||||
proc->profile_elapsed_ts ?
|
||||
proc->profile_events[i].tsc * 100
|
||||
/ proc->profile_elapsed_ts : 0),
|
||||
(proc->profile_events[i].tsc &&
|
||||
proc->profile_elapsed_ts ?
|
||||
(proc->profile_events[i].tsc * 10000
|
||||
/ proc->profile_elapsed_ts) % 100 : 0)
|
||||
);
|
||||
}
|
||||
|
||||
kprintf_unlock(flags);
|
||||
print_profile_events(proc->profile_events,
|
||||
"PID: %4d elapsed cycles for all threads (excluding idle): %luk\n",
|
||||
"PID",
|
||||
proc->pid,
|
||||
proc->profile_elapsed_ts);
|
||||
}
|
||||
|
||||
int profile_accumulate_and_print_job_events(struct process *proc)
|
||||
{
|
||||
int i;
|
||||
unsigned long flags;
|
||||
struct mcs_lock_node mcs_node;
|
||||
|
||||
mcs_lock_lock(&job_profile_lock, &mcs_node);
|
||||
@ -297,68 +252,20 @@ int profile_accumulate_and_print_job_events(struct process *proc)
|
||||
|
||||
/* Last process? */
|
||||
if (job_nr_processes_left == 0) {
|
||||
flags = kprintf_lock();
|
||||
__kprintf("JOB: (%2d) elapsed cycles for all threads (excluding idle): %luk\n",
|
||||
job_nr_processes,
|
||||
job_elapsed_ts / 1000);
|
||||
|
||||
for (i = 0; i < PROFILE_SYSCALL_MAX; ++i) {
|
||||
if (!job_profile_events[i].cnt &&
|
||||
!job_profile_events[i + PROFILE_SYSCALL_MAX].cnt)
|
||||
continue;
|
||||
|
||||
__kprintf("JOB: (%2d) (%3d,%20s): %6u %6luk offl: %6u %6luk (%2d.%2d%%)\n",
|
||||
job_nr_processes,
|
||||
i,
|
||||
syscall_name[i],
|
||||
job_profile_events[i].cnt,
|
||||
(job_profile_events[i].tsc /
|
||||
(job_profile_events[i].cnt ?
|
||||
job_profile_events[i].cnt : 1))
|
||||
/ 1000,
|
||||
job_profile_events[i + PROFILE_SYSCALL_MAX].cnt,
|
||||
(job_profile_events[i + PROFILE_SYSCALL_MAX].tsc /
|
||||
(job_profile_events[i + PROFILE_SYSCALL_MAX].cnt ?
|
||||
job_profile_events[i + PROFILE_SYSCALL_MAX].cnt : 1))
|
||||
/ 1000,
|
||||
(job_profile_events[i].tsc ?
|
||||
job_profile_events[i].tsc * 100
|
||||
/ job_elapsed_ts : 0),
|
||||
(job_profile_events[i].tsc ?
|
||||
(job_profile_events[i].tsc * 10000
|
||||
/ job_elapsed_ts) % 100 : 0)
|
||||
);
|
||||
|
||||
job_profile_events[i].tsc = 0;
|
||||
job_profile_events[i].cnt = 0;
|
||||
job_profile_events[i + PROFILE_SYSCALL_MAX].tsc = 0;
|
||||
job_profile_events[i + PROFILE_SYSCALL_MAX].cnt = 0;
|
||||
}
|
||||
|
||||
for (i = PROFILE_EVENT_MIN; i < PROFILE_EVENT_MAX; ++i) {
|
||||
|
||||
if (!job_profile_events[i].cnt)
|
||||
continue;
|
||||
|
||||
__kprintf("JOB: (%2d) (%24s): %6u %6luk \n",
|
||||
job_nr_processes,
|
||||
profile_event_names[i - PROFILE_EVENT_MIN],
|
||||
job_profile_events[i].cnt,
|
||||
(job_profile_events[i].tsc /
|
||||
(job_profile_events[i].cnt ?
|
||||
job_profile_events[i].cnt : 1))
|
||||
/ 1000);
|
||||
|
||||
job_profile_events[i].tsc = 0;
|
||||
job_profile_events[i].cnt = 0;
|
||||
}
|
||||
|
||||
kprintf_unlock(flags);
|
||||
print_profile_events(job_profile_events,
|
||||
"JOB: (%2d) elapsed cycles for all threads (excluding idle): %luk\n",
|
||||
"JOB",
|
||||
job_nr_processes,
|
||||
job_elapsed_ts);
|
||||
|
||||
/* Reset job process indicators */
|
||||
job_nr_processes = -1;
|
||||
job_nr_processes_left = -1;
|
||||
job_elapsed_ts = 0;
|
||||
|
||||
memset(job_profile_events, 0, sizeof(*job_profile_events) *
|
||||
PROFILE_EVENT_MAX);
|
||||
}
|
||||
|
||||
mcs_lock_unlock(&job_profile_lock, &mcs_node);
|
||||
|
||||
892
kernel/syscall.c
892
kernel/syscall.c
File diff suppressed because it is too large
Load Diff
314
kernel/xpmem.c
314
kernel/xpmem.c
@ -423,11 +423,6 @@ static int xpmem_make(
|
||||
struct xpmem_thread_group *seg_tg;
|
||||
struct xpmem_segment *seg;
|
||||
struct mcs_rwlock_node_irqsave lock;
|
||||
struct process_vm *vm = cpu_local_var(current)->vm;
|
||||
int ret;
|
||||
pte_t *seg_pte = NULL;
|
||||
size_t pgsize = 0, seg_size = 0;
|
||||
unsigned long pf_addr;
|
||||
|
||||
XPMEM_DEBUG("call: vaddr=0x%lx, size=0x%lx, permit_type=%d, "
|
||||
"permit_value=0%04lo",
|
||||
@ -459,27 +454,6 @@ static int xpmem_make(
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Page-in segment area */
|
||||
pf_addr = vaddr;
|
||||
while (pf_addr < vaddr + size) {
|
||||
ret = page_fault_process_vm(vm, (void *)pf_addr,
|
||||
PF_POPULATE | PF_WRITE | PF_USER);
|
||||
if (ret) {
|
||||
xpmem_tg_deref(seg_tg);
|
||||
return -ENOENT;
|
||||
}
|
||||
seg_pte = xpmem_vaddr_to_pte(vm, pf_addr, &pgsize);
|
||||
if (!seg_pte || pte_is_null(seg_pte)) {
|
||||
xpmem_tg_deref(seg_tg);
|
||||
return -ENOENT;
|
||||
}
|
||||
pf_addr += pgsize;
|
||||
seg_size += pgsize;
|
||||
}
|
||||
if (seg_size > size) {
|
||||
size = seg_size;
|
||||
}
|
||||
|
||||
segid = xpmem_make_segid(seg_tg);
|
||||
if (segid < 0) {
|
||||
xpmem_tg_deref(seg_tg);
|
||||
@ -1037,6 +1011,7 @@ static int xpmem_attach(
|
||||
struct xpmem_segment *seg;
|
||||
struct xpmem_attachment *att;
|
||||
struct mcs_rwlock_node_irqsave at_lock;
|
||||
struct vm_range *vmr;
|
||||
struct process_vm *vm = cpu_local_var(current)->vm;
|
||||
|
||||
XPMEM_DEBUG("call: apid=0x%lx, offset=0x%lx, size=0x%lx, vaddr=0x%lx, "
|
||||
@ -1130,38 +1105,58 @@ static int xpmem_attach(
|
||||
if (flags & MAP_FIXED) {
|
||||
struct vm_range *existing_vmr;
|
||||
|
||||
ihk_mc_spinlock_lock_noirq(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_read_lock_noirq(&vm->memory_range_lock);
|
||||
|
||||
existing_vmr = lookup_process_memory_range(vm, vaddr,
|
||||
vaddr + size);
|
||||
|
||||
ihk_rwspinlock_read_unlock_noirq(&vm->memory_range_lock);
|
||||
|
||||
for (; existing_vmr && existing_vmr->start < vaddr + size;
|
||||
existing_vmr = next_process_memory_range(vm,
|
||||
existing_vmr)) {
|
||||
if (xpmem_is_private_data(existing_vmr)) {
|
||||
ret = -EINVAL;
|
||||
ihk_mc_spinlock_unlock_noirq(
|
||||
&vm->memory_range_lock);
|
||||
goto out_2;
|
||||
}
|
||||
}
|
||||
|
||||
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||
}
|
||||
|
||||
flags |= MAP_ANONYMOUS;
|
||||
XPMEM_DEBUG("do_mmap(): vaddr=0x%lx, size=0x%lx, prot_flags=0x%lx, "
|
||||
"flags=0x%lx, fd=%d, offset=0x%lx",
|
||||
vaddr, size, prot_flags, flags, mckfd->fd, offset);
|
||||
/* The new range is associated with shmobj because of
|
||||
/* The new range uses on-demand paging and is associated with shmobj because of
|
||||
MAP_ANONYMOUS && !MAP_PRIVATE && MAP_SHARED */
|
||||
at_vaddr = do_mmap(vaddr, size, prot_flags, flags, mckfd->fd,
|
||||
offset, VR_XPMEM, att);
|
||||
at_vaddr = do_mmap(vaddr, size, prot_flags, flags, mckfd->fd, offset);
|
||||
if (IS_ERR((void *)(uintptr_t)at_vaddr)) {
|
||||
ret = at_vaddr;
|
||||
goto out_2;
|
||||
}
|
||||
XPMEM_DEBUG("at_vaddr=0x%lx", at_vaddr);
|
||||
att->at_vaddr = at_vaddr;
|
||||
|
||||
ihk_rwspinlock_read_lock_noirq(&vm->memory_range_lock);
|
||||
|
||||
vmr = lookup_process_memory_range(vm, at_vaddr, at_vaddr + 1);
|
||||
|
||||
/* To identify pages of XPMEM attachment for rusage accounting */
|
||||
if(vmr->memobj) {
|
||||
vmr->memobj->flags |= MF_XPMEM;
|
||||
} else {
|
||||
ekprintf("%s: vmr->memobj equals to NULL\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
ihk_rwspinlock_read_unlock_noirq(&vm->memory_range_lock);
|
||||
|
||||
if (!vmr) {
|
||||
ret = -ENOENT;
|
||||
goto out_2;
|
||||
}
|
||||
vmr->private_data = att;
|
||||
|
||||
|
||||
att->at_vmr = vmr;
|
||||
|
||||
*at_vaddr_p = at_vaddr + offset_in_page(att->vaddr);
|
||||
|
||||
@ -1187,6 +1182,7 @@ out_1:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int xpmem_detach(
|
||||
unsigned long at_vaddr)
|
||||
{
|
||||
@ -1199,18 +1195,18 @@ static int xpmem_detach(
|
||||
|
||||
XPMEM_DEBUG("call: at_vaddr=0x%lx", at_vaddr);
|
||||
|
||||
ihk_mc_spinlock_lock_noirq(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_write_lock_noirq(&vm->memory_range_lock);
|
||||
|
||||
range = lookup_process_memory_range(vm, at_vaddr, at_vaddr + 1);
|
||||
|
||||
if (!range || range->start > at_vaddr) {
|
||||
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_write_unlock_noirq(&vm->memory_range_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
att = (struct xpmem_attachment *)range->private_data;
|
||||
if (att == NULL) {
|
||||
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_write_unlock_noirq(&vm->memory_range_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1220,7 +1216,7 @@ static int xpmem_detach(
|
||||
|
||||
if (att->flags & XPMEM_FLAG_DESTROYING) {
|
||||
mcs_rwlock_writer_unlock(&att->at_lock, &at_lock);
|
||||
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_write_unlock_noirq(&vm->memory_range_lock);
|
||||
xpmem_att_deref(att);
|
||||
return 0;
|
||||
}
|
||||
@ -1233,7 +1229,7 @@ static int xpmem_detach(
|
||||
att->flags &= ~XPMEM_FLAG_DESTROYING;
|
||||
xpmem_ap_deref(ap);
|
||||
mcs_rwlock_writer_unlock(&att->at_lock, &at_lock);
|
||||
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_write_unlock_noirq(&vm->memory_range_lock);
|
||||
xpmem_att_deref(att);
|
||||
return -EACCES;
|
||||
}
|
||||
@ -1253,7 +1249,7 @@ static int xpmem_detach(
|
||||
ekprintf("%s: ERROR: xpmem_vm_munmap() failed %d\n",
|
||||
__FUNCTION__, ret);
|
||||
}
|
||||
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_write_unlock_noirq(&vm->memory_range_lock);
|
||||
DBUG_ON(ret != 0);
|
||||
|
||||
att->flags &= ~XPMEM_FLAG_VALIDPTEs;
|
||||
@ -1416,21 +1412,24 @@ static void xpmem_detach_att(
|
||||
|
||||
XPMEM_DEBUG("call: apid=0x%lx, att=0x%p", ap->apid, att);
|
||||
|
||||
XPMEM_DEBUG("detaching att->vm=0x%p", (void *)att->vm);
|
||||
XPMEM_DEBUG("detaching current->vm=0x%p, att->vm=0x%p",
|
||||
(void *)cpu_local_var(current)->vm, (void *)att->vm);
|
||||
|
||||
vm = cpu_local_var(current)->vm ? cpu_local_var(current)->vm : att->vm;
|
||||
|
||||
ihk_rwspinlock_read_lock_noirq(&vm->memory_range_lock);
|
||||
|
||||
mcs_rwlock_writer_lock(&att->at_lock, &at_lock);
|
||||
|
||||
if (att->flags & XPMEM_FLAG_DESTROYING) {
|
||||
mcs_rwlock_writer_unlock(&att->at_lock, &at_lock);
|
||||
ihk_rwspinlock_read_unlock_noirq(&vm->memory_range_lock);
|
||||
XPMEM_DEBUG("return: XPMEM_FLAG_DESTROYING");
|
||||
return;
|
||||
}
|
||||
att->flags |= XPMEM_FLAG_DESTROYING;
|
||||
|
||||
vm = att->vm;
|
||||
ihk_mc_spinlock_lock_noirq(&vm->memory_range_lock);
|
||||
|
||||
range = lookup_process_memory_range(vm,
|
||||
range = lookup_process_memory_range(cpu_local_var(current)->vm,
|
||||
att->at_vaddr, att->at_vaddr + 1);
|
||||
|
||||
if (!range || range->start > att->at_vaddr) {
|
||||
@ -1438,7 +1437,7 @@ static void xpmem_detach_att(
|
||||
list_del_init(&att->att_list);
|
||||
ihk_mc_spinlock_unlock_noirq(&ap->lock);
|
||||
mcs_rwlock_writer_unlock(&att->at_lock, &at_lock);
|
||||
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_read_unlock_noirq(&vm->memory_range_lock);
|
||||
xpmem_att_destroyable(att);
|
||||
XPMEM_DEBUG("return: range=%p");
|
||||
return;
|
||||
@ -1467,13 +1466,14 @@ static void xpmem_detach_att(
|
||||
|
||||
XPMEM_DEBUG("xpmem_vm_munmap(): start=0x%lx, len=0x%lx",
|
||||
range->start, att->at_size);
|
||||
ret = xpmem_vm_munmap(vm, (void *)range->start, att->at_size);
|
||||
ret = xpmem_vm_munmap(cpu_local_var(current)->vm, (void *)range->start,
|
||||
att->at_size);
|
||||
if (ret) {
|
||||
ekprintf("%s: ERROR: xpmem_vm_munmap() failed %d\n",
|
||||
__FUNCTION__, ret);
|
||||
}
|
||||
|
||||
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||
ihk_rwspinlock_read_unlock_noirq(&vm->memory_range_lock);
|
||||
|
||||
xpmem_att_destroyable(att);
|
||||
|
||||
@ -1576,7 +1576,7 @@ static void xpmem_clear_PTEs_of_att(
|
||||
XPMEM_DEBUG("call: att=0x%p, start=0x%lx, end=0x%lx",
|
||||
att, start, end);
|
||||
|
||||
ihk_mc_spinlock_lock_noirq(&att->vm->memory_range_lock);
|
||||
ihk_rwspinlock_read_lock_noirq(&att->vm->memory_range_lock);
|
||||
mcs_rwlock_writer_lock(&att->at_lock, &at_lock);
|
||||
|
||||
if (att->flags & XPMEM_FLAG_VALIDPTEs) {
|
||||
@ -1636,7 +1636,7 @@ static void xpmem_clear_PTEs_of_att(
|
||||
}
|
||||
out:
|
||||
mcs_rwlock_writer_unlock(&att->at_lock, &at_lock);
|
||||
ihk_mc_spinlock_unlock_noirq(&att->vm->memory_range_lock);
|
||||
ihk_rwspinlock_read_unlock_noirq(&att->vm->memory_range_lock);
|
||||
|
||||
XPMEM_DEBUG("return: ");
|
||||
}
|
||||
@ -1664,11 +1664,16 @@ int xpmem_remove_process_memory_range(
|
||||
|
||||
xpmem_att_ref(att);
|
||||
|
||||
ihk_rwspinlock_read_lock_noirq(
|
||||
&cpu_local_var(current)->vm->memory_range_lock);
|
||||
|
||||
mcs_rwlock_writer_lock(&att->at_lock, &at_lock);
|
||||
|
||||
if (att->flags & XPMEM_FLAG_DESTROYING) {
|
||||
mcs_rwlock_writer_unlock(&att->at_lock, &at_lock);
|
||||
xpmem_att_deref(att);
|
||||
XPMEM_DEBUG("already cleaned up");
|
||||
goto out;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vmr->start == att->at_vaddr &&
|
||||
@ -1697,7 +1702,7 @@ int xpmem_remove_process_memory_range(
|
||||
else {
|
||||
remaining_vaddr = vmr->end;
|
||||
remaining_vmr = lookup_process_memory_range(
|
||||
vm, remaining_vaddr - 1,
|
||||
cpu_local_var(current)->vm, remaining_vaddr - 1,
|
||||
remaining_vaddr);
|
||||
if (!remaining_vmr) {
|
||||
ekprintf("%s: ERROR: vm_range is NULL\n", __FUNCTION__);
|
||||
@ -1718,7 +1723,7 @@ int xpmem_remove_process_memory_range(
|
||||
}
|
||||
|
||||
remaining_vmr = lookup_process_memory_range(
|
||||
vm, remaining_vaddr,
|
||||
cpu_local_var(current)->vm, remaining_vaddr,
|
||||
remaining_vaddr + 1);
|
||||
if (!remaining_vmr) {
|
||||
ekprintf("%s: ERROR: vm_range is NULL\n", __FUNCTION__);
|
||||
@ -1742,6 +1747,9 @@ int xpmem_remove_process_memory_range(
|
||||
out:
|
||||
mcs_rwlock_writer_unlock(&att->at_lock, &at_lock);
|
||||
|
||||
ihk_rwspinlock_read_unlock_noirq(
|
||||
&cpu_local_var(current)->vm->memory_range_lock);
|
||||
|
||||
xpmem_att_deref(att);
|
||||
|
||||
XPMEM_DEBUG("return: ret=%d", 0);
|
||||
@ -1870,117 +1878,6 @@ out_1:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int xpmem_update_process_page_table(
|
||||
struct process_vm *vm, struct vm_range *vmr)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long seg_vaddr = 0;
|
||||
unsigned long vaddr = vmr->start;
|
||||
pte_t *pte = NULL;
|
||||
pte_t *seg_pte = NULL;
|
||||
struct xpmem_thread_group *ap_tg;
|
||||
struct xpmem_thread_group *seg_tg;
|
||||
struct xpmem_access_permit *ap;
|
||||
struct xpmem_attachment *att;
|
||||
struct xpmem_segment *seg;
|
||||
size_t seg_pgsize;
|
||||
size_t pgsize;
|
||||
|
||||
XPMEM_DEBUG("call: vmr=0x%p", vmr);
|
||||
|
||||
att = (struct xpmem_attachment *)vmr->private_data;
|
||||
if (att == NULL) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
xpmem_att_ref(att);
|
||||
ap = att->ap;
|
||||
xpmem_ap_ref(ap);
|
||||
ap_tg = ap->tg;
|
||||
xpmem_tg_ref(ap_tg);
|
||||
|
||||
if ((ap->flags & XPMEM_FLAG_DESTROYING) ||
|
||||
(ap_tg->flags & XPMEM_FLAG_DESTROYING)) {
|
||||
ret = -EFAULT;
|
||||
goto out_1;
|
||||
}
|
||||
|
||||
DBUG_ON(cpu_local_var(current)->proc->pid != ap_tg->tgid);
|
||||
DBUG_ON(ap->mode != XPMEM_RDWR);
|
||||
|
||||
seg = ap->seg;
|
||||
xpmem_seg_ref(seg);
|
||||
seg_tg = seg->tg;
|
||||
xpmem_tg_ref(seg_tg);
|
||||
|
||||
if ((seg->flags & XPMEM_FLAG_DESTROYING) ||
|
||||
(seg_tg->flags & XPMEM_FLAG_DESTROYING)) {
|
||||
ret = -ENOENT;
|
||||
goto out_2;
|
||||
}
|
||||
|
||||
att->at_vaddr = vmr->start;
|
||||
att->at_vmr = vmr;
|
||||
|
||||
if ((att->flags & XPMEM_FLAG_DESTROYING) ||
|
||||
(ap_tg->flags & XPMEM_FLAG_DESTROYING) ||
|
||||
(seg_tg->flags & XPMEM_FLAG_DESTROYING)) {
|
||||
goto out_2;
|
||||
}
|
||||
|
||||
seg_vaddr = (att->vaddr & PAGE_MASK) + (vaddr - att->at_vaddr);
|
||||
XPMEM_DEBUG("vaddr=%lx, seg_vaddr=%lx", vaddr, seg_vaddr);
|
||||
while (vaddr < vmr->end) {
|
||||
ret = xpmem_ensure_valid_page(seg, seg_vaddr);
|
||||
if (ret != 0) {
|
||||
goto out_2;
|
||||
}
|
||||
|
||||
seg_pte = xpmem_vaddr_to_pte(seg_tg->vm, seg_vaddr,
|
||||
&seg_pgsize);
|
||||
|
||||
if (seg_pte && !pte_is_null(seg_pte)) {
|
||||
pte = xpmem_vaddr_to_pte(cpu_local_var(current)->vm,
|
||||
vaddr, &pgsize);
|
||||
if (pte && !pte_is_null(pte)) {
|
||||
if (*seg_pte != *pte) {
|
||||
ret = -EFAULT;
|
||||
ekprintf("%s: ERROR: pte mismatch: "
|
||||
"0x%lx != 0x%lx\n",
|
||||
__func__, *seg_pte, *pte);
|
||||
}
|
||||
|
||||
ihk_atomic_dec(&seg->tg->n_pinned);
|
||||
goto out_2;
|
||||
}
|
||||
|
||||
ret = xpmem_remap_pte(vm, vmr, vaddr,
|
||||
0, seg, seg_vaddr);
|
||||
if (ret) {
|
||||
ekprintf("%s: ERROR: xpmem_remap_pte() failed %d\n",
|
||||
__func__, ret);
|
||||
}
|
||||
}
|
||||
flush_tlb_single(vaddr);
|
||||
att->flags |= XPMEM_FLAG_VALIDPTEs;
|
||||
|
||||
seg_vaddr += seg_pgsize;
|
||||
vaddr += seg_pgsize;
|
||||
}
|
||||
|
||||
out_2:
|
||||
xpmem_tg_deref(seg_tg);
|
||||
xpmem_seg_deref(seg);
|
||||
|
||||
out_1:
|
||||
xpmem_att_deref(att);
|
||||
xpmem_ap_deref(ap);
|
||||
xpmem_tg_deref(ap_tg);
|
||||
|
||||
XPMEM_DEBUG("return: ret=%d", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int xpmem_remap_pte(
|
||||
struct process_vm *vm,
|
||||
@ -2008,13 +1905,13 @@ static int xpmem_remap_pte(
|
||||
"seg_vaddr=0x%lx",
|
||||
vmr, vaddr, reason, seg->segid, seg_vaddr);
|
||||
|
||||
if (is_remote_vm(seg_tg->vm)) {
|
||||
ihk_mc_spinlock_lock_noirq(&seg_tg->vm->memory_range_lock);
|
||||
}
|
||||
ihk_rwspinlock_read_lock_noirq(&seg_tg->vm->memory_range_lock);
|
||||
|
||||
seg_vmr = lookup_process_memory_range(seg_tg->vm, seg_vaddr,
|
||||
seg_vaddr + 1);
|
||||
|
||||
ihk_rwspinlock_read_unlock_noirq(&seg_tg->vm->memory_range_lock);
|
||||
|
||||
if (!seg_vmr) {
|
||||
ret = -EFAULT;
|
||||
ekprintf("%s: ERROR: lookup_process_memory_range() failed\n",
|
||||
@ -2025,7 +1922,6 @@ static int xpmem_remap_pte(
|
||||
seg_pte = ihk_mc_pt_lookup_pte(seg_tg->vm->address_space->page_table,
|
||||
(void *)seg_vaddr, seg_vmr->pgshift, &seg_pgaddr, &seg_pgsize,
|
||||
&seg_p2align);
|
||||
|
||||
if (!seg_pte) {
|
||||
ret = -EFAULT;
|
||||
ekprintf("%s: ERROR: ihk_mc_pt_lookup_pte() failed\n",
|
||||
@ -2049,34 +1945,31 @@ static int xpmem_remap_pte(
|
||||
att_attr = arch_vrflag_to_ptattr(vmr->flag, reason, att_pte);
|
||||
XPMEM_DEBUG("att_attr=0x%lx", att_attr);
|
||||
|
||||
if (att_pte && !pgsize_is_contiguous(seg_pgsize)) {
|
||||
ret = ihk_mc_pt_set_pte(vm->address_space->page_table, att_pte,
|
||||
seg_pgsize, seg_phys, att_attr);
|
||||
if (att_pte) {
|
||||
ret = ihk_mc_pt_set_pte(vm->address_space->page_table, att_pte,
|
||||
att_pgsize, seg_phys, att_attr);
|
||||
if (ret) {
|
||||
ret = -EFAULT;
|
||||
ekprintf("%s: ERROR: ihk_mc_pt_set_pte() failed %d\n",
|
||||
__func__, ret);
|
||||
ekprintf("%s: ERROR: ihk_mc_pt_set_pte() failed %d\n",
|
||||
__FUNCTION__, ret);
|
||||
goto out;
|
||||
}
|
||||
// memory_stat_rss_add() is called by the process hosting the memory area
|
||||
}
|
||||
else {
|
||||
ret = ihk_mc_pt_set_range(vm->address_space->page_table, vm,
|
||||
att_pgaddr, att_pgaddr + seg_pgsize,
|
||||
seg_phys, att_attr,
|
||||
pgsize_to_pgshift(seg_pgsize), vmr, 1);
|
||||
ret = ihk_mc_pt_set_range(vm->address_space->page_table, vm,
|
||||
att_pgaddr, att_pgaddr + att_pgsize, seg_phys, att_attr,
|
||||
vmr->pgshift, vmr, 0);
|
||||
if (ret) {
|
||||
ret = -EFAULT;
|
||||
ekprintf("%s: ERROR: ihk_mc_pt_set_range() failed %d\n",
|
||||
__func__, ret);
|
||||
__FUNCTION__, ret);
|
||||
goto out;
|
||||
}
|
||||
// memory_stat_rss_add() is called by the process hosting the memory area
|
||||
}
|
||||
|
||||
out:
|
||||
if (is_remote_vm(seg_tg->vm)) {
|
||||
ihk_mc_spinlock_unlock_noirq(&seg_tg->vm->memory_range_lock);
|
||||
}
|
||||
|
||||
XPMEM_DEBUG("return: ret=%d", ret);
|
||||
|
||||
return ret;
|
||||
@ -2133,7 +2026,8 @@ static pte_t * xpmem_vaddr_to_pte(
|
||||
}
|
||||
|
||||
out:
|
||||
return pte;
|
||||
|
||||
return pte;
|
||||
}
|
||||
|
||||
|
||||
@ -2143,35 +2037,37 @@ static int xpmem_pin_page(
|
||||
struct process_vm *src_vm,
|
||||
unsigned long vaddr)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret;
|
||||
struct vm_range *range;
|
||||
|
||||
XPMEM_DEBUG("call: tgid=%d, vaddr=0x%lx", tg->tgid, vaddr);
|
||||
|
||||
if (is_remote_vm(src_vm)) {
|
||||
ihk_mc_spinlock_lock_noirq(&src_vm->memory_range_lock);
|
||||
}
|
||||
ihk_rwspinlock_read_lock_noirq(&src_vm->memory_range_lock);
|
||||
|
||||
range = lookup_process_memory_range(src_vm, vaddr, vaddr + 1);
|
||||
|
||||
ihk_rwspinlock_read_unlock_noirq(&src_vm->memory_range_lock);
|
||||
|
||||
if (!range || range->start > vaddr) {
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (xpmem_is_private_data(range)) {
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
ihk_atomic_inc(&tg->n_pinned);
|
||||
out:
|
||||
if (is_remote_vm(src_vm)) {
|
||||
ihk_mc_spinlock_unlock_noirq(&src_vm->memory_range_lock);
|
||||
ret = page_fault_process_vm(src_vm, (void *)vaddr,
|
||||
PF_POPULATE | PF_WRITE | PF_USER);
|
||||
if (!ret) {
|
||||
ihk_atomic_inc(&tg->n_pinned);
|
||||
}
|
||||
else {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
XPMEM_DEBUG("return: ret=%d", ret);
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -2181,24 +2077,30 @@ static void xpmem_unpin_pages(
|
||||
unsigned long vaddr,
|
||||
size_t size)
|
||||
{
|
||||
int n_pgs = (((offset_in_page(vaddr) + (size)) + (PAGE_SIZE - 1)) >>
|
||||
PAGE_SHIFT);
|
||||
int n_pgs_unpinned = 0;
|
||||
size_t vsize = 0;
|
||||
unsigned long end = vaddr + size;
|
||||
pte_t *pte = NULL;
|
||||
|
||||
XPMEM_DEBUG("call: segid=0x%lx, vaddr=0x%lx, size=0x%lx",
|
||||
seg->segid, vaddr, size);
|
||||
|
||||
XPMEM_DEBUG("n_pgs=%d", n_pgs);
|
||||
|
||||
vaddr &= PAGE_MASK;
|
||||
|
||||
while (vaddr < end) {
|
||||
while (n_pgs > 0) {
|
||||
pte = xpmem_vaddr_to_pte(vm, vaddr, &vsize);
|
||||
if (pte && !pte_is_null(pte)) {
|
||||
n_pgs_unpinned++;
|
||||
vaddr += vsize;
|
||||
vaddr += PAGE_SIZE;
|
||||
n_pgs--;
|
||||
}
|
||||
else {
|
||||
vaddr = ((vaddr + vsize) & (~(vsize - 1)));
|
||||
vsize = ((vaddr + vsize) & (~(vsize - 1)));
|
||||
n_pgs -= (vsize - vaddr) / PAGE_SIZE;
|
||||
vaddr = vsize;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2400,15 +2302,3 @@ static int xpmem_validate_access(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_remote_vm(struct process_vm *vm)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (cpu_local_var(current)->proc->vm != vm) {
|
||||
/* vm is not mine */
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -15,6 +15,162 @@
|
||||
|
||||
#include <arch-lock.h>
|
||||
|
||||
|
||||
/* Simple read/write spinlock implementation */
|
||||
#define IHK_RWSPINLOCK_WRITELOCKED (0xffU << 24)
|
||||
typedef struct {
|
||||
ihk_atomic_t v;
|
||||
} __attribute__((aligned(4))) ihk_rwspinlock_t;
|
||||
|
||||
static void ihk_rwspinlock_init(ihk_rwspinlock_t *lock)
|
||||
{
|
||||
ihk_atomic_set(&lock->v, 0);
|
||||
}
|
||||
|
||||
static inline void __ihk_rwspinlock_read_lock(ihk_rwspinlock_t *lock)
|
||||
{
|
||||
int desired_old_val;
|
||||
int new_val;
|
||||
|
||||
/*
|
||||
* Atomically increase number of readers,
|
||||
* but make sure no writer is holding the lock.
|
||||
*/
|
||||
for (;;) {
|
||||
desired_old_val = ihk_atomic_read(&lock->v);
|
||||
desired_old_val &= ~(IHK_RWSPINLOCK_WRITELOCKED);
|
||||
new_val = desired_old_val + 1;
|
||||
|
||||
/* Only if we have not reached the max number of readers */
|
||||
if (likely((uint32_t)new_val < IHK_RWSPINLOCK_WRITELOCKED)) {
|
||||
if (likely(cmpxchg(&lock->v.counter, desired_old_val, new_val) ==
|
||||
desired_old_val))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline int __ihk_rwspinlock_read_trylock(ihk_rwspinlock_t *lock)
|
||||
{
|
||||
int desired_old_val;
|
||||
int new_val;
|
||||
|
||||
/*
|
||||
* Atomically try to increase number of readers,
|
||||
* but make sure no writer is holding the lock.
|
||||
*/
|
||||
desired_old_val = ihk_atomic_read(&lock->v);
|
||||
desired_old_val &= ~(IHK_RWSPINLOCK_WRITELOCKED);
|
||||
new_val = desired_old_val + 1;
|
||||
|
||||
/* Only if we have not reached the max number of readers */
|
||||
if (likely((uint32_t)new_val < IHK_RWSPINLOCK_WRITELOCKED)) {
|
||||
if (likely(cmpxchg(&lock->v.counter, desired_old_val, new_val) ==
|
||||
desired_old_val))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static inline void __ihk_rwspinlock_read_unlock(ihk_rwspinlock_t *lock)
|
||||
{
|
||||
ihk_atomic_dec((ihk_atomic_t *)&lock->v);
|
||||
}
|
||||
|
||||
static inline void __ihk_rwspinlock_write_lock(ihk_rwspinlock_t *lock)
|
||||
{
|
||||
/*
|
||||
* Atomically switch to write-locked state,
|
||||
* but make sure no one else is holding the lock.
|
||||
*/
|
||||
for (;;) {
|
||||
if (likely(cmpxchg(&lock->v.counter,
|
||||
0, IHK_RWSPINLOCK_WRITELOCKED) == 0))
|
||||
return;
|
||||
cpu_pause();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __ihk_rwspinlock_write_unlock(ihk_rwspinlock_t *lock)
|
||||
{
|
||||
smp_store_release(&(lock->v.counter), 0);
|
||||
}
|
||||
|
||||
/* User facing functions */
|
||||
static inline void ihk_rwspinlock_read_lock_noirq(ihk_rwspinlock_t *lock)
|
||||
{
|
||||
preempt_disable();
|
||||
__ihk_rwspinlock_read_lock(lock);
|
||||
}
|
||||
|
||||
static inline int ihk_rwspinlock_read_trylock_noirq(ihk_rwspinlock_t *lock)
|
||||
{
|
||||
int rc;
|
||||
|
||||
preempt_disable();
|
||||
rc = __ihk_rwspinlock_read_trylock(lock);
|
||||
if (!rc) {
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline void ihk_rwspinlock_write_lock_noirq(ihk_rwspinlock_t *lock)
|
||||
{
|
||||
preempt_disable();
|
||||
__ihk_rwspinlock_write_lock(lock);
|
||||
}
|
||||
|
||||
static inline void ihk_rwspinlock_read_unlock_noirq(ihk_rwspinlock_t *lock)
|
||||
{
|
||||
__ihk_rwspinlock_read_unlock(lock);
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
static inline void ihk_rwspinlock_write_unlock_noirq(ihk_rwspinlock_t *lock)
|
||||
{
|
||||
__ihk_rwspinlock_write_unlock(lock);
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
|
||||
static inline
|
||||
unsigned long ihk_rwspinlock_read_lock(ihk_rwspinlock_t *lock)
|
||||
{
|
||||
unsigned long irqstate = cpu_disable_interrupt_save();
|
||||
|
||||
ihk_rwspinlock_read_lock_noirq(lock);
|
||||
return irqstate;
|
||||
}
|
||||
|
||||
static inline
|
||||
unsigned long ihk_rwspinlock_write_lock(ihk_rwspinlock_t *lock)
|
||||
{
|
||||
unsigned long irqstate = cpu_disable_interrupt_save();
|
||||
|
||||
ihk_rwspinlock_write_lock_noirq(lock);
|
||||
return irqstate;
|
||||
}
|
||||
|
||||
static inline void ihk_rwspinlock_read_unlock(ihk_rwspinlock_t *lock,
|
||||
unsigned long irqstate)
|
||||
{
|
||||
ihk_rwspinlock_read_unlock_noirq(lock);
|
||||
cpu_restore_interrupt(irqstate);
|
||||
}
|
||||
|
||||
static inline void ihk_rwspinlock_write_unlock(ihk_rwspinlock_t *lock,
|
||||
unsigned long irqstate)
|
||||
{
|
||||
ihk_rwspinlock_write_unlock_noirq(lock);
|
||||
cpu_restore_interrupt(irqstate);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef ARCH_MCS_LOCK
|
||||
/* An architecture independent implementation of the
|
||||
* Mellor-Crummey Scott (MCS) lock */
|
||||
|
||||
96
scripts/eclair-dump-backtrace.exp.in
Executable file
96
scripts/eclair-dump-backtrace.exp.in
Executable file
@ -0,0 +1,96 @@
|
||||
#!/usr/bin/expect
|
||||
|
||||
set INST_DIR "@prefix@"
|
||||
|
||||
spawn $INST_DIR/bin/eclair -k $INST_DIR/smp-@ARCH@/kernel/mckernel.img -i -l
|
||||
|
||||
set state "init"
|
||||
set thread_id 0
|
||||
set timeout -1
|
||||
|
||||
expect {
|
||||
"Quit anyway? (y or n) " {
|
||||
send "y\r"
|
||||
wait
|
||||
exit 0
|
||||
}
|
||||
"Unknown thread*" {
|
||||
send "quit\r"
|
||||
exp_continue
|
||||
}
|
||||
"in ?? ()" {
|
||||
switch -- $state {
|
||||
"thread_chosen" {
|
||||
set state "thread_skip"
|
||||
}
|
||||
"thread_bt" {
|
||||
set state "thread_skip"
|
||||
}
|
||||
}
|
||||
|
||||
exp_continue
|
||||
}
|
||||
"(eclair) " {
|
||||
switch -- $state {
|
||||
"init" {
|
||||
set state "threads_list"
|
||||
send "info threads\r"
|
||||
}
|
||||
"threads_list" {
|
||||
incr thread_id
|
||||
set state "thread_chosen"
|
||||
send "thread $thread_id\r"
|
||||
}
|
||||
"thread_bt" {
|
||||
incr thread_id
|
||||
set state "thread_chosen"
|
||||
send "thread $thread_id\r"
|
||||
}
|
||||
"thread_skip" {
|
||||
incr thread_id
|
||||
set state "thread_chosen"
|
||||
send "thread $thread_id\r"
|
||||
}
|
||||
"thread_chosen" {
|
||||
set state "thread_bt"
|
||||
send "bt\r"
|
||||
}
|
||||
}
|
||||
|
||||
exp_continue
|
||||
}
|
||||
"Type <RET> for more, q to quit, c to continue without paging--" {
|
||||
switch -- $state {
|
||||
"threads_list" {
|
||||
send "\r"
|
||||
}
|
||||
"thread_bt" {
|
||||
send "q\r"
|
||||
}
|
||||
"thread_skip" {
|
||||
send "q\r"
|
||||
}
|
||||
}
|
||||
exp_continue
|
||||
}
|
||||
"Type <return> to continue, or q <return> to quit" {
|
||||
switch -- $state {
|
||||
"threads_list" {
|
||||
send "\r"
|
||||
}
|
||||
"thread_bt" {
|
||||
send "\r"
|
||||
}
|
||||
"thread_skip" {
|
||||
send "q\r"
|
||||
}
|
||||
}
|
||||
exp_continue
|
||||
}
|
||||
" not known." {
|
||||
expect "(eclair) " { send "quit\r" }
|
||||
expect "Quit anyway? (y or n) " { send "y\r" }
|
||||
exit 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
%{!?kernel_version: %global kernel_version @UNAME_R@}
|
||||
%{!?kernel_dir: %global kernel_dir /usr/src/kernels/%{kernel_version}}
|
||||
%define krequires %(echo %{kernel_version} | sed "s/.%{_target_cpu}$//")
|
||||
%define ktag %(echo %{krequires} | tr '-' '_' | sed -e 's/\.el[0-9]*$//' | sed -e 's/\.\([a-zA-Z]\)/_\1/')
|
||||
%define ktag %(echo %{krequires} | tr '-' '_' | sed -e 's/\.el[0-9_]*$//' | sed -e 's/\.\([a-zA-Z]\)/_\1/')
|
||||
|
||||
Name: mckernel
|
||||
Version: @MCKERNEL_VERSION@
|
||||
@ -96,6 +96,9 @@ This package contains headers and libraries required for build apps using IHK/Mc
|
||||
%{_sbindir}/ihkmond
|
||||
%{_bindir}/mcexec
|
||||
%{_bindir}/eclair
|
||||
%{_bindir}/eclair-dump-backtrace.exp
|
||||
%{_bindir}/mcinspect
|
||||
%{_bindir}/mcps
|
||||
%{_bindir}/vmcore2mckdump
|
||||
%{_bindir}/mcstat
|
||||
%{_libdir}/libihk.so
|
||||
|
||||
@ -1,187 +0,0 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
USELTP=0
|
||||
USEOSTEST=0
|
||||
|
||||
XPMEM_DIR=$HOME/usr
|
||||
XPMEM_BUILD_DIR=/home/satoken/xpmem
|
||||
|
||||
arch=`uname -p`
|
||||
if [ -f "./${arch}_config" ]; then
|
||||
. ./${arch}_config
|
||||
else
|
||||
echo "$1 is unexpected arch"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
. ../../common.sh
|
||||
|
||||
sudo insmod ${XPMEM_DIR}/lib/modules/`uname -r`/xpmem.ko
|
||||
sudo chmod og+rw /dev/xpmem
|
||||
|
||||
issue=1259
|
||||
tid=01
|
||||
ng=0
|
||||
echo "*** C${issue}T${tid} start *******************************"
|
||||
echo "** xpmem_attach to Huge mapped memory range"
|
||||
echo "** end of range is aligned with Large page size"
|
||||
for pgshift in ${PGSHIFT_LIST[@]}
|
||||
do
|
||||
${IHKOSCTL} 0 clear_kmsg
|
||||
log_file="./C${issue}T${tid}_${pgshift}.log"
|
||||
echo pageshift: ${pgshift}
|
||||
${MCEXEC} ./huge_page_xpmem ${pgshift} 2 0 > ${log_file}
|
||||
${IHKOSCTL} 0 kmsg >> ${log_file}
|
||||
|
||||
EXPECT_PGSIZE=`grep EXPECT_PAGE_SIZE ${log_file} | awk '{ print $2; }'`
|
||||
|
||||
SEG_ADDR=`grep parent: ${log_file} | awk '{ print $3; }'`
|
||||
SEG_PGSIZE=`cat ${log_file} | awk '/OK/,/DONE/' | \
|
||||
grep -o "large_page_allocation.*${SEG_ADDR}.*" | awk '{ print $5; }'`
|
||||
|
||||
XPMEM_ADDR=`grep xpmem_attachment_addr ${log_file} | awk '{ print $3; }'`
|
||||
XPMEM_PGSIZE=`grep -o "xpmem_page_attach.*${XPMEM_ADDR}.*" ${log_file} | awk '{ print $5; }'`
|
||||
|
||||
if [ "${SEG_PGSIZE}" = "${EXPECT_PGSIZE}" ]; then
|
||||
echo "** [ OK ] seg_addr ($SEG_ADDR) is allocated until xpmem_attach"
|
||||
else
|
||||
echo "** [ NG ] seg_addr ($SEG_ADDR) is NOT allocated until xpmem_attach"
|
||||
let ng++
|
||||
fi
|
||||
if [ "${XPMEM_PGSIZE}" = "${EXPECT_PGSIZE}" ]; then
|
||||
echo "** [ OK ] xpmem_addr ($XPMEM_ADDR) is allocated using large pages"
|
||||
else
|
||||
echo "** [ NG ] xpmem_addr ($XPMEM_ADDR) is NOT allocated using large pages"
|
||||
let ng++
|
||||
fi
|
||||
done
|
||||
if [ ${ng} -eq 0 ]; then
|
||||
echo "*** C${issue}T${tid}: PASSED"
|
||||
else
|
||||
echo "*** C${issue}T${tid}: FAILED"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
tid=02
|
||||
ng=0
|
||||
echo "*** C${issue}T${tid} start *******************************"
|
||||
echo "** xpmem_attach to Huge mapped memory range"
|
||||
echo "** end of range is NOT aligned with Large page size"
|
||||
for pgshift in ${PGSHIFT_LIST[@]}
|
||||
do
|
||||
${IHKOSCTL} 0 clear_kmsg
|
||||
log_file="./C${issue}T${tid}_${pgshift}.log"
|
||||
echo pageshift: ${pgshift}
|
||||
${MCEXEC} ./huge_page_xpmem ${pgshift} 2 ${SMALL_PGSIZE} > ${log_file}
|
||||
${IHKOSCTL} 0 kmsg >> ${log_file}
|
||||
|
||||
EXPECT_PGSIZE=`grep EXPECT_PAGE_SIZE ${log_file} | awk '{ print $2; }'`
|
||||
|
||||
SEG_ADDR=`grep parent: ${log_file} | awk '{ print $3; }'`
|
||||
SEG_PGSIZE=`cat ${log_file} | awk '/OK/,/DONE/' | \
|
||||
grep -o "large_page_allocation.*${SEG_ADDR}.*" | awk '{ print $5; }'`
|
||||
|
||||
XPMEM_ADDR=`grep xpmem_attachment_addr ${log_file} | awk '{ print $3; }'`
|
||||
XPMEM_PGSIZE=`grep -o "xpmem_page_attach.*${XPMEM_ADDR}.*" ${log_file} | awk '{ print $5; }'`
|
||||
|
||||
if [ "${SEG_PGSIZE}" = "${EXPECT_PGSIZE}" ]; then
|
||||
echo "** [ OK ] seg_addr ($SEG_ADDR) is allocated until xpmem_attach"
|
||||
else
|
||||
echo "** [ NG ] seg_addr ($SEG_ADDR) is NOT allocated until xpmem_attach"
|
||||
let ng++
|
||||
fi
|
||||
if [ "${XPMEM_PGSIZE}" = "${EXPECT_PGSIZE}" ]; then
|
||||
echo "** [ OK ] xpmem_addr ($XPMEM_ADDR) is allocated using large pages"
|
||||
else
|
||||
echo "** [ NG ] xpmem_addr ($XPMEM_ADDR) is NOT allocated using large pages"
|
||||
let ng++
|
||||
fi
|
||||
done
|
||||
if [ ${ng} -eq 0 ]; then
|
||||
echo "*** C${issue}T${tid}: PASSED"
|
||||
else
|
||||
echo "*** C${issue}T${tid}: FAILED"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
tid=03
|
||||
ng=0
|
||||
echo "*** C${issue}T${tid} start *******************************"
|
||||
echo "** xpmem_attach to small mapped memory range"
|
||||
${IHKOSCTL} 0 clear_kmsg
|
||||
log_file="./C${issue}T${tid}.log"
|
||||
echo pageshift: small page
|
||||
${MCEXEC} ./huge_page_xpmem -1 2 0 > ${log_file}
|
||||
${IHKOSCTL} 0 kmsg >> ${log_file}
|
||||
|
||||
EXPECT_PGSIZE=`grep EXPECT_PAGE_SIZE ${log_file} | awk '{ print $2; }'`
|
||||
|
||||
XPMEM_ADDR=`grep xpmem_attachment_addr ${log_file} | awk '{ print $3; }'`
|
||||
XPMEM_PGSIZE=`grep -o "xpmem_page_attach.*${XPMEM_ADDR}.*" ${log_file} | awk '{ print $5; }'`
|
||||
|
||||
if [ "${XPMEM_PGSIZE}" = "${EXPECT_PGSIZE}" ]; then
|
||||
echo "** [ OK ] xpmem_addr ($XPMEM_ADDR) is allocated using small pages"
|
||||
else
|
||||
echo "** [ NG ] xpmem_addr ($XPMEM_ADDR) is NOT allocated using small pages"
|
||||
ng=1
|
||||
fi
|
||||
if [ ${ng} -eq 0 ]; then
|
||||
echo "*** C${issue}T${tid}: PASSED"
|
||||
else
|
||||
echo "*** C${issue}T${tid}: FAILED"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
tid=04
|
||||
ng=0
|
||||
echo "*** C${issue}T${tid} start *******************************"
|
||||
echo "** xpmem_attach to multi pagesize range"
|
||||
pgshift=${PGSHIFT_LIST[0]}
|
||||
${IHKOSCTL} 0 clear_kmsg
|
||||
log_file="./C${issue}T${tid}_${pgshift}.log"
|
||||
echo pageshift: ${pgshift}
|
||||
${MCEXEC} ./multi_vmr_xpmem ${pgshift} 1 > ${log_file}
|
||||
${IHKOSCTL} 0 kmsg >> ${log_file}
|
||||
|
||||
EXPECT_PGSIZE=`grep EXPECT_PAGE_SIZE ${log_file} | awk '{ print $2; }'`
|
||||
|
||||
XPMEM_ADDR=`grep xpmem_large ${log_file} | awk '{ print $3; }'`
|
||||
XPMEM_PGSIZE=`grep -o "xpmem_page_attach.*${XPMEM_ADDR}.*" ${log_file} | awk '{ print $5; }'`
|
||||
|
||||
if [ "${XPMEM_PGSIZE}" = "${EXPECT_PGSIZE}" ]; then
|
||||
echo "** [ OK ] xpmem_addr ($XPMEM_ADDR) is allocated using large pages"
|
||||
else
|
||||
echo "** [ NG ] xpmem_addr ($XPMEM_ADDR) is NOT allocated using large pages"
|
||||
let ng++
|
||||
fi
|
||||
if [ ${ng} -eq 0 ]; then
|
||||
echo "*** C${issue}T${tid}: PASSED"
|
||||
else
|
||||
echo "*** C${issue}T${tid}: FAILED"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
tid=05
|
||||
ng=0
|
||||
echo "*** C${issue}T${tid} start *******************************"
|
||||
echo "** xpmem testsuite"
|
||||
cwd=`pwd`
|
||||
cd ${XPMEM_BUILD_DIR}/test
|
||||
${cwd}/mc_run.sh
|
||||
cd ${cwd}
|
||||
|
||||
# xpmem basic test
|
||||
${MCEXEC} ./XTP_001
|
||||
${MCEXEC} ./XTP_002
|
||||
${MCEXEC} ./XTP_003
|
||||
${MCEXEC} ./XTP_004
|
||||
${MCEXEC} ./XTP_005
|
||||
${MCEXEC} ./XTP_006
|
||||
sleep 3
|
||||
${MCEXEC} ./XTP_007
|
||||
${MCEXEC} ./XTP_008
|
||||
${MCEXEC} ./XTP_009
|
||||
${MCEXEC} ./XTP_010
|
||||
${MCEXEC} ./XTP_011
|
||||
|
||||
sudo rmmod xpmem.ko
|
||||
@ -1,12 +0,0 @@
|
||||
XPMEM_DIR=$(HOME)/usr
|
||||
CPPFLAGS=-I$(XPMEM_DIR)/include
|
||||
LDFLAGS=-L$(XPMEM_DIR)/lib -Wl,-rpath -Wl,$(XPMEM_DIR)/lib -lxpmem
|
||||
|
||||
TARGET=huge_page_xpmem multi_vmr_xpmem XTP_001 XTP_002 XTP_003 XTP_004 XTP_005 XTP_006 XTP_007 XTP_008 XTP_009 XTP_010 XTP_011
|
||||
|
||||
all: $(TARGET)
|
||||
test: all
|
||||
bash ./C1259.sh
|
||||
clean:
|
||||
rm -f $(TARGET) C*.log
|
||||
|
||||
@ -1,104 +0,0 @@
|
||||
【Issue#1259 動作確認】
|
||||
□ テスト内容
|
||||
1. Large pageでマップされたメモリ領域でのxpmemの動作確認
|
||||
C1259T01:
|
||||
Large pageでマップされたメモリ領域に対してxpmem_attachを行った場合、
|
||||
attach先の領域がxpmem_makeでページインされることを確認する
|
||||
また、xpmemでもLarge pageが利用されることを確認する
|
||||
|
||||
C1259T02:
|
||||
Large pageでかつ、最後のページがLarge pageサイズでアラインされていない
|
||||
メモリ領域に対してxpmem_attachを行った場合、
|
||||
xpmemでもLarge pageが利用されることを確認する
|
||||
|
||||
C1259T03:
|
||||
Small pageでマップされたメモリ領域に対してxpmem_attachを行った場合、
|
||||
xpmemでもSmall pageが利用されることを確認する
|
||||
|
||||
C1259T04:
|
||||
small - large - small のように、異なるページサイズの複数のvm_rangeから
|
||||
構成されるメモリ領域に対してxpmem_attach を行った場合、
|
||||
xpmemでも同じ構成でLarge pageが利用されることを確認する
|
||||
|
||||
2. xpmemのテストスイートによる動作確認
|
||||
xpmemに付属するテストスイートをMcKernelで実行し、PASSすることを確認する
|
||||
|
||||
3. xpmemの基本操作の確認
|
||||
xpmemで操作するメモリ領域は、Large pageでマップする
|
||||
|
||||
XTP_001: 単一プロセスでのXPMEM操作
|
||||
1. 実行したプロセスがxpmem_make -> xpmem_get -> xpmem_attach -> xpmem_detach -> xpmem_remove
|
||||
|
||||
XTP_002: 子プロセスでのXPMEM操作
|
||||
1. 親プロセスがfork()
|
||||
2. 子プロセスがxpmem_make -> xpmem_get -> xpmem_attach -> xpmem_detach ->xpmem_remove
|
||||
3. 子プロセス終了後、親プロセスが終了
|
||||
|
||||
XTP_003: 親プロセスがmakeした共有領域への子プロセスによるXPMEM操作
|
||||
1. 親プロセスがxpmem_make
|
||||
2. fork()で子プロセスを作成
|
||||
3. 子プロセスで、xpmem_get -> xpmem_attach -> 値(TEST_VAL)の設定 -> xpmem_detach
|
||||
4. 子プロセスが終了
|
||||
5. 親プロセスが、子プロセスによって設定された値(TEST_VAL)を確認
|
||||
6. 親プロセスがxpmem_remove
|
||||
|
||||
XTP_004: fork()後に親プロセスがmakeした共有領域への子プロセスによるXPMEM操作
|
||||
1. fork()で子プロセスを作成
|
||||
2. 親プロセスがxpmem_make
|
||||
3. 子プロセスで、xpmem_get -> xpmem_attach -> 値(TEST_VAL)の設定 -> xpmem_detach
|
||||
4. 子プロセスが終了
|
||||
5. 親プロセスが、子プロセスによって設定された値(TEST_VAL)を確認
|
||||
6. 親プロセスがxpmem_remove
|
||||
|
||||
XTP_005: 子プロセスがxpmem_attach後、xpmem_detachをせずに終了
|
||||
1. 親プロセスがxpmem_make
|
||||
2. fork()で子プロセスを作成
|
||||
3. 子プロセスで、xpmem_get -> xpmem_attach
|
||||
4. 子プロセスが終了
|
||||
5. 親プロセスがxpmem_remove
|
||||
|
||||
XTP_006: 子プロセスがXPMEM操作を行う時点で、xpmem_makeをした親プロセスが終了している
|
||||
1. 親プロセスがxpmem_make
|
||||
2. fork()で子プロセスを作成
|
||||
3. 親プロセスが終了
|
||||
4. 子プロセスで、xpmem_get (失敗)
|
||||
5. 子プロセスが終了
|
||||
|
||||
XTP_007: xpmem_make 呼び出しの異常系
|
||||
1. xpmem_make の第1引数に不正なアドレスを指定する (失敗)
|
||||
2. 1度xpmem_make を実施したメモリ領域に対して、再度xpmem_make を行う (成功)
|
||||
|
||||
XTP_008: xpmem_get 呼び出しの異常系
|
||||
1. xpmem_get の第1引数に不正なsegidを指定する (失敗)
|
||||
2. 1度xpmem_get を実施したsegidで、再度xpmem_get を行う (成功)
|
||||
|
||||
XTP_009: xpmem_attach 呼び出しの異常系
|
||||
1. xpmem_attach の第1引数に不正なapidを指定する (失敗)
|
||||
2. 1度xpmem_attach を実施したapidで、再度xpmem_attach を行う (成功)
|
||||
|
||||
XTP_010: xpmem_detach 呼び出しの異常系
|
||||
1. xpmem_detach の第1引数に不正なアドレスを指定する (成功)
|
||||
2. 1度xpmem_detach を実施したメモリ領域に対して、再度xpmem_detach を行う (成功)
|
||||
|
||||
XTP_011: xpmem_remove 呼び出しの異常系
|
||||
1. xpmem_remove の第1引数に不正なsegidを指定する (失敗)
|
||||
2. 1度xpmem_remove を実施したsegidで、再度xpmem_remove を行う (失敗)
|
||||
|
||||
□ 実行手順
|
||||
1. xpmemのインストールディレクトリをMakefileとC1259.sh中のXPMEM_DIRに記載する
|
||||
2. xpmemのビルドディレクトリをC1259.sh中のXPMEM_BUILD_DIRに記載する
|
||||
3. 下記の手順でテストを実行する
|
||||
$ cd <mckernel>
|
||||
$ patch -p0 < test/issues/1259/large_page.patch
|
||||
(build mckernel)
|
||||
$ cd test/issues/1259
|
||||
$ make test
|
||||
|
||||
McKernelのインストール先や、OSTEST, LTPの配置場所は、
|
||||
$HOME/.mck_test_config を参照している
|
||||
.mck_test_config は、McKernelをビルドした際に生成されるmck_test_config.sample ファイルを
|
||||
$HOMEにコピーし、適宜編集する
|
||||
|
||||
□ 実行結果
|
||||
x86_64_result.log, aarch64_result.log 参照。
|
||||
すべての項目をPASSしていることを確認。
|
||||
@ -1,60 +0,0 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <xpmem.h>
|
||||
#include <libgen.h>
|
||||
#include "util2.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *mem, *attach;
|
||||
int rc = 0;
|
||||
int status;
|
||||
xpmem_segid_t segid;
|
||||
xpmem_apid_t apid;
|
||||
struct xpmem_addr addr;
|
||||
|
||||
printf("*** %s start ***\n", basename(argv[0]));
|
||||
|
||||
mem = mmap(0, SZ_MEM, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE |
|
||||
MAP_HUGETLB | (LARGE_PAGE_SHIFT << MAP_HUGE_SHIFT), -1, 0);
|
||||
CHKANDJUMP(mem == NULL, "mmap");
|
||||
memset(mem, 0, SZ_MEM);
|
||||
|
||||
rc = xpmem_init();
|
||||
CHKANDJUMP(rc != 0, "xpmem_init");
|
||||
|
||||
segid = xpmem_make(mem, SZ_MEM, XPMEM_PERMIT_MODE, (void *)0666);
|
||||
OKNG(segid == -1, "xpmem_make");
|
||||
|
||||
apid = xpmem_get(segid, XPMEM_RDWR, XPMEM_PERMIT_MODE, NULL);
|
||||
OKNG(apid == -1, "xpmem_get");
|
||||
|
||||
addr.apid = apid;
|
||||
addr.offset = 0;
|
||||
attach = xpmem_attach(addr, SZ_MEM, NULL);
|
||||
OKNG(attach == (void *)-1, "xpmem_attach");
|
||||
|
||||
rc = xpmem_detach(attach);
|
||||
OKNG(rc == -1, "xpmem_detach");
|
||||
|
||||
rc = xpmem_remove(segid);
|
||||
OKNG(rc == -1, "xpmem_remove");
|
||||
|
||||
printf("*** %s PASSED\n\n", basename(argv[0]));
|
||||
return 0;
|
||||
|
||||
fn_fail:
|
||||
printf("*** %s FAILED\n\n", basename(argv[0]));
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -1,76 +0,0 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <xpmem.h>
|
||||
#include <libgen.h>
|
||||
#include "util2.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *mem, *attach;
|
||||
int rc = 0;
|
||||
int status;
|
||||
pid_t pid;
|
||||
xpmem_segid_t segid;
|
||||
xpmem_apid_t apid;
|
||||
struct xpmem_addr addr;
|
||||
|
||||
printf("*** %s start ***\n", basename(argv[0]));
|
||||
|
||||
mem = mmap(0, SZ_MEM, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE |
|
||||
MAP_HUGETLB | (LARGE_PAGE_SHIFT << MAP_HUGE_SHIFT), -1, 0);
|
||||
CHKANDJUMP(mem == NULL, "mmap");
|
||||
memset(mem, 0, SZ_MEM);
|
||||
|
||||
fflush(0);
|
||||
pid = fork();
|
||||
CHKANDJUMP(pid == -1, "fork failed\n");
|
||||
|
||||
if (pid == 0) {
|
||||
/* Child process */
|
||||
rc = xpmem_init();
|
||||
CHKANDJUMP(rc != 0, "xpmem_init in child");
|
||||
|
||||
segid = xpmem_make(mem, SZ_MEM, XPMEM_PERMIT_MODE,
|
||||
(void *)0666);
|
||||
OKNG(segid == -1, "xpmem_make in child");
|
||||
|
||||
apid = xpmem_get(segid, XPMEM_RDWR, XPMEM_PERMIT_MODE, NULL);
|
||||
OKNG(apid == -1, "xpmem_get in child");
|
||||
|
||||
addr.apid = apid;
|
||||
addr.offset = 0;
|
||||
attach = xpmem_attach(addr, SZ_MEM, NULL);
|
||||
OKNG(attach == (void *)-1, "xpmem_attach in child");
|
||||
|
||||
rc = xpmem_detach(attach);
|
||||
OKNG(rc == -1, "xpmem_detach in child");
|
||||
|
||||
rc = xpmem_remove(segid);
|
||||
OKNG(rc == -1, "xpmem_remove in child");
|
||||
|
||||
fflush(0);
|
||||
_exit(0);
|
||||
} else {
|
||||
/* Parent process */
|
||||
rc = waitpid(pid, &status, 0);
|
||||
CHKANDJUMP(rc == -1, "waitpid failed\n");
|
||||
}
|
||||
|
||||
printf("*** %s PASSED\n\n", basename(argv[0]));
|
||||
return 0;
|
||||
|
||||
fn_fail:
|
||||
printf("*** %s FAILED\n\n", basename(argv[0]));
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -1,79 +0,0 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <xpmem.h>
|
||||
#include <libgen.h>
|
||||
#include "util2.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *mem, *attach;
|
||||
int rc = 0;
|
||||
int status;
|
||||
pid_t pid;
|
||||
xpmem_segid_t segid;
|
||||
xpmem_apid_t apid;
|
||||
struct xpmem_addr addr;
|
||||
|
||||
printf("*** %s start ***\n", basename(argv[0]));
|
||||
|
||||
mem = mmap(0, SZ_MEM, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE |
|
||||
MAP_HUGETLB | (LARGE_PAGE_SHIFT << MAP_HUGE_SHIFT), -1, 0);
|
||||
CHKANDJUMP(mem == NULL, "mmap");
|
||||
memset(mem, 0, SZ_MEM);
|
||||
|
||||
rc = xpmem_init();
|
||||
CHKANDJUMP(rc != 0, "xpmem_init");
|
||||
|
||||
segid = xpmem_make(mem, SZ_MEM, XPMEM_PERMIT_MODE, (void *)0666);
|
||||
OKNG(segid == -1, "xpmem_make");
|
||||
|
||||
fflush(0);
|
||||
pid = fork();
|
||||
CHKANDJUMP(pid == -1, "fork failed\n");
|
||||
|
||||
if (pid == 0) {
|
||||
/* Child process */
|
||||
apid = xpmem_get(segid, XPMEM_RDWR, XPMEM_PERMIT_MODE, NULL);
|
||||
OKNG(apid == -1, "xpmem_get in child");
|
||||
|
||||
addr.apid = apid;
|
||||
addr.offset = 0;
|
||||
attach = xpmem_attach(addr, SZ_MEM, NULL);
|
||||
OKNG(attach == (void *)-1, "xpmem_attach in child");
|
||||
|
||||
*((unsigned long *)attach) = TEST_VAL;
|
||||
|
||||
rc = xpmem_detach(attach);
|
||||
OKNG(rc == -1, "xpmem_detach in child");
|
||||
|
||||
fflush(0);
|
||||
_exit(0);
|
||||
} else {
|
||||
/* Parent process */
|
||||
rc = waitpid(pid, &status, 0);
|
||||
CHKANDJUMP(rc == -1, "waitpid failed\n");
|
||||
|
||||
OKNG(*((unsigned long *)mem) != TEST_VAL, "validate TEST_VAL");
|
||||
|
||||
rc = xpmem_remove(segid);
|
||||
OKNG(rc == -1, "xpmem_remove");
|
||||
}
|
||||
|
||||
printf("*** %s PASSED\n\n", basename(argv[0]));
|
||||
return 0;
|
||||
|
||||
fn_fail:
|
||||
printf("*** %s FAILED\n\n", basename(argv[0]));
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -1,112 +0,0 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <xpmem.h>
|
||||
#include <libgen.h>
|
||||
#include "util2.h"
|
||||
|
||||
#define BUFF_SIZE 1024
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *mem, *attach;
|
||||
int rc = 0;
|
||||
int status;
|
||||
pid_t pid;
|
||||
xpmem_segid_t segid;
|
||||
xpmem_apid_t apid;
|
||||
struct xpmem_addr addr;
|
||||
key_t key = ftok(argv[0], 0);
|
||||
int shmid;
|
||||
|
||||
printf("*** %s start ***\n", basename(argv[0]));
|
||||
|
||||
shmid = shmget(key, SZ_MEM, IPC_CREAT | 0660);
|
||||
CHKANDJUMP(shmid == -1, "shmget");
|
||||
|
||||
mem = mmap(0, SZ_MEM, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE |
|
||||
MAP_HUGETLB | (LARGE_PAGE_SHIFT << MAP_HUGE_SHIFT), -1, 0);
|
||||
CHKANDJUMP(mem == NULL, "mmap");
|
||||
memset(mem, 0, SZ_MEM);
|
||||
|
||||
fflush(0);
|
||||
pid = fork();
|
||||
CHKANDJUMP(pid == -1, "fork failed\n");
|
||||
|
||||
if (pid == 0) {
|
||||
/* Child process */
|
||||
void *shm = shmat(shmid, NULL, 0);
|
||||
|
||||
CHKANDJUMP(shm == (void *)-1, "shmat in child");
|
||||
|
||||
while ((segid = *(xpmem_segid_t *)shm) == 0) {
|
||||
};
|
||||
|
||||
rc = shmdt(shm);
|
||||
CHKANDJUMP(rc == -1, "shmdt");
|
||||
|
||||
rc = xpmem_init();
|
||||
CHKANDJUMP(rc != 0, "xpmem_init in child");
|
||||
|
||||
apid = xpmem_get(segid, XPMEM_RDWR, XPMEM_PERMIT_MODE, NULL);
|
||||
OKNG(apid == -1, "xpmem_get in child");
|
||||
|
||||
addr.apid = apid;
|
||||
addr.offset = 0;
|
||||
attach = xpmem_attach(addr, SZ_MEM, NULL);
|
||||
OKNG(attach == (void *)-1, "xpmem_attach in child");
|
||||
|
||||
*((unsigned long *)attach) = TEST_VAL;
|
||||
|
||||
rc = xpmem_detach(attach);
|
||||
OKNG(rc == -1, "xpmem_detach in child");
|
||||
|
||||
fflush(0);
|
||||
_exit(0);
|
||||
} else {
|
||||
/* Parent process */
|
||||
void *shm = shmat(shmid, NULL, 0);
|
||||
struct shmid_ds buf;
|
||||
|
||||
CHKANDJUMP(shm == (void *)-1, "shmat in parent");
|
||||
rc = xpmem_init();
|
||||
CHKANDJUMP(rc != 0, "xpmem_init");
|
||||
|
||||
segid = xpmem_make(mem, SZ_MEM, XPMEM_PERMIT_MODE,
|
||||
(void *)0666);
|
||||
OKNG(segid == -1, "xpmem_make");
|
||||
|
||||
*(xpmem_segid_t *)shm = segid;
|
||||
|
||||
rc = waitpid(pid, &status, 0);
|
||||
CHKANDJUMP(rc == -1, "waitpid failed\n");
|
||||
|
||||
OKNG(*((unsigned long *)mem) != TEST_VAL, "validate TEST_VAL");
|
||||
|
||||
rc = shmctl(shmid, IPC_RMID, &buf);
|
||||
CHKANDJUMP(rc == -1, "shmctl");
|
||||
|
||||
rc = shmdt(shm);
|
||||
CHKANDJUMP(rc == -1, "shmdt");
|
||||
|
||||
rc = xpmem_remove(segid);
|
||||
OKNG(rc == -1, "xpmem_remove");
|
||||
}
|
||||
|
||||
printf("*** %s PASSED\n\n", basename(argv[0]));
|
||||
return 0;
|
||||
|
||||
fn_fail:
|
||||
printf("*** %s FAILED\n\n", basename(argv[0]));
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -1,76 +0,0 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <xpmem.h>
|
||||
#include <libgen.h>
|
||||
#include "util2.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *mem, *attach;
|
||||
int rc = 0;
|
||||
int status;
|
||||
pid_t pid;
|
||||
xpmem_segid_t segid;
|
||||
xpmem_apid_t apid;
|
||||
struct xpmem_addr addr;
|
||||
|
||||
printf("*** %s start ***\n", basename(argv[0]));
|
||||
|
||||
mem = mmap(0, SZ_MEM, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE |
|
||||
MAP_HUGETLB | (LARGE_PAGE_SHIFT << MAP_HUGE_SHIFT), -1, 0);
|
||||
CHKANDJUMP(mem == NULL, "mmap");
|
||||
memset(mem, 0, SZ_MEM);
|
||||
|
||||
rc = xpmem_init();
|
||||
CHKANDJUMP(rc != 0, "xpmem_init");
|
||||
|
||||
segid = xpmem_make(mem, SZ_MEM, XPMEM_PERMIT_MODE, (void *)0666);
|
||||
OKNG(segid == -1, "xpmem_make");
|
||||
|
||||
fflush(0);
|
||||
pid = fork();
|
||||
CHKANDJUMP(pid == -1, "fork failed\n");
|
||||
|
||||
if (pid == 0) {
|
||||
/* Child process */
|
||||
apid = xpmem_get(segid, XPMEM_RDWR, XPMEM_PERMIT_MODE, NULL);
|
||||
OKNG(apid == -1, "xpmem_get in child");
|
||||
|
||||
addr.apid = apid;
|
||||
addr.offset = 0;
|
||||
attach = xpmem_attach(addr, SZ_MEM, NULL);
|
||||
OKNG(attach == (void *)-1, "xpmem_attach in child");
|
||||
|
||||
*((unsigned long *)attach) = TEST_VAL;
|
||||
|
||||
fflush(0);
|
||||
_exit(0);
|
||||
} else {
|
||||
/* Parent process */
|
||||
rc = waitpid(pid, &status, 0);
|
||||
CHKANDJUMP(rc == -1, "waitpid failed\n");
|
||||
|
||||
OKNG(*((unsigned long *)mem) != TEST_VAL, "validate TEST_VAL");
|
||||
|
||||
rc = xpmem_remove(segid);
|
||||
OKNG(rc == -1, "xpmem_remove");
|
||||
}
|
||||
|
||||
printf("*** %s PASSED\n\n", basename(argv[0]));
|
||||
return 0;
|
||||
|
||||
fn_fail:
|
||||
printf("*** %s FAILED\n\n", basename(argv[0]));
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <xpmem.h>
|
||||
#include <libgen.h>
|
||||
#include "util2.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *mem, *attach;
|
||||
int rc = 0;
|
||||
int status;
|
||||
pid_t pid;
|
||||
xpmem_segid_t segid;
|
||||
xpmem_apid_t apid;
|
||||
struct xpmem_addr addr;
|
||||
|
||||
printf("*** %s start ***\n", basename(argv[0]));
|
||||
|
||||
mem = mmap(0, SZ_MEM, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE |
|
||||
MAP_HUGETLB | (LARGE_PAGE_SHIFT << MAP_HUGE_SHIFT), -1, 0);
|
||||
CHKANDJUMP(mem == NULL, "mmap");
|
||||
memset(mem, 0, SZ_MEM);
|
||||
|
||||
rc = xpmem_init();
|
||||
CHKANDJUMP(rc != 0, "xpmem_init");
|
||||
|
||||
segid = xpmem_make(mem, SZ_MEM, XPMEM_PERMIT_MODE, (void *)0666);
|
||||
OKNG(segid == -1, "xpmem_make");
|
||||
|
||||
fflush(0);
|
||||
pid = fork();
|
||||
CHKANDJUMP(pid == -1, "fork failed\n");
|
||||
|
||||
if (pid == 0) {
|
||||
/* Child process */
|
||||
sleep(1); /* wait for parent process exit */
|
||||
apid = xpmem_get(segid, XPMEM_RDWR, XPMEM_PERMIT_MODE, NULL);
|
||||
OKNG(apid != -1,
|
||||
"xpmem_get in child failed (parent process exited already");
|
||||
fflush(0);
|
||||
|
||||
} else {
|
||||
/* Parent process */
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
printf("*** %s PASSED\n\n", basename(argv[0]));
|
||||
return 0;
|
||||
|
||||
fn_fail:
|
||||
printf("*** %s FAILED\n\n", basename(argv[0]));
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -1,89 +0,0 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <xpmem.h>
|
||||
#include <libgen.h>
|
||||
#include "util2.h"
|
||||
|
||||
#define BAD_ADDRESS ((void *)-1)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *mem, *attach;
|
||||
int rc = 0;
|
||||
int status;
|
||||
pid_t pid;
|
||||
xpmem_segid_t segid;
|
||||
xpmem_apid_t apid;
|
||||
struct xpmem_addr addr;
|
||||
|
||||
printf("*** %s start ***\n", basename(argv[0]));
|
||||
|
||||
mem = mmap(0, SZ_MEM, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE |
|
||||
MAP_HUGETLB | (LARGE_PAGE_SHIFT << MAP_HUGE_SHIFT), -1, 0);
|
||||
CHKANDJUMP(mem == NULL, "mmap");
|
||||
memset(mem, 0, SZ_MEM);
|
||||
|
||||
rc = xpmem_init();
|
||||
CHKANDJUMP(rc != 0, "xpmem_init");
|
||||
|
||||
segid = xpmem_make(BAD_ADDRESS, SZ_MEM, XPMEM_PERMIT_MODE,
|
||||
(void *)0666);
|
||||
OKNG(segid != -1, "xpmem_make failed (invalid address)");
|
||||
|
||||
segid = xpmem_make(mem, SZ_MEM, XPMEM_PERMIT_MODE, (void *)0666);
|
||||
CHKANDJUMP(segid == -1, "xpmem_make");
|
||||
|
||||
segid = xpmem_make(mem, SZ_MEM, XPMEM_PERMIT_MODE, (void *)0666);
|
||||
OKNG(segid == -1, "xpmem_make succeed(do twice to same address)");
|
||||
|
||||
fflush(0);
|
||||
pid = fork();
|
||||
CHKANDJUMP(pid == -1, "fork failed\n");
|
||||
|
||||
if (pid == 0) {
|
||||
/* Child process */
|
||||
apid = xpmem_get(segid, XPMEM_RDWR, XPMEM_PERMIT_MODE, NULL);
|
||||
CHKANDJUMP(apid == -1, "xpmem_get in child");
|
||||
|
||||
addr.apid = apid;
|
||||
addr.offset = 0;
|
||||
attach = xpmem_attach(addr, SZ_MEM, NULL);
|
||||
CHKANDJUMP(attach == (void *)-1, "xpmem_attach in child");
|
||||
|
||||
*((unsigned long *)attach) = TEST_VAL;
|
||||
|
||||
rc = xpmem_detach(attach);
|
||||
CHKANDJUMP(rc == -1, "xpmem_detach in child");
|
||||
|
||||
fflush(0);
|
||||
_exit(0);
|
||||
} else {
|
||||
/* Parent process */
|
||||
rc = waitpid(pid, &status, 0);
|
||||
CHKANDJUMP(rc == -1, "waitpid failed\n");
|
||||
|
||||
CHKANDJUMP(*((unsigned long *)mem) != TEST_VAL,
|
||||
"validate TEST_VAL");
|
||||
|
||||
rc = xpmem_remove(segid);
|
||||
CHKANDJUMP(rc == -1, "xpmem_remove");
|
||||
}
|
||||
|
||||
printf("*** %s PASSED\n\n", basename(argv[0]));
|
||||
return 0;
|
||||
|
||||
fn_fail:
|
||||
printf("*** %s FAILED\n\n", basename(argv[0]));
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -1,89 +0,0 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <xpmem.h>
|
||||
#include <libgen.h>
|
||||
#include "util2.h"
|
||||
|
||||
#define BAD_SEGID -1
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *mem, *attach;
|
||||
int rc = 0;
|
||||
int status;
|
||||
pid_t pid;
|
||||
xpmem_segid_t segid;
|
||||
xpmem_apid_t apid;
|
||||
struct xpmem_addr addr;
|
||||
|
||||
printf("*** %s start ***\n", basename(argv[0]));
|
||||
|
||||
mem = mmap(0, SZ_MEM, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE |
|
||||
MAP_HUGETLB | (LARGE_PAGE_SHIFT << MAP_HUGE_SHIFT), -1, 0);
|
||||
CHKANDJUMP(mem == NULL, "mmap");
|
||||
memset(mem, 0, SZ_MEM);
|
||||
|
||||
rc = xpmem_init();
|
||||
CHKANDJUMP(rc != 0, "xpmem_init");
|
||||
|
||||
segid = xpmem_make(mem, SZ_MEM, XPMEM_PERMIT_MODE, (void *)0666);
|
||||
CHKANDJUMP(segid == -1, "xpmem_make");
|
||||
|
||||
fflush(0);
|
||||
pid = fork();
|
||||
CHKANDJUMP(pid == -1, "fork failed\n");
|
||||
|
||||
if (pid == 0) {
|
||||
/* Child process */
|
||||
apid = xpmem_get(BAD_SEGID, XPMEM_RDWR, XPMEM_PERMIT_MODE,
|
||||
NULL);
|
||||
OKNG(apid != -1, "xpmem_get in child failed (invalid segid)");
|
||||
|
||||
apid = xpmem_get(segid, XPMEM_RDWR, XPMEM_PERMIT_MODE, NULL);
|
||||
CHKANDJUMP(apid == -1, "xpmem_get in child");
|
||||
|
||||
apid = xpmem_get(segid, XPMEM_RDWR, XPMEM_PERMIT_MODE, NULL);
|
||||
OKNG(apid == -1, "xpmem_get in child (do twice to same segid");
|
||||
|
||||
addr.apid = apid;
|
||||
addr.offset = 0;
|
||||
attach = xpmem_attach(addr, SZ_MEM, NULL);
|
||||
CHKANDJUMP(attach == (void *)-1, "xpmem_attach in child");
|
||||
|
||||
*((unsigned long *)attach) = TEST_VAL;
|
||||
|
||||
rc = xpmem_detach(attach);
|
||||
CHKANDJUMP(rc == -1, "xpmem_detach in child");
|
||||
|
||||
fflush(0);
|
||||
_exit(0);
|
||||
} else {
|
||||
/* Parent process */
|
||||
rc = waitpid(pid, &status, 0);
|
||||
CHKANDJUMP(rc == -1, "waitpid failed\n");
|
||||
|
||||
CHKANDJUMP(*((unsigned long *)mem) != TEST_VAL,
|
||||
"validate TEST_VAL");
|
||||
|
||||
rc = xpmem_remove(segid);
|
||||
CHKANDJUMP(rc == -1, "xpmem_remove");
|
||||
}
|
||||
|
||||
printf("*** %s PASSED\n\n", basename(argv[0]));
|
||||
return 0;
|
||||
|
||||
fn_fail:
|
||||
printf("*** %s FAILED\n\n", basename(argv[0]));
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -1,92 +0,0 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <xpmem.h>
|
||||
#include <libgen.h>
|
||||
#include "util2.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *mem, *attach;
|
||||
int rc = 0;
|
||||
int status;
|
||||
pid_t pid;
|
||||
xpmem_segid_t segid;
|
||||
xpmem_apid_t apid;
|
||||
struct xpmem_addr addr;
|
||||
|
||||
printf("*** %s start ***\n", basename(argv[0]));
|
||||
|
||||
mem = mmap(0, SZ_MEM, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE |
|
||||
MAP_HUGETLB | (LARGE_PAGE_SHIFT << MAP_HUGE_SHIFT), -1, 0);
|
||||
CHKANDJUMP(mem == NULL, "mmap");
|
||||
memset(mem, 0, SZ_MEM);
|
||||
|
||||
rc = xpmem_init();
|
||||
CHKANDJUMP(rc != 0, "xpmem_init");
|
||||
|
||||
segid = xpmem_make(mem, SZ_MEM, XPMEM_PERMIT_MODE, (void *)0666);
|
||||
CHKANDJUMP(segid == -1, "xpmem_make");
|
||||
|
||||
fflush(0);
|
||||
pid = fork();
|
||||
CHKANDJUMP(pid == -1, "fork failed\n");
|
||||
|
||||
if (pid == 0) {
|
||||
/* Child process */
|
||||
apid = xpmem_get(segid, XPMEM_RDWR, XPMEM_PERMIT_MODE, NULL);
|
||||
CHKANDJUMP(apid == -1, "xpmem_get in child");
|
||||
|
||||
addr.apid = -1;
|
||||
addr.offset = 0;
|
||||
attach = xpmem_attach(addr, SZ_MEM, NULL);
|
||||
OKNG(attach != (void *)-1,
|
||||
"xpmem_attach in childi failed (invalid apid)");
|
||||
|
||||
addr.apid = apid;
|
||||
addr.offset = 0;
|
||||
attach = xpmem_attach(addr, SZ_MEM, NULL);
|
||||
CHKANDJUMP(attach == (void *)-1, "xpmem_attach in child");
|
||||
|
||||
addr.apid = apid;
|
||||
addr.offset = 0;
|
||||
attach = xpmem_attach(addr, SZ_MEM, NULL);
|
||||
OKNG(attach == (void *)-1,
|
||||
"xpmem_attach in child succeed (do twice to same apid)");
|
||||
|
||||
*((unsigned long *)attach) = TEST_VAL;
|
||||
|
||||
rc = xpmem_detach(attach);
|
||||
CHKANDJUMP(rc == -1, "xpmem_detach in child");
|
||||
|
||||
fflush(0);
|
||||
_exit(0);
|
||||
} else {
|
||||
/* Parent process */
|
||||
rc = waitpid(pid, &status, 0);
|
||||
CHKANDJUMP(rc == -1, "waitpid failed\n");
|
||||
|
||||
CHKANDJUMP(*((unsigned long *)mem) != TEST_VAL,
|
||||
"validate TEST_VAL");
|
||||
|
||||
rc = xpmem_remove(segid);
|
||||
CHKANDJUMP(rc == -1, "xpmem_remove");
|
||||
}
|
||||
|
||||
printf("*** %s PASSED\n\n", basename(argv[0]));
|
||||
return 0;
|
||||
|
||||
fn_fail:
|
||||
printf("*** %s FAILED\n\n", basename(argv[0]));
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -1,90 +0,0 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <xpmem.h>
|
||||
#include <libgen.h>
|
||||
#include "util2.h"
|
||||
|
||||
#define BAD_ADDRESS ((void *) -1)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *mem, *attach;
|
||||
int rc = 0;
|
||||
int status;
|
||||
pid_t pid;
|
||||
xpmem_segid_t segid;
|
||||
xpmem_apid_t apid;
|
||||
struct xpmem_addr addr;
|
||||
|
||||
printf("*** %s start ***\n", basename(argv[0]));
|
||||
|
||||
mem = mmap(0, SZ_MEM, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE |
|
||||
MAP_HUGETLB | (LARGE_PAGE_SHIFT << MAP_HUGE_SHIFT), -1, 0);
|
||||
CHKANDJUMP(mem == NULL, "mmap");
|
||||
memset(mem, 0, SZ_MEM);
|
||||
|
||||
rc = xpmem_init();
|
||||
CHKANDJUMP(rc != 0, "xpmem_init");
|
||||
|
||||
segid = xpmem_make(mem, SZ_MEM, XPMEM_PERMIT_MODE, (void *)0666);
|
||||
CHKANDJUMP(segid == -1, "xpmem_make");
|
||||
|
||||
fflush(0);
|
||||
pid = fork();
|
||||
CHKANDJUMP(pid == -1, "fork failed\n");
|
||||
|
||||
if (pid == 0) {
|
||||
/* Child process */
|
||||
apid = xpmem_get(segid, XPMEM_RDWR, XPMEM_PERMIT_MODE, NULL);
|
||||
CHKANDJUMP(apid == -1, "xpmem_get in child");
|
||||
|
||||
addr.apid = apid;
|
||||
addr.offset = 0;
|
||||
attach = xpmem_attach(addr, SZ_MEM, NULL);
|
||||
CHKANDJUMP(attach == (void *)-1, "xpmem_attach in child");
|
||||
|
||||
*((unsigned long *)attach) = TEST_VAL;
|
||||
|
||||
rc = xpmem_detach(BAD_ADDRESS);
|
||||
OKNG(rc == -1,
|
||||
"xpmem_detach in child succeed (invalid address)");
|
||||
|
||||
rc = xpmem_detach(attach);
|
||||
CHKANDJUMP(rc == -1, "xpmem_detach in child");
|
||||
|
||||
rc = xpmem_detach(attach);
|
||||
OKNG(rc == -1,
|
||||
"xpmem_detach in child succeed (do twice to same address)");
|
||||
|
||||
fflush(0);
|
||||
_exit(0);
|
||||
} else {
|
||||
/* Parent process */
|
||||
rc = waitpid(pid, &status, 0);
|
||||
CHKANDJUMP(rc == -1, "waitpid failed\n");
|
||||
|
||||
CHKANDJUMP(*((unsigned long *)mem) != TEST_VAL,
|
||||
"validate TEST_VAL");
|
||||
|
||||
rc = xpmem_remove(segid);
|
||||
CHKANDJUMP(rc == -1, "xpmem_remove");
|
||||
}
|
||||
|
||||
printf("*** %s PASSED\n\n", basename(argv[0]));
|
||||
return 0;
|
||||
|
||||
fn_fail:
|
||||
printf("*** %s FAILED\n\n", basename(argv[0]));
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -1,88 +0,0 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <xpmem.h>
|
||||
#include <libgen.h>
|
||||
#include "util2.h"
|
||||
|
||||
#define BAD_SEGID -1
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *mem, *attach;
|
||||
int rc = 0;
|
||||
int status;
|
||||
pid_t pid;
|
||||
xpmem_segid_t segid;
|
||||
xpmem_apid_t apid;
|
||||
struct xpmem_addr addr;
|
||||
|
||||
printf("*** %s start ***\n", basename(argv[0]));
|
||||
|
||||
mem = mmap(0, SZ_MEM, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE |
|
||||
MAP_HUGETLB | (LARGE_PAGE_SHIFT << MAP_HUGE_SHIFT), -1, 0);
|
||||
CHKANDJUMP(mem == NULL, "mmap");
|
||||
memset(mem, 0, SZ_MEM);
|
||||
|
||||
rc = xpmem_init();
|
||||
CHKANDJUMP(rc != 0, "xpmem_init");
|
||||
|
||||
segid = xpmem_make(mem, SZ_MEM, XPMEM_PERMIT_MODE, (void *)0666);
|
||||
CHKANDJUMP(segid == -1, "xpmem_make");
|
||||
|
||||
fflush(0);
|
||||
pid = fork();
|
||||
CHKANDJUMP(pid == -1, "fork failed\n");
|
||||
|
||||
if (pid == 0) {
|
||||
/* Child process */
|
||||
apid = xpmem_get(segid, XPMEM_RDWR, XPMEM_PERMIT_MODE, NULL);
|
||||
CHKANDJUMP(apid == -1, "xpmem_get in child");
|
||||
|
||||
addr.apid = apid;
|
||||
addr.offset = 0;
|
||||
attach = xpmem_attach(addr, SZ_MEM, NULL);
|
||||
CHKANDJUMP(attach == (void *)-1, "xpmem_attach in child");
|
||||
|
||||
*((unsigned long *)attach) = TEST_VAL;
|
||||
|
||||
rc = xpmem_detach(attach);
|
||||
CHKANDJUMP(rc == -1, "xpmem_detach in child");
|
||||
|
||||
fflush(0);
|
||||
_exit(0);
|
||||
} else {
|
||||
/* Parent process */
|
||||
rc = waitpid(pid, &status, 0);
|
||||
CHKANDJUMP(rc == -1, "waitpid failed\n");
|
||||
|
||||
CHKANDJUMP(*((unsigned long *)mem) != TEST_VAL,
|
||||
"validate TEST_VAL");
|
||||
|
||||
rc = xpmem_remove(BAD_SEGID);
|
||||
OKNG(rc != -1, "xpmem_remove failed (invalid segid)");
|
||||
|
||||
rc = xpmem_remove(segid);
|
||||
CHKANDJUMP(rc == -1, "xpmem_remove");
|
||||
|
||||
rc = xpmem_remove(segid);
|
||||
OKNG(rc != -1, "xpmem_remove failed (do twice to same segid)");
|
||||
}
|
||||
|
||||
printf("*** %s PASSED\n\n", basename(argv[0]));
|
||||
return 0;
|
||||
|
||||
fn_fail:
|
||||
printf("*** %s FAILED\n\n", basename(argv[0]));
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -1,2 +0,0 @@
|
||||
PGSHIFT_LIST=(21 29 34)
|
||||
SMALL_PGSIZE=65536
|
||||
@ -1,184 +0,0 @@
|
||||
*** C1259T01 start *******************************
|
||||
** xpmem_attach to Huge mapped memory range
|
||||
** end of range is aligned with Large page size
|
||||
pageshift: 21
|
||||
** [ OK ] seg_addr (100000400000) is allocated until xpmem_attach
|
||||
** [ OK ] xpmem_addr (100000400000) is allocated using large pages
|
||||
pageshift: 29
|
||||
** [ OK ] seg_addr (100020000000) is allocated until xpmem_attach
|
||||
** [ OK ] xpmem_addr (100020000000) is allocated using large pages
|
||||
pageshift: 34
|
||||
** [ OK ] seg_addr (100400000000) is allocated until xpmem_attach
|
||||
** [ OK ] xpmem_addr (100400000000) is allocated using large pages
|
||||
*** C1259T01: PASSED
|
||||
|
||||
*** C1259T02 start *******************************
|
||||
** xpmem_attach to Huge mapped memory range
|
||||
** end of range is NOT aligned with Large page size
|
||||
pageshift: 21
|
||||
** [ OK ] seg_addr (100000400000) is allocated until xpmem_attach
|
||||
** [ OK ] xpmem_addr (100000400000) is allocated using large pages
|
||||
pageshift: 29
|
||||
** [ OK ] seg_addr (100020000000) is allocated until xpmem_attach
|
||||
** [ OK ] xpmem_addr (100020000000) is allocated using large pages
|
||||
pageshift: 34
|
||||
** [ OK ] seg_addr (100400000000) is allocated until xpmem_attach
|
||||
** [ OK ] xpmem_addr (100400000000) is allocated using large pages
|
||||
*** C1259T02: PASSED
|
||||
|
||||
*** C1259T03 start *******************************
|
||||
** xpmem_attach to small mapped memory range
|
||||
pageshift: small page
|
||||
** [ OK ] xpmem_addr (100000210000) is allocated using small pages
|
||||
*** C1259T03: PASSED
|
||||
|
||||
*** C1259T04 start *******************************
|
||||
** xpmem_attach to multi pagesize range
|
||||
pageshift: 21
|
||||
** [ OK ] xpmem_addr (100000600000) is allocated using large pages
|
||||
*** C1259T04: PASSED
|
||||
|
||||
*** C1259T05 start *******************************
|
||||
** xpmem testsuite
|
||||
XPMEM version = 26003
|
||||
|
||||
==== test_base STARTS ====
|
||||
xpmem_proc1: mypid = 38514
|
||||
xpmem_proc1: sharing 262144 bytes
|
||||
xpmem_proc1: segid = 200009672 at 0x100000210000
|
||||
|
||||
xpmem_proc2: mypid = 38711
|
||||
xpmem_proc2: segid = 200009672
|
||||
xpmem_proc2: attached at 0x100000210000
|
||||
xpmem_proc2: adding 1 to all elems
|
||||
|
||||
xpmem_proc1: verifying data...done
|
||||
==== test_base PASSED ====
|
||||
|
||||
==== test_two_attach STARTS ====
|
||||
xpmem_proc1: mypid = 39028
|
||||
xpmem_proc1: sharing 262144 bytes
|
||||
xpmem_proc1: segid = 200009874 at 0x100000210000
|
||||
|
||||
xpmem_proc2: mypid = 39233
|
||||
xpmem_proc2: segid = 200009874
|
||||
xpmem_proc2: attached at 0x100000210000
|
||||
xpmem_proc2: attached at 0x100000250000
|
||||
xpmem_proc2: adding 1 to all elems using 0x100000210000
|
||||
xpmem_proc2: adding 1 to all elems using 0x100000250000
|
||||
|
||||
xpmem_proc1: verifying data...done
|
||||
==== test_two_attach PASSED ====
|
||||
|
||||
==== test_two_shares STARTS ====
|
||||
xpmem_proc1: mypid = 39429
|
||||
xpmem_proc1: sharing 2 segments, 262144 bytes each
|
||||
xpmem_proc1: segid[0] = 200009a05 at 0x100000210000
|
||||
xpmem_proc1: segid[1] = 400009a05 at 0x100000250000
|
||||
|
||||
xpmem_proc2: mypid = 39625
|
||||
xpmem_proc2: segid[0] = 200009a05
|
||||
xpmem_proc2: segid[1] = 400009a05
|
||||
xpmem_proc2: data[0] attached at 0x100000210000
|
||||
xpmem_proc2: data[1] attached at 0x100000250000
|
||||
xpmem_proc2: adding 1 to all elems using 0x100000210000
|
||||
xpmem_proc2: adding 1 to all elems using 0x100000250000
|
||||
|
||||
xpmem_proc1: verifying data...done
|
||||
==== test_two_shares PASSED ====
|
||||
|
||||
==== test_fork STARTS ====
|
||||
xpmem_proc1: mypid = 39831
|
||||
xpmem_proc1: sharing 262144 bytes
|
||||
xpmem_proc1: segid = 200009b97 at 0x100000210000
|
||||
|
||||
xpmem_proc2: mypid = 40027
|
||||
xpmem_proc2: segid = 200009b97
|
||||
xpmem_proc2: attached at 0x100000220000
|
||||
xpmem_proc2: reading to pin pages
|
||||
xpmem_proc2: waiting for COW...
|
||||
|
||||
xpmem_proc1: forking a child
|
||||
xpmem_proc1: adding 1 to all elems to induce COW
|
||||
|
||||
xpmem_child: hello from pid 40224
|
||||
|
||||
xpmem_proc1: give control back to xpmem_proc2
|
||||
|
||||
xpmem_proc2: adding 1 to all elems
|
||||
|
||||
xpmem_proc1: verifying data...done
|
||||
==== test_fork PASSED ====
|
||||
|
||||
*** XTP_001 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get
|
||||
[OK] xpmem_attach
|
||||
[OK] xpmem_detach
|
||||
[OK] xpmem_remove
|
||||
*** XTP_001 PASSED
|
||||
|
||||
*** XTP_002 start ***
|
||||
[OK] xpmem_make in child
|
||||
[OK] xpmem_get in child
|
||||
[OK] xpmem_attach in child
|
||||
[OK] xpmem_detach in child
|
||||
[OK] xpmem_remove in child
|
||||
*** XTP_002 PASSED
|
||||
|
||||
*** XTP_003 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get in child
|
||||
[OK] xpmem_attach in child
|
||||
[OK] xpmem_detach in child
|
||||
[OK] validate TEST_VAL
|
||||
[OK] xpmem_remove
|
||||
*** XTP_003 PASSED
|
||||
|
||||
*** XTP_004 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get in child
|
||||
[OK] xpmem_attach in child
|
||||
[OK] xpmem_detach in child
|
||||
[OK] validate TEST_VAL
|
||||
[OK] xpmem_remove
|
||||
*** XTP_004 PASSED
|
||||
|
||||
*** XTP_005 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get in child
|
||||
[OK] xpmem_attach in child
|
||||
[OK] validate TEST_VAL
|
||||
[OK] xpmem_remove
|
||||
*** XTP_005 PASSED
|
||||
|
||||
*** XTP_006 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get in child failed (parent process exited already
|
||||
*** XTP_006 PASSED
|
||||
|
||||
*** XTP_007 start ***
|
||||
[OK] xpmem_make failed (invalid address)
|
||||
[OK] xpmem_make succeed(do twice to same address)
|
||||
*** XTP_007 PASSED
|
||||
|
||||
*** XTP_008 start ***
|
||||
[OK] xpmem_get in child failed (invalid segid)
|
||||
[OK] xpmem_get in child (do twice to same segid
|
||||
*** XTP_008 PASSED
|
||||
|
||||
*** XTP_009 start ***
|
||||
[OK] xpmem_attach in childi failed (invalid apid)
|
||||
[OK] xpmem_attach in child succeed (do twice to same apid)
|
||||
*** XTP_009 PASSED
|
||||
|
||||
*** XTP_010 start ***
|
||||
[OK] xpmem_detach in child succeed (invalid address)
|
||||
[OK] xpmem_detach in child succeed (do twice to same address)
|
||||
*** XTP_010 PASSED
|
||||
|
||||
*** XTP_011 start ***
|
||||
[OK] xpmem_remove failed (invalid segid)
|
||||
[OK] xpmem_remove failed (do twice to same segid)
|
||||
*** XTP_011 PASSED
|
||||
|
||||
@ -1,182 +0,0 @@
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <xpmem.h>
|
||||
#include "util.h"
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#define SHM_SIZE (1UL << 12)
|
||||
|
||||
#define MAP_HUGE_SHIFT 26
|
||||
#define KEYWORD 0x12345678UL
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
printf("Usage: huge_page_map: <pgshift> <pgnum> <pgoffset>\n");
|
||||
printf("\tpgshift : pageshift of map area (Using MAP_HUGETLB)\n");
|
||||
printf("\t -1 means using small pagesize\n");
|
||||
printf("\tpgnum : number of page of map area\n");
|
||||
printf("\tpgoffset: offset of last page\n");
|
||||
}
|
||||
|
||||
|
||||
void *mmap_flag(size_t mapsize, int page_shift)
|
||||
{
|
||||
char *addr_mmap;
|
||||
int flags = MAP_ANONYMOUS | MAP_PRIVATE;
|
||||
|
||||
if (page_shift >= 0) {
|
||||
/* mean use MAP_HUGETLB */
|
||||
flags |= MAP_HUGETLB | (page_shift << MAP_HUGE_SHIFT);
|
||||
}
|
||||
|
||||
addr_mmap = mmap(0, mapsize,
|
||||
PROT_READ | PROT_WRITE,
|
||||
flags, -1, 0);
|
||||
|
||||
return addr_mmap;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *mem;
|
||||
int ret = 0;
|
||||
pid_t pid;
|
||||
int status;
|
||||
key_t key = ftok(argv[0], 0);
|
||||
void *shm;
|
||||
int shmid;
|
||||
xpmem_segid_t segid;
|
||||
struct shmid_ds shmctl_buf;
|
||||
int pgshift, pgnum;
|
||||
size_t pgsize, map_size, pgoffset;
|
||||
|
||||
if (argc < 4) {
|
||||
printf("Err: Too few arguments\n");
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
pgshift = atoi(argv[1]);
|
||||
pgnum = atoi(argv[2]);
|
||||
pgoffset = atol(argv[3]);
|
||||
if (pgshift > 0) {
|
||||
pgsize = (1UL << pgshift);
|
||||
} else {
|
||||
pgsize = getpagesize();
|
||||
}
|
||||
|
||||
if (pgoffset > 0) {
|
||||
map_size = (pgsize * (pgnum - 1)) + pgoffset;
|
||||
} else {
|
||||
map_size = pgsize * pgnum;
|
||||
}
|
||||
|
||||
shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0660);
|
||||
CHKANDJUMP(shmid == -1, EXIT_FAILURE, "shmget failed: %s\n",
|
||||
strerror(errno));
|
||||
|
||||
printf("EXPECT_PAGE_SIZE: 0x%lx\n", pgsize);
|
||||
fflush(stdout);
|
||||
|
||||
pid = fork();
|
||||
CHKANDJUMP(pid == -1, EXIT_FAILURE, "fork failed\n");
|
||||
if (pid == 0) {
|
||||
xpmem_apid_t apid;
|
||||
struct xpmem_addr addr;
|
||||
void *attach;
|
||||
|
||||
shm = shmat(shmid, NULL, 0);
|
||||
CHKANDJUMP(shm == (void *)-1, EXIT_FAILURE,
|
||||
"shmat failed: %s\n", strerror(errno));
|
||||
|
||||
while ((segid = *(xpmem_segid_t *)shm) == 0) {
|
||||
};
|
||||
|
||||
ret = shmdt(shm);
|
||||
CHKANDJUMP(ret == -1, EXIT_FAILURE, "shmdt failed\n");
|
||||
|
||||
apid = xpmem_get(segid, XPMEM_RDWR,
|
||||
XPMEM_PERMIT_MODE, NULL);
|
||||
CHKANDJUMP(apid == -1, EXIT_FAILURE, "xpmem_get failed: %s\n",
|
||||
strerror(errno));
|
||||
|
||||
addr.apid = apid;
|
||||
addr.offset = 0;
|
||||
attach = xpmem_attach(addr, pgsize * pgnum, NULL);
|
||||
|
||||
CHKANDJUMP(attach == (void *)-1, EXIT_FAILURE,
|
||||
"xpmem_attach failed: %s\n", strerror(errno));
|
||||
|
||||
printf("child: xpmem_attachment_addr: %lx\n",
|
||||
attach);
|
||||
|
||||
*((unsigned long *)attach) = KEYWORD;
|
||||
if (pgnum > 1 && pgshift > 0) {
|
||||
*((unsigned long *)(attach +
|
||||
(1UL << pgshift))) = KEYWORD;
|
||||
}
|
||||
*((unsigned long *)(attach + map_size
|
||||
- sizeof(unsigned long *))) = KEYWORD;
|
||||
|
||||
ret = xpmem_detach(attach);
|
||||
CHKANDJUMP(ret == -1, EXIT_FAILURE, "xpmem_detach failed\n");
|
||||
|
||||
exit(0);
|
||||
} else {
|
||||
mem = mmap_flag(map_size, pgshift);
|
||||
CHKANDJUMP(mem == MAP_FAILED, EXIT_FAILURE, "mmap failed\n");
|
||||
printf("parent: anonymous_map_addr: %lx - %lx\n",
|
||||
mem, mem + map_size);
|
||||
|
||||
shm = shmat(shmid, NULL, 0);
|
||||
|
||||
CHKANDJUMP(shm == (void *)-1, EXIT_FAILURE,
|
||||
"shmat failed: %s\n", strerror(errno));
|
||||
|
||||
segid = xpmem_make(mem, map_size, XPMEM_PERMIT_MODE,
|
||||
(void *)0666);
|
||||
CHKANDJUMP(segid == -1, EXIT_FAILURE,
|
||||
"xpmem_ioctl failed: %s\n", strerror(errno));
|
||||
|
||||
*(xpmem_segid_t *)shm = segid;
|
||||
|
||||
ret = waitpid(pid, &status, 0);
|
||||
CHKANDJUMP(ret == -1, EXIT_FAILURE, "waitpid failed\n");
|
||||
|
||||
NG(*(unsigned long *)mem == KEYWORD,
|
||||
"HEAD of xpmem area is INVALID. isn't shared?\n");
|
||||
if (pgnum > 1 && pgshift > 0) {
|
||||
NG(*((unsigned long *)(mem +
|
||||
(1UL << pgshift))) == KEYWORD,
|
||||
"MIDDLE of xpmem area is INVALID. isn't shared?\n");
|
||||
}
|
||||
NG(*((unsigned long *)(mem + map_size
|
||||
- sizeof(unsigned long *))) == KEYWORD,
|
||||
"TAIL of xpmem area is INVALID. isn't shared?\n");
|
||||
printf("xpmem area is shared: OK\n");
|
||||
|
||||
ret = shmctl(shmid, IPC_RMID, &shmctl_buf);
|
||||
CHKANDJUMP(ret == -1, EXIT_FAILURE, "shmctl failed\n");
|
||||
|
||||
ret = shmdt(shm);
|
||||
CHKANDJUMP(ret == -1, EXIT_FAILURE, "shmdt failed\n");
|
||||
|
||||
ret = xpmem_remove(segid);
|
||||
CHKANDJUMP(ret == -1, EXIT_FAILURE, "xpmem_remove failed\n");
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@ -1,99 +0,0 @@
|
||||
diff --git arch/arm64/kernel/memory.c arch/arm64/kernel/memory.c
|
||||
index a84bc21..7368ada 100644
|
||||
--- arch/arm64/kernel/memory.c
|
||||
+++ arch/arm64/kernel/memory.c
|
||||
@@ -2701,6 +2701,13 @@ int set_range_l1(void *args0, pte_t *ptep, uintptr_t base, uintptr_t start,
|
||||
ptl1_set(ptep, pte);
|
||||
|
||||
error = 0;
|
||||
+
|
||||
+ if (args->attr[0] & PTE_CONT &&
|
||||
+ __page_offset(base, PTL1_CONT_SIZE) == 0) {
|
||||
+ kprintf("%s: large_page_allocation, addr: %016lx, size: 0x%lx , phys: %lx\n",
|
||||
+ __func__, base, PTL1_CONT_SIZE, phys);
|
||||
+ }
|
||||
+
|
||||
// call memory_stat_rss_add() here because pgshift is resolved here
|
||||
if (!(args->attr[0] & PTE_CONT)) {
|
||||
if (rusage_memory_stat_add(args->range, phys,
|
||||
@@ -2810,6 +2817,17 @@ retry:
|
||||
level);
|
||||
|
||||
error = 0;
|
||||
+
|
||||
+ if (args->attr[level-1] & PTE_CONT) {
|
||||
+ if (__page_offset(base, tbl.cont_pgsize) == 0) {
|
||||
+ kprintf("%s: large_page_allocation, addr: %016lx, size: 0x%lx , phys: %lx\n",
|
||||
+ __func__, base, tbl.cont_pgsize, phys);
|
||||
+ }
|
||||
+ } else {
|
||||
+ kprintf("%s: large_page_allocation, addr: %016lx, size: 0x%lx , phys: %lx\n",
|
||||
+ __func__, base, tbl.pgsize, phys);
|
||||
+ }
|
||||
+
|
||||
dkprintf("set_range_middle(%lx,%lx,%lx,%d):"
|
||||
"large page. %d %lx\n",
|
||||
base, start, end, level, error, *ptep);
|
||||
diff --git arch/x86_64/kernel/memory.c arch/x86_64/kernel/memory.c
|
||||
index df545e1..633e390 100644
|
||||
--- arch/x86_64/kernel/memory.c
|
||||
+++ arch/x86_64/kernel/memory.c
|
||||
@@ -1931,6 +1931,10 @@ retry:
|
||||
dkprintf("set_range_l2(%lx,%lx,%lx):"
|
||||
"2MiB page. %d %lx\n",
|
||||
base, start, end, error, *ptep);
|
||||
+
|
||||
+ kprintf("%s: large_page_allocation, addr: %016lx, size: 0x%lx\n",
|
||||
+ __func__, base, PTL2_SIZE);
|
||||
+
|
||||
// Call memory_stat_rss_add() here because pgshift is resolved here
|
||||
if (rusage_memory_stat_add(args->range, phys, PTL2_SIZE, PTL2_SIZE)) {
|
||||
dkprintf("%lx+,%s: calling memory_stat_rss_add(),base=%lx,phys=%lx,size=%ld,pgsize=%ld\n", phys, __FUNCTION__, base, phys, PTL2_SIZE, PTL2_SIZE);
|
||||
@@ -2020,6 +2024,9 @@ retry:
|
||||
"1GiB page. %d %lx\n",
|
||||
base, start, end, error, *ptep);
|
||||
|
||||
+ kprintf("%s: large_page_allocation, addr: %016lx, size: 0x%lx\n",
|
||||
+ __func__, base, PTL3_SIZE);
|
||||
+
|
||||
// Call memory_stat_rss_add() here because pgshift is resolved here
|
||||
if (rusage_memory_stat_add(args->range, phys, PTL3_SIZE, PTL3_SIZE)) {
|
||||
dkprintf("%lx+,%s: calling memory_stat_rss_add(),base=%lx,phys=%lx,size=%ld,pgsize=%ld\n", phys, __FUNCTION__, base, phys, PTL3_SIZE, PTL3_SIZE);
|
||||
diff --git kernel/process.c kernel/process.c
|
||||
index 809f5e0..cba9e5a 100644
|
||||
--- kernel/process.c
|
||||
+++ kernel/process.c
|
||||
@@ -2059,6 +2059,12 @@ retry:
|
||||
}
|
||||
|
||||
dkprintf("%s: attr=%x\n", __FUNCTION__, attr);
|
||||
+
|
||||
+ if (pgsize > PAGE_SIZE) {
|
||||
+ kprintf("large_page_allocation, addr: %016lx, size: %d, phys: %lx\n",
|
||||
+ pgaddr, pgsize, phys);
|
||||
+ }
|
||||
+
|
||||
error = ihk_mc_pt_set_pte(vm->address_space->page_table, ptep,
|
||||
pgsize, phys, attr);
|
||||
if (error) {
|
||||
diff --git kernel/xpmem.c kernel/xpmem.c
|
||||
index e1d0231..c9da711 100644
|
||||
--- kernel/xpmem.c
|
||||
+++ kernel/xpmem.c
|
||||
@@ -514,6 +514,7 @@ static int xpmem_make(
|
||||
*segid_p = segid;
|
||||
|
||||
XPMEM_DEBUG("return: ret=%d, segid=0x%lx", 0, *segid_p);
|
||||
+ kprintf("%s: DONE\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1994,6 +1995,8 @@ int xpmem_update_process_page_table(
|
||||
flush_tlb_single(vaddr);
|
||||
att->flags |= XPMEM_FLAG_VALIDPTEs;
|
||||
|
||||
+ kprintf("%s: xpmem_page_attach, addr: %016lx, size: 0x%lx\n",
|
||||
+ __func__, vaddr, seg_pgsize);
|
||||
seg_vaddr += seg_pgsize;
|
||||
vaddr += seg_pgsize;
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
test -e /tmp/xpmem.share && rm -f /tmp/xpmem.share
|
||||
test -e /tmp/xpmem.lock && rm -f /tmp/xpmem.lock
|
||||
|
||||
# create TMP_SHARE_SIZE bytes defined in xpmem_test.h
|
||||
for i in `seq 0 31` ; do
|
||||
echo -n 0 >> /tmp/xpmem.share
|
||||
done
|
||||
echo 0 > /tmp/xpmem.lock
|
||||
|
||||
# Run the main test app
|
||||
mcexec $PWD/xpmem_master
|
||||
exit 0
|
||||
|
||||
@ -1,187 +0,0 @@
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <xpmem.h>
|
||||
#include "util.h"
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#define SHM_SIZE (1UL << 12)
|
||||
|
||||
#define MAP_HUGE_SHIFT 26
|
||||
#define KEYWORD 0x12345678UL
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
printf("Usage: multi_vmr_xpmem: <pgshift> <pgnum>\n");
|
||||
printf("\tpgshift : pageshift of map area (Using MAP_HUGETLB)\n");
|
||||
printf("\t -1 means using small pagesize\n");
|
||||
printf("\tpgnum : number of page of map area\n");
|
||||
}
|
||||
|
||||
|
||||
void *mmap_flag(size_t mapsize, int page_shift)
|
||||
{
|
||||
char *addr_mmap;
|
||||
int flags = MAP_ANONYMOUS | MAP_PRIVATE;
|
||||
|
||||
if (page_shift >= 0) {
|
||||
/* mean use MAP_HUGETLB */
|
||||
flags |= MAP_HUGETLB | (page_shift << MAP_HUGE_SHIFT);
|
||||
}
|
||||
|
||||
addr_mmap = mmap(0, mapsize * 2,
|
||||
PROT_READ | PROT_WRITE,
|
||||
flags, -1, 0);
|
||||
|
||||
/* Make sure that area before addr_map is available to
|
||||
* MAP_FIXED map
|
||||
*/
|
||||
return addr_mmap + mapsize;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *mem, *mem_1, *mem_2;
|
||||
int ret = 0;
|
||||
pid_t pid;
|
||||
int status;
|
||||
key_t key = ftok(argv[0], 10);
|
||||
void *shm;
|
||||
int shmid;
|
||||
xpmem_segid_t segid;
|
||||
struct shmid_ds shmctl_buf;
|
||||
int pgshift, pgnum;
|
||||
size_t extr_size, pgsize, map_size;
|
||||
|
||||
if (argc < 3) {
|
||||
printf("Err: Too few arguments\n");
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
pgshift = atoi(argv[1]);
|
||||
pgnum = atoi(argv[2]);
|
||||
extr_size = getpagesize() * 3;
|
||||
if (pgshift > 0) {
|
||||
pgsize = (1UL << pgshift);
|
||||
} else {
|
||||
pgsize = getpagesize();
|
||||
}
|
||||
|
||||
map_size = pgsize * pgnum;
|
||||
|
||||
shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0660);
|
||||
CHKANDJUMP(shmid == -1, EXIT_FAILURE, "shmget failed: %s\n",
|
||||
strerror(errno));
|
||||
|
||||
printf("EXPECT_PAGE_SIZE: 0x%lx\n", pgsize);
|
||||
fflush(stdout);
|
||||
|
||||
pid = fork();
|
||||
CHKANDJUMP(pid == -1, EXIT_FAILURE, "fork failed\n");
|
||||
if (pid == 0) {
|
||||
xpmem_apid_t apid;
|
||||
struct xpmem_addr addr;
|
||||
void *attach;
|
||||
|
||||
shm = shmat(shmid, NULL, 0);
|
||||
CHKANDJUMP(shm == (void *)-1, EXIT_FAILURE,
|
||||
"shmat failed: %s\n", strerror(errno));
|
||||
|
||||
while ((segid = *(xpmem_segid_t *)shm) == 0) {
|
||||
};
|
||||
ret = shmdt(shm);
|
||||
CHKANDJUMP(ret == -1, EXIT_FAILURE, "shmdt failed\n");
|
||||
|
||||
apid = xpmem_get(segid, XPMEM_RDWR,
|
||||
XPMEM_PERMIT_MODE, NULL);
|
||||
CHKANDJUMP(apid == -1, EXIT_FAILURE, "xpmem_get failed: %s\n",
|
||||
strerror(errno));
|
||||
|
||||
addr.apid = apid;
|
||||
addr.offset = 0;
|
||||
attach = xpmem_attach(addr, map_size + (extr_size * 2), NULL);
|
||||
|
||||
CHKANDJUMP(attach == (void *)-1, EXIT_FAILURE,
|
||||
"xpmem_attach failed: %s\n", strerror(errno));
|
||||
|
||||
printf("child: xpmem_attachment_addr: %lx - %lx\n",
|
||||
attach, attach + map_size + (extr_size * 2));
|
||||
printf("child: xpmem_large: %lx\n", attach + extr_size);
|
||||
|
||||
*((unsigned long *)attach) = KEYWORD;
|
||||
*((unsigned long *)(attach + extr_size)) = KEYWORD;
|
||||
*((unsigned long *)(attach + extr_size * 2 + map_size
|
||||
- sizeof(unsigned long *))) = KEYWORD;
|
||||
|
||||
ret = xpmem_detach(attach);
|
||||
CHKANDJUMP(ret == -1, EXIT_FAILURE, "xpmem_detach failed\n");
|
||||
|
||||
exit(0);
|
||||
} else {
|
||||
mem = mmap_flag(map_size, pgshift);
|
||||
CHKANDJUMP(mem == MAP_FAILED, EXIT_FAILURE, "mmap failed\n");
|
||||
mem_1 = mmap(mem - extr_size, extr_size,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED,
|
||||
-1, 0);
|
||||
mem_2 = mmap(mem + map_size, extr_size,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED,
|
||||
-1, 0);
|
||||
if ((mem_1 + extr_size != mem) || (mem_2 != mem + map_size)) {
|
||||
printf("vm_range is NOT contignuous!!\n");
|
||||
exit(1);
|
||||
}
|
||||
printf("parent: anonymous_map_addr: %lx - %lx\n",
|
||||
mem_1, mem_2 + extr_size);
|
||||
|
||||
shm = shmat(shmid, NULL, 0);
|
||||
|
||||
CHKANDJUMP(shm == (void *)-1, EXIT_FAILURE,
|
||||
"shmat failed: %s\n", strerror(errno));
|
||||
|
||||
segid = xpmem_make(mem_1, map_size + (extr_size * 2),
|
||||
XPMEM_PERMIT_MODE, (void *)0666);
|
||||
CHKANDJUMP(segid == -1, EXIT_FAILURE,
|
||||
"xpmem_ioctl failed: %s\n", strerror(errno));
|
||||
|
||||
*(xpmem_segid_t *)shm = segid;
|
||||
|
||||
ret = waitpid(pid, &status, 0);
|
||||
printf("child exited\n");
|
||||
CHKANDJUMP(ret == -1, EXIT_FAILURE, "waitpid failed\n");
|
||||
|
||||
NG(*(unsigned long *)mem_1 == KEYWORD,
|
||||
"HEAD of xpmem area is INVALID. isn't shared?\n");
|
||||
NG(*(unsigned long *)mem == KEYWORD,
|
||||
"MIDDLE of xpmem area is INVALID. isn't shared?\n");
|
||||
NG(*((unsigned long *)(mem_2 + extr_size
|
||||
- sizeof(unsigned long *))) == KEYWORD,
|
||||
"TAIL of xpmem area is INVALID. isn't shared?\n");
|
||||
printf("xpmem area is shared: OK\n");
|
||||
|
||||
ret = shmctl(shmid, IPC_RMID, &shmctl_buf);
|
||||
CHKANDJUMP(ret == -1, EXIT_FAILURE, "shmctl failed\n");
|
||||
|
||||
ret = shmdt(shm);
|
||||
CHKANDJUMP(ret == -1, EXIT_FAILURE, "shmdt failed\n");
|
||||
|
||||
ret = xpmem_remove(segid);
|
||||
CHKANDJUMP(ret == -1, EXIT_FAILURE, "xpmem_remove failed\n");
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
#ifndef __UTIL_H_INCLUDED__
|
||||
#define __UTIL_H_INCLUDED__
|
||||
|
||||
#define CHKANDJUMP(cond, err, ...) do { \
|
||||
if (cond) { \
|
||||
printf(__VA_ARGS__); \
|
||||
ret = err; \
|
||||
goto out; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define _OKNG(verb, jump, cond, fmt, args...) do { \
|
||||
if (cond) { \
|
||||
if (verb) \
|
||||
printf("[ OK ] " fmt, ##args); \
|
||||
} else { \
|
||||
printf("[ NG ] " fmt, ##args); \
|
||||
if (jump) \
|
||||
goto out; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define OKNG(args...) _OKNG(1, 1, ##args)
|
||||
#define NG(args...) _OKNG(0, 1, ##args)
|
||||
#define OKNGNOJUMP(args...) _OKNG(1, 0, ##args)
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,31 +0,0 @@
|
||||
#define CHKANDJUMP(cond, ...) do { \
|
||||
if (cond) { \
|
||||
fprintf(stderr, " [NG] "); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
fprintf(stderr, " failed\n"); \
|
||||
goto fn_fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define OKNG(cond, ...) do { \
|
||||
if (cond) { \
|
||||
CHKANDJUMP(cond, __VA_ARGS__); \
|
||||
} else { \
|
||||
fprintf(stdout, " [OK] "); \
|
||||
fprintf(stdout, __VA_ARGS__); \
|
||||
fprintf(stdout, "\n"); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#ifdef __aarch64__
|
||||
#define LARGE_PAGE_SHIFT 21
|
||||
#elif defined(__x86_64__)
|
||||
#define LARGE_PAGE_SHIFT 21
|
||||
#else
|
||||
#error "Non-compliant architecture."
|
||||
#endif
|
||||
|
||||
#define MAP_HUGE_SHIFT 26
|
||||
#define SZ_MEM (2 * (1ULL << LARGE_PAGE_SHIFT))
|
||||
#define TEST_VAL 0x1129
|
||||
@ -1,2 +0,0 @@
|
||||
PGSHIFT_LIST=(21 30)
|
||||
SMALL_PGSIZE=4096
|
||||
@ -1,178 +0,0 @@
|
||||
*** C1259T01 start *******************************
|
||||
** xpmem_attach to Huge mapped memory range
|
||||
** end of range is aligned with Large page size
|
||||
pageshift: 21
|
||||
** [ OK ] seg_addr (2aaaab000000) is allocated until xpmem_attach
|
||||
** [ OK ] xpmem_addr (2aaaab000000) is allocated using large pages
|
||||
pageshift: 30
|
||||
** [ OK ] seg_addr (2aaac0000000) is allocated until xpmem_attach
|
||||
** [ OK ] xpmem_addr (2aaac0000000) is allocated using large pages
|
||||
*** C1259T01: PASSED
|
||||
|
||||
*** C1259T02 start *******************************
|
||||
** xpmem_attach to Huge mapped memory range
|
||||
** end of range is NOT aligned with Large page size
|
||||
pageshift: 21
|
||||
** [ OK ] seg_addr (2aaaab000000) is allocated until xpmem_attach
|
||||
** [ OK ] xpmem_addr (2aaaab000000) is allocated using large pages
|
||||
pageshift: 30
|
||||
** [ OK ] seg_addr (2aaac0000000) is allocated until xpmem_attach
|
||||
** [ OK ] xpmem_addr (2aaac0000000) is allocated using large pages
|
||||
*** C1259T02: PASSED
|
||||
|
||||
*** C1259T03 start *******************************
|
||||
** xpmem_attach to small mapped memory range
|
||||
pageshift: small page
|
||||
** [ OK ] xpmem_addr (2aaaaafee000) is allocated using small pages
|
||||
*** C1259T03: PASSED
|
||||
|
||||
*** C1259T04 start *******************************
|
||||
** xpmem_attach to multi pagesize range
|
||||
pageshift: 21
|
||||
** [ OK ] xpmem_addr (2aaaab200000) is allocated using large pages
|
||||
*** C1259T04: PASSED
|
||||
|
||||
*** C1259T05 start *******************************
|
||||
** xpmem testsuite
|
||||
XPMEM version = 26003
|
||||
|
||||
==== test_base STARTS ====
|
||||
xpmem_proc1: mypid = 20070
|
||||
xpmem_proc1: sharing 16384 bytes
|
||||
xpmem_proc1: segid = 200004e66 at 0x2aaaaafee000
|
||||
|
||||
xpmem_proc2: mypid = 20490
|
||||
xpmem_proc2: segid = 200004e66
|
||||
xpmem_proc2: attached at 0x2aaaaafee000
|
||||
xpmem_proc2: adding 1 to all elems
|
||||
|
||||
xpmem_proc1: verifying data...done
|
||||
==== test_base PASSED ====
|
||||
|
||||
==== test_two_attach STARTS ====
|
||||
xpmem_proc1: mypid = 20913
|
||||
xpmem_proc1: sharing 16384 bytes
|
||||
xpmem_proc1: segid = 2000051b1 at 0x2aaaaafee000
|
||||
|
||||
xpmem_proc2: mypid = 21336
|
||||
xpmem_proc2: segid = 2000051b1
|
||||
xpmem_proc2: attached at 0x2aaaaafee000
|
||||
xpmem_proc2: attached at 0x2aaaaaff2000
|
||||
xpmem_proc2: adding 1 to all elems using 0x2aaaaafee000
|
||||
xpmem_proc2: adding 1 to all elems using 0x2aaaaaff2000
|
||||
|
||||
xpmem_proc1: verifying data...done
|
||||
==== test_two_attach PASSED ====
|
||||
|
||||
==== test_two_shares STARTS ====
|
||||
xpmem_proc1: mypid = 21758
|
||||
xpmem_proc1: sharing 2 segments, 16384 bytes each
|
||||
xpmem_proc1: segid[0] = 2000054fe at 0x2aaaaafee000
|
||||
xpmem_proc1: segid[1] = 4000054fe at 0x2aaaaaff2000
|
||||
|
||||
xpmem_proc2: mypid = 22179
|
||||
xpmem_proc2: segid[0] = 2000054fe
|
||||
xpmem_proc2: segid[1] = 4000054fe
|
||||
xpmem_proc2: data[0] attached at 0x2aaaaafee000
|
||||
xpmem_proc2: data[1] attached at 0x2aaaaaff2000
|
||||
xpmem_proc2: adding 1 to all elems using 0x2aaaaafee000
|
||||
xpmem_proc2: adding 1 to all elems using 0x2aaaaaff2000
|
||||
|
||||
xpmem_proc1: verifying data...done
|
||||
==== test_two_shares PASSED ====
|
||||
|
||||
==== test_fork STARTS ====
|
||||
xpmem_proc1: mypid = 22599
|
||||
xpmem_proc1: sharing 16384 bytes
|
||||
xpmem_proc1: segid = 200005847 at 0x2aaaaafee000
|
||||
|
||||
xpmem_proc2: mypid = 23022
|
||||
xpmem_proc2: segid = 200005847
|
||||
xpmem_proc2: attached at 0x2aaaaafef000
|
||||
xpmem_proc2: reading to pin pages
|
||||
xpmem_proc2: waiting for COW...
|
||||
|
||||
xpmem_proc1: forking a child
|
||||
xpmem_proc1: adding 1 to all elems to induce COW
|
||||
|
||||
xpmem_proc1: give control back to xpmem_proc2
|
||||
xpmem_child: hello from pid 23443
|
||||
|
||||
|
||||
xpmem_proc2: adding 1 to all elems
|
||||
|
||||
xpmem_proc1: verifying data...done
|
||||
==== test_fork PASSED ====
|
||||
|
||||
*** XTP_001 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get
|
||||
[OK] xpmem_attach
|
||||
[OK] xpmem_detach
|
||||
[OK] xpmem_remove
|
||||
*** XTP_001 PASSED
|
||||
|
||||
*** XTP_002 start ***
|
||||
[OK] xpmem_make in child
|
||||
[OK] xpmem_get in child
|
||||
[OK] xpmem_attach in child
|
||||
[OK] xpmem_detach in child
|
||||
[OK] xpmem_remove in child
|
||||
*** XTP_002 PASSED
|
||||
|
||||
*** XTP_003 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get in child
|
||||
[OK] xpmem_attach in child
|
||||
[OK] xpmem_detach in child
|
||||
[OK] validate TEST_VAL
|
||||
[OK] xpmem_remove
|
||||
*** XTP_003 PASSED
|
||||
|
||||
*** XTP_004 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get in child
|
||||
[OK] xpmem_attach in child
|
||||
[OK] xpmem_detach in child
|
||||
[OK] validate TEST_VAL
|
||||
[OK] xpmem_remove
|
||||
*** XTP_004 PASSED
|
||||
|
||||
*** XTP_005 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get in child
|
||||
[OK] xpmem_attach in child
|
||||
[OK] validate TEST_VAL
|
||||
[OK] xpmem_remove
|
||||
*** XTP_005 PASSED
|
||||
|
||||
*** XTP_006 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get in child failed (parent process exited already
|
||||
*** XTP_006 PASSED
|
||||
|
||||
*** XTP_007 start ***
|
||||
[OK] xpmem_make failed (invalid address)
|
||||
[OK] xpmem_make succeed(do twice to same address)
|
||||
*** XTP_007 PASSED
|
||||
|
||||
*** XTP_008 start ***
|
||||
[OK] xpmem_get in child failed (invalid segid)
|
||||
[OK] xpmem_get in child (do twice to same segid
|
||||
*** XTP_008 PASSED
|
||||
|
||||
*** XTP_009 start ***
|
||||
[OK] xpmem_attach in childi failed (invalid apid)
|
||||
[OK] xpmem_attach in child succeed (do twice to same apid)
|
||||
*** XTP_009 PASSED
|
||||
|
||||
*** XTP_010 start ***
|
||||
[OK] xpmem_detach in child succeed (invalid address)
|
||||
[OK] xpmem_detach in child succeed (do twice to same address)
|
||||
*** XTP_010 PASSED
|
||||
|
||||
*** XTP_011 start ***
|
||||
[OK] xpmem_remove failed (invalid segid)
|
||||
[OK] xpmem_remove failed (do twice to same segid)
|
||||
*** XTP_011 PASSED
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
【Issue#1330 動作確認】
|
||||
□ テスト内容
|
||||
1. xpmemの基本操作の確認
|
||||
mckernel/test/xpmemのテストを実行し、xpmemの基本操作が
|
||||
正常に動作することを確認する
|
||||
テスト内容の詳細はmckernel/test/xpmem/README を参照
|
||||
|
||||
□ 実行手順
|
||||
1. mckernel/test/xpmem に移動する
|
||||
1. xpmemのインストールディレクトリをMakefileとgo_test.sh中のXPMEM_DIRに記載する
|
||||
2. xpmemのビルドディレクトリをgo_test.sh中のXPMEM_BUILD_DIRに記載する
|
||||
3. 下記の手順でテストを実行する
|
||||
$ make test
|
||||
|
||||
McKernelのインストール先や、OSTEST, LTPの配置場所は、
|
||||
$HOME/.mck_test_config を参照している
|
||||
.mck_test_config は、McKernelをビルドした際に生成されるmck_test_config.sample ファイルを
|
||||
$HOMEにコピーし、適宜編集する
|
||||
|
||||
□ 実行結果
|
||||
x86_64_result.log, aarch64_result.log 参照。
|
||||
すべての項目をPASSしていることを確認。
|
||||
@ -1,151 +0,0 @@
|
||||
*** XPMEM_TESTSUITE start *******************************
|
||||
XPMEM version = 26003
|
||||
|
||||
==== test_base STARTS ====
|
||||
xpmem_proc1: mypid = 3962
|
||||
xpmem_proc1: sharing 262144 bytes
|
||||
xpmem_proc1: segid = 200000f7a at 0x100000210000
|
||||
|
||||
xpmem_proc2: mypid = 4161
|
||||
xpmem_proc2: segid = 200000f7a
|
||||
xpmem_proc2: attached at 0x100000210000
|
||||
xpmem_proc2: adding 1 to all elems
|
||||
|
||||
xpmem_proc1: verifying data...done
|
||||
==== test_base PASSED ====
|
||||
|
||||
==== test_two_attach STARTS ====
|
||||
xpmem_proc1: mypid = 4472
|
||||
xpmem_proc1: sharing 262144 bytes
|
||||
xpmem_proc1: segid = 200001178 at 0x100000210000
|
||||
|
||||
xpmem_proc2: mypid = 4670
|
||||
xpmem_proc2: segid = 200001178
|
||||
xpmem_proc2: attached at 0x100000210000
|
||||
xpmem_proc2: attached at 0x100000250000
|
||||
xpmem_proc2: adding 1 to all elems using 0x100000210000
|
||||
xpmem_proc2: adding 1 to all elems using 0x100000250000
|
||||
|
||||
xpmem_proc1: verifying data...done
|
||||
==== test_two_attach PASSED ====
|
||||
|
||||
==== test_two_shares STARTS ====
|
||||
xpmem_proc1: mypid = 4871
|
||||
xpmem_proc1: sharing 2 segments, 262144 bytes each
|
||||
xpmem_proc1: segid[0] = 200001307 at 0x100000210000
|
||||
xpmem_proc1: segid[1] = 400001307 at 0x100000250000
|
||||
|
||||
xpmem_proc2: mypid = 5068
|
||||
xpmem_proc2: segid[0] = 200001307
|
||||
xpmem_proc2: segid[1] = 400001307
|
||||
xpmem_proc2: data[0] attached at 0x100000210000
|
||||
xpmem_proc2: data[1] attached at 0x100000250000
|
||||
xpmem_proc2: adding 1 to all elems using 0x100000210000
|
||||
xpmem_proc2: adding 1 to all elems using 0x100000250000
|
||||
|
||||
xpmem_proc1: verifying data...done
|
||||
==== test_two_shares PASSED ====
|
||||
|
||||
==== test_fork STARTS ====
|
||||
xpmem_proc1: mypid = 5271
|
||||
xpmem_proc1: sharing 262144 bytes
|
||||
xpmem_proc1: segid = 200001497 at 0x100000210000
|
||||
|
||||
xpmem_proc2: mypid = 5468
|
||||
xpmem_proc2: segid = 200001497
|
||||
xpmem_proc2: attached at 0x100000220000
|
||||
xpmem_proc2: reading to pin pages
|
||||
xpmem_proc2: waiting for COW...
|
||||
|
||||
xpmem_proc1: forking a child
|
||||
xpmem_proc1: adding 1 to all elems to induce COW
|
||||
|
||||
xpmem_child: hello from pid 5789
|
||||
|
||||
xpmem_proc1: give control back to xpmem_proc2
|
||||
|
||||
xpmem_proc2: adding 1 to all elems
|
||||
|
||||
xpmem_proc1: verifying data...done
|
||||
==== test_fork PASSED ====
|
||||
|
||||
*** XTP_001 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get
|
||||
[OK] xpmem_attach
|
||||
[OK] xpmem_detach
|
||||
[OK] xpmem_remove
|
||||
*** XTP_001 PASSED
|
||||
|
||||
*** XTP_002 start ***
|
||||
[OK] xpmem_make in child
|
||||
[OK] xpmem_get in child
|
||||
[OK] xpmem_attach in child
|
||||
[OK] xpmem_detach in child
|
||||
[OK] xpmem_remove in child
|
||||
*** XTP_002 PASSED
|
||||
|
||||
*** XTP_003 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get in child
|
||||
[OK] xpmem_attach in child
|
||||
[OK] xpmem_detach in child
|
||||
[OK] validate TEST_VAL
|
||||
[OK] xpmem_remove
|
||||
*** XTP_003 PASSED
|
||||
|
||||
*** XTP_004 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get in child
|
||||
[OK] xpmem_attach in child
|
||||
[OK] xpmem_detach in child
|
||||
[OK] validate TEST_VAL
|
||||
[OK] xpmem_remove
|
||||
*** XTP_004 PASSED
|
||||
|
||||
*** XTP_005 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get in child
|
||||
[OK] xpmem_attach in child
|
||||
[OK] validate TEST_VAL
|
||||
[OK] xpmem_remove
|
||||
*** XTP_005 PASSED
|
||||
|
||||
*** XTP_006 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get in child failed (parent process exited already
|
||||
*** XTP_006 PASSED
|
||||
|
||||
*** XTP_007 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get in child
|
||||
[OK] xpmem_attach in child
|
||||
[OK] validate TEST_VAL
|
||||
[OK] xpmem_remove
|
||||
*** XTP_007 PASSED
|
||||
|
||||
*** XTP_901 start ***
|
||||
[OK] xpmem_make failed (invalid address)
|
||||
[OK] xpmem_make succeed(do twice to same address)
|
||||
*** XTP_901 PASSED
|
||||
|
||||
*** XTP_902 start ***
|
||||
[OK] xpmem_get in child failed (invalid segid)
|
||||
[OK] xpmem_get in child (do twice to same segid
|
||||
*** XTP_902 PASSED
|
||||
|
||||
*** XTP_903 start ***
|
||||
[OK] xpmem_attach in childi failed (invalid apid)
|
||||
[OK] xpmem_attach in child succeed (do twice to same apid)
|
||||
*** XTP_903 PASSED
|
||||
|
||||
*** XTP_904 start ***
|
||||
[OK] xpmem_detach in child succeed (invalid address)
|
||||
[OK] xpmem_detach in child succeed (do twice to same address)
|
||||
*** XTP_904 PASSED
|
||||
|
||||
*** XTP_905 start ***
|
||||
[OK] xpmem_remove failed (invalid segid)
|
||||
[OK] xpmem_remove failed (do twice to same segid)
|
||||
*** XTP_905 PASSED
|
||||
|
||||
@ -1,151 +0,0 @@
|
||||
*** XPMEM_TESTSUITE start *******************************
|
||||
XPMEM version = 26003
|
||||
|
||||
==== test_base STARTS ====
|
||||
xpmem_proc1: mypid = 4598
|
||||
xpmem_proc1: sharing 16384 bytes
|
||||
xpmem_proc1: segid = 2000011f6 at 0x2aaaaafee000
|
||||
|
||||
xpmem_proc2: mypid = 5018
|
||||
xpmem_proc2: segid = 2000011f6
|
||||
xpmem_proc2: attached at 0x2aaaaafee000
|
||||
xpmem_proc2: adding 1 to all elems
|
||||
|
||||
xpmem_proc1: verifying data...done
|
||||
==== test_base PASSED ====
|
||||
|
||||
==== test_two_attach STARTS ====
|
||||
xpmem_proc1: mypid = 5438
|
||||
xpmem_proc1: sharing 16384 bytes
|
||||
xpmem_proc1: segid = 20000153e at 0x2aaaaafee000
|
||||
|
||||
xpmem_proc2: mypid = 5858
|
||||
xpmem_proc2: segid = 20000153e
|
||||
xpmem_proc2: attached at 0x2aaaaafee000
|
||||
xpmem_proc2: attached at 0x2aaaaaff2000
|
||||
xpmem_proc2: adding 1 to all elems using 0x2aaaaafee000
|
||||
xpmem_proc2: adding 1 to all elems using 0x2aaaaaff2000
|
||||
|
||||
xpmem_proc1: verifying data...done
|
||||
==== test_two_attach PASSED ====
|
||||
|
||||
==== test_two_shares STARTS ====
|
||||
xpmem_proc1: mypid = 6278
|
||||
xpmem_proc1: sharing 2 segments, 16384 bytes each
|
||||
xpmem_proc1: segid[0] = 200001886 at 0x2aaaaafee000
|
||||
xpmem_proc1: segid[1] = 400001886 at 0x2aaaaaff2000
|
||||
|
||||
xpmem_proc2: mypid = 6698
|
||||
xpmem_proc2: segid[0] = 200001886
|
||||
xpmem_proc2: segid[1] = 400001886
|
||||
xpmem_proc2: data[0] attached at 0x2aaaaafee000
|
||||
xpmem_proc2: data[1] attached at 0x2aaaaaff2000
|
||||
xpmem_proc2: adding 1 to all elems using 0x2aaaaafee000
|
||||
xpmem_proc2: adding 1 to all elems using 0x2aaaaaff2000
|
||||
|
||||
xpmem_proc1: verifying data...done
|
||||
==== test_two_shares PASSED ====
|
||||
|
||||
==== test_fork STARTS ====
|
||||
xpmem_proc1: mypid = 7118
|
||||
xpmem_proc1: sharing 16384 bytes
|
||||
xpmem_proc1: segid = 200001bce at 0x2aaaaafee000
|
||||
|
||||
xpmem_proc2: mypid = 7538
|
||||
xpmem_proc2: segid = 200001bce
|
||||
xpmem_proc2: attached at 0x2aaaaafef000
|
||||
xpmem_proc2: reading to pin pages
|
||||
xpmem_proc2: waiting for COW...
|
||||
|
||||
xpmem_proc1: forking a child
|
||||
xpmem_proc1: adding 1 to all elems to induce COW
|
||||
|
||||
xpmem_proc1: give control back to xpmem_proc2
|
||||
|
||||
xpmem_child: hello from pid 7958
|
||||
|
||||
xpmem_proc2: adding 1 to all elems
|
||||
|
||||
xpmem_proc1: verifying data...done
|
||||
==== test_fork PASSED ====
|
||||
|
||||
*** XTP_001 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get
|
||||
[OK] xpmem_attach
|
||||
[OK] xpmem_detach
|
||||
[OK] xpmem_remove
|
||||
*** XTP_001 PASSED
|
||||
|
||||
*** XTP_002 start ***
|
||||
[OK] xpmem_make in child
|
||||
[OK] xpmem_get in child
|
||||
[OK] xpmem_attach in child
|
||||
[OK] xpmem_detach in child
|
||||
[OK] xpmem_remove in child
|
||||
*** XTP_002 PASSED
|
||||
|
||||
*** XTP_003 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get in child
|
||||
[OK] xpmem_attach in child
|
||||
[OK] xpmem_detach in child
|
||||
[OK] validate TEST_VAL
|
||||
[OK] xpmem_remove
|
||||
*** XTP_003 PASSED
|
||||
|
||||
*** XTP_004 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get in child
|
||||
[OK] xpmem_attach in child
|
||||
[OK] xpmem_detach in child
|
||||
[OK] validate TEST_VAL
|
||||
[OK] xpmem_remove
|
||||
*** XTP_004 PASSED
|
||||
|
||||
*** XTP_005 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get in child
|
||||
[OK] xpmem_attach in child
|
||||
[OK] validate TEST_VAL
|
||||
[OK] xpmem_remove
|
||||
*** XTP_005 PASSED
|
||||
|
||||
*** XTP_006 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get in child failed (parent process exited already
|
||||
*** XTP_006 PASSED
|
||||
|
||||
*** XTP_007 start ***
|
||||
[OK] xpmem_make
|
||||
[OK] xpmem_get in child
|
||||
[OK] xpmem_attach in child
|
||||
[OK] validate TEST_VAL
|
||||
[OK] xpmem_remove
|
||||
*** XTP_007 PASSED
|
||||
|
||||
*** XTP_901 start ***
|
||||
[OK] xpmem_make failed (invalid address)
|
||||
[OK] xpmem_make succeed(do twice to same address)
|
||||
*** XTP_901 PASSED
|
||||
|
||||
*** XTP_902 start ***
|
||||
[OK] xpmem_get in child failed (invalid segid)
|
||||
[OK] xpmem_get in child (do twice to same segid
|
||||
*** XTP_902 PASSED
|
||||
|
||||
*** XTP_903 start ***
|
||||
[OK] xpmem_attach in childi failed (invalid apid)
|
||||
[OK] xpmem_attach in child succeed (do twice to same apid)
|
||||
*** XTP_903 PASSED
|
||||
|
||||
*** XTP_904 start ***
|
||||
[OK] xpmem_detach in child succeed (invalid address)
|
||||
[OK] xpmem_detach in child succeed (do twice to same address)
|
||||
*** XTP_904 PASSED
|
||||
|
||||
*** XTP_905 start ***
|
||||
[OK] xpmem_remove failed (invalid segid)
|
||||
[OK] xpmem_remove failed (do twice to same segid)
|
||||
*** XTP_905 PASSED
|
||||
|
||||
56
test/issues/1377/C1377.sh
Normal file
56
test/issues/1377/C1377.sh
Normal file
@ -0,0 +1,56 @@
|
||||
#!/bin/sh
|
||||
USELTP=1
|
||||
USEOSTEST=0
|
||||
|
||||
. ../../common.sh
|
||||
|
||||
################################################################################
|
||||
if [ ! -f "$LTPBIN/dirtyc0w" ]; then
|
||||
echo BAD environment: LTP is too old >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "*** C1377T01 start"
|
||||
ng=0
|
||||
ok=0
|
||||
tp=dirtyc0w
|
||||
for ((i=0; i<20; i++)); do
|
||||
for ((j=0; j<50; j++)); do
|
||||
sudo PATH=$PATH:$LTPBIN $MCEXEC $LTPBIN/$tp > $tp.txt 2>&1
|
||||
wok=`grep PASS $tp.txt | wc -l`
|
||||
wng=`grep FAIL $tp.txt | wc -l`
|
||||
if [ $wng != 0 ]; then
|
||||
echo -n '*'
|
||||
ng=`expr $ng + 1`
|
||||
elif [ $wok == 0 ]; then
|
||||
echo -n '?'
|
||||
else
|
||||
echo -n '.'
|
||||
ok=`expr $ok + 1`
|
||||
fi
|
||||
done
|
||||
echo
|
||||
done
|
||||
|
||||
if [ $ng != 0 ]; then
|
||||
echo "*** C1377T01 FAILED ok: $ok, ng: $ng"
|
||||
else
|
||||
echo "*** C1377T01 PASS ok: $ok"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
for i in wait02:02 wait401:03 waitpid01:04 waitpid02:05 waitpid04:06 \
|
||||
waitpid05:07 waitpid06:08 waitpid07:09 waitpid08:10 waitpid09:11 \
|
||||
waitpid10:12 waitpid11:13 waitpid12:14 waitpid13:15; do
|
||||
tp=`echo $i|sed 's/:.*//'`
|
||||
id=`echo $i|sed 's/.*://'`
|
||||
sudo PATH=$PATH:$LTPBIN $MCEXEC $LTPBIN/$tp 2>&1 | tee $tp.txt
|
||||
ok=`grep PASS $tp.txt | wc -l`
|
||||
ng=`grep FAIL $tp.txt | wc -l`
|
||||
if [ $ng = 0 ]; then
|
||||
echo "*** C1377T$id: $tp PASS ($ok)"
|
||||
else
|
||||
echo "*** C1377T$id: $tp FAIL (ok=$ok ng=$ng)"
|
||||
fi
|
||||
done
|
||||
179
test/issues/1377/C1377_arm64.txt
Normal file
179
test/issues/1377/C1377_arm64.txt
Normal file
@ -0,0 +1,179 @@
|
||||
Script started on Tue 16 Jun 2020 02:42:48 PM JST
|
||||
[shirasawa@apollo04 1377]$ make test
|
||||
sh ./C1377.sh
|
||||
mcstop+release.sh ... done
|
||||
mcreboot.sh -c 2-31 -m 2G@0,2G@1 -O ... done
|
||||
*** C1377T01 start
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
*** C1377T01 PASS ok: 1000
|
||||
wait02 1 TPASS : wait(&status) returned 78343
|
||||
*** C1377T02: wait02 PASS (1)
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
wait401.c:55: PASS: waitpid() returned correct pid 78457
|
||||
wait401.c:64: PASS: WIFEXITED() is set in status
|
||||
wait401.c:69: PASS: WEXITSTATUS() == 0
|
||||
|
||||
Summary:
|
||||
passed 3
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1377T03: wait401 PASS (3)
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
waitpid01.c:51: PASS: waitpid() returned correct pid 78571
|
||||
waitpid01.c:60: PASS: WIFSIGNALED() set in status
|
||||
waitpid01.c:68: PASS: WTERMSIG() == SIGALRM
|
||||
|
||||
Summary:
|
||||
passed 3
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1377T04: waitpid01 PASS (3)
|
||||
waitpid02 1 TPASS : received expected pid
|
||||
waitpid02 2 TPASS : received expected signal
|
||||
waitpid02 3 TPASS : received expected exit value
|
||||
*** C1377T05: waitpid02 PASS (3)
|
||||
waitpid04 1 TPASS : condition 1 test passed
|
||||
waitpid04 2 TPASS : condition 2 test passed
|
||||
waitpid04 3 TPASS : condition 3 test passed
|
||||
*** C1377T06: waitpid04 PASS (3)
|
||||
waitpid05 1 TPASS : received expected pid.
|
||||
waitpid05 2 TPASS : received expected exit number.
|
||||
waitpid05 3 TPASS : received expected pid.
|
||||
waitpid05 4 TPASS : received expected exit number.
|
||||
waitpid05 5 TPASS : received expected pid.
|
||||
waitpid05 6 TPASS : received expected exit number.
|
||||
waitpid05 7 TPASS : received expected pid.
|
||||
waitpid05 8 TPASS : received expected exit number.
|
||||
waitpid05 9 TPASS : received expected pid.
|
||||
waitpid05 10 TPASS : received expected exit number.
|
||||
waitpid05 11 TPASS : received expected pid.
|
||||
waitpid05 12 TPASS : received expected exit number.
|
||||
waitpid05 13 TPASS : received expected pid.
|
||||
waitpid05 14 TPASS : received expected exit number.
|
||||
waitpid05 15 TPASS : received expected pid.
|
||||
waitpid05 16 TPASS : received expected exit number.
|
||||
waitpid05 17 TPASS : received expected pid.
|
||||
waitpid05 18 TPASS : received expected exit number.
|
||||
waitpid05 19 TPASS : received expected pid.
|
||||
waitpid05 20 TPASS : received expected exit number.
|
||||
waitpid05 21 TPASS : received expected pid.
|
||||
waitpid05 22 TPASS : received expected exit number.
|
||||
waitpid05 23 TPASS : received expected pid.
|
||||
waitpid05 24 TPASS : received expected exit number.
|
||||
*** C1377T07: waitpid05 PASS (24)
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
waitpid06.c:54: PASS: Test PASSED
|
||||
|
||||
Summary:
|
||||
passed 1
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1377T08: waitpid06 PASS (1)
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
waitpid07.c:59: PASS: Test PASSED
|
||||
|
||||
Summary:
|
||||
passed 1
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1377T09: waitpid07 PASS (1)
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 80073
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 80105
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 80137
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 80169
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 80201
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 80233
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 80266
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 80298
|
||||
waitpid08.c:62: PASS: Test PASSED
|
||||
|
||||
Summary:
|
||||
passed 1
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1377T10: waitpid08 PASS (1)
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
waitpid09.c:83: PASS: waitpid(pid, WNOHANG) = 0 for a running child
|
||||
waitpid09.c:123: PASS: waitpid(pid, WNOHANG) = pid for an exited child
|
||||
waitpid09.c:143: PASS: waitpid(-1, 0) = -1 with ECHILD if no children
|
||||
waitpid09.c:162: PASS: waitpid(-1, WNOHANG) = -1 with ECHILD if no children
|
||||
|
||||
Summary:
|
||||
passed 4
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1377T11: waitpid09 PASS (4)
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
waitpid10.c:62: PASS: Test PASSED
|
||||
|
||||
Summary:
|
||||
passed 1
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1377T12: waitpid10 PASS (1)
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
waitpid11.c:60: PASS: Test PASSED
|
||||
|
||||
Summary:
|
||||
passed 1
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1377T13: waitpid11 PASS (1)
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
waitpid12.c:70: PASS: Test PASSED
|
||||
|
||||
Summary:
|
||||
passed 1
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1377T14: waitpid12 PASS (1)
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 85038
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 85070
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 85102
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 85134
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 84910
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 84942
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 84974
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 85006
|
||||
waitpid13.c:70: PASS: Test PASSED
|
||||
|
||||
Summary:
|
||||
passed 1
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1377T15: waitpid13 PASS (1)
|
||||
[shirasawa@apollo04 1377]$ exit
|
||||
exit
|
||||
|
||||
Script done on Tue 16 Jun 2020 03:02:48 PM JST
|
||||
179
test/issues/1377/C1377_x86_64.txt
Normal file
179
test/issues/1377/C1377_x86_64.txt
Normal file
@ -0,0 +1,179 @@
|
||||
Script started on Tue Jun 16 15:36:06 2020
|
||||
bash-4.2$ make test
|
||||
sh ./C1377.sh
|
||||
mcstop+release.sh ... done
|
||||
mcreboot.sh -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 ... done
|
||||
*** C1377T01 start
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
..................................................
|
||||
*** C1377T01 PASS ok: 1000
|
||||
wait02 1 TPASS : wait(&status) returned 32240
|
||||
*** C1377T02: wait02 PASS (1)
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
wait401.c:55: PASS: waitpid() returned correct pid 32347
|
||||
wait401.c:64: PASS: WIFEXITED() is set in status
|
||||
wait401.c:69: PASS: WEXITSTATUS() == 0
|
||||
|
||||
Summary:
|
||||
passed 3
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1377T03: wait401 PASS (3)
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
waitpid01.c:51: PASS: waitpid() returned correct pid 32454
|
||||
waitpid01.c:60: PASS: WIFSIGNALED() set in status
|
||||
waitpid01.c:68: PASS: WTERMSIG() == SIGALRM
|
||||
|
||||
Summary:
|
||||
passed 3
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1377T04: waitpid01 PASS (3)
|
||||
waitpid02 1 TPASS : received expected pid
|
||||
waitpid02 2 TPASS : received expected signal
|
||||
waitpid02 3 TPASS : received expected exit value
|
||||
*** C1377T05: waitpid02 PASS (3)
|
||||
waitpid04 1 TPASS : condition 1 test passed
|
||||
waitpid04 2 TPASS : condition 2 test passed
|
||||
waitpid04 3 TPASS : condition 3 test passed
|
||||
*** C1377T06: waitpid04 PASS (3)
|
||||
waitpid05 1 TPASS : received expected pid.
|
||||
waitpid05 2 TPASS : received expected exit number.
|
||||
waitpid05 3 TPASS : received expected pid.
|
||||
waitpid05 4 TPASS : received expected exit number.
|
||||
waitpid05 5 TPASS : received expected pid.
|
||||
waitpid05 6 TPASS : received expected exit number.
|
||||
waitpid05 7 TPASS : received expected pid.
|
||||
waitpid05 8 TPASS : received expected exit number.
|
||||
waitpid05 9 TPASS : received expected pid.
|
||||
waitpid05 10 TPASS : received expected exit number.
|
||||
waitpid05 11 TPASS : received expected pid.
|
||||
waitpid05 12 TPASS : received expected exit number.
|
||||
waitpid05 13 TPASS : received expected pid.
|
||||
waitpid05 14 TPASS : received expected exit number.
|
||||
waitpid05 15 TPASS : received expected pid.
|
||||
waitpid05 16 TPASS : received expected exit number.
|
||||
waitpid05 17 TPASS : received expected pid.
|
||||
waitpid05 18 TPASS : received expected exit number.
|
||||
waitpid05 19 TPASS : received expected pid.
|
||||
waitpid05 20 TPASS : received expected exit number.
|
||||
waitpid05 21 TPASS : received expected pid.
|
||||
waitpid05 22 TPASS : received expected exit number.
|
||||
waitpid05 23 TPASS : received expected pid.
|
||||
waitpid05 24 TPASS : received expected exit number.
|
||||
*** C1377T07: waitpid05 PASS (24)
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
waitpid06.c:54: PASS: Test PASSED
|
||||
|
||||
Summary:
|
||||
passed 1
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1377T08: waitpid06 PASS (1)
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
waitpid07.c:59: PASS: Test PASSED
|
||||
|
||||
Summary:
|
||||
passed 1
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1377T09: waitpid07 PASS (1)
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 1524
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 1554
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 1584
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 1614
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 1644
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 1674
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 1704
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 1734
|
||||
waitpid08.c:62: PASS: Test PASSED
|
||||
|
||||
Summary:
|
||||
passed 1
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1377T10: waitpid08 PASS (1)
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
waitpid09.c:83: PASS: waitpid(pid, WNOHANG) = 0 for a running child
|
||||
waitpid09.c:123: PASS: waitpid(pid, WNOHANG) = pid for an exited child
|
||||
waitpid09.c:143: PASS: waitpid(-1, 0) = -1 with ECHILD if no children
|
||||
waitpid09.c:162: PASS: waitpid(-1, WNOHANG) = -1 with ECHILD if no children
|
||||
|
||||
Summary:
|
||||
passed 4
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1377T11: waitpid09 PASS (4)
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
waitpid10.c:62: PASS: Test PASSED
|
||||
|
||||
Summary:
|
||||
passed 1
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1377T12: waitpid10 PASS (1)
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
waitpid11.c:60: PASS: Test PASSED
|
||||
|
||||
Summary:
|
||||
passed 1
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1377T13: waitpid11 PASS (1)
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
waitpid12.c:70: PASS: Test PASSED
|
||||
|
||||
Summary:
|
||||
passed 1
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1377T14: waitpid12 PASS (1)
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 6219
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 6249
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 6279
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 6309
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 6099
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 6129
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 6159
|
||||
waitpid_common.h:142: INFO: Sending SIGCONT to 6189
|
||||
waitpid13.c:70: PASS: Test PASSED
|
||||
|
||||
Summary:
|
||||
passed 1
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1377T15: waitpid13 PASS (1)
|
||||
bash-4.2$ exit
|
||||
exit
|
||||
|
||||
Script done on Tue Jun 16 15:55:52 2020
|
||||
9
test/issues/1377/Makefile
Normal file
9
test/issues/1377/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
CC = gcc
|
||||
|
||||
all::
|
||||
|
||||
test:: all
|
||||
sh ./C1377.sh
|
||||
|
||||
clean::
|
||||
rm -f $(TARGET) *.o
|
||||
38
test/issues/1377/README
Normal file
38
test/issues/1377/README
Normal file
@ -0,0 +1,38 @@
|
||||
【Issue#1377 動作確認】
|
||||
□ テスト内容
|
||||
1. Issue 指摘事項の再現確認
|
||||
現象はタイミングに依存し、ARM64環境でdirtyc0wを繰り返し実行した際に、
|
||||
数回〜数十回に1回程度発生する。
|
||||
問題の発生はタイミングに依存するため、dirtyc0wを十分な回数繰り返し
|
||||
実行し、問題が再発しないことを確認する。
|
||||
|
||||
C1377T01 dirtyc0wを1000回連続実行し、全てPASSすることを確認
|
||||
|
||||
2. LTP を用いて既存処理に影響しないことを確認
|
||||
プロセスの終了ステータスを変更したため、修正が既存処理に影響しないことを
|
||||
wait系システムコールのLTPを用いて確認する。
|
||||
C1377T02 wait02: waitの基本機能の確認
|
||||
C1377T03 wait401: wait4の基本機能の確認
|
||||
C1377T04 waitpid01: waitpidの基本機能の確認
|
||||
C1377T05 waitpid02: waitpidの基本機能の確認
|
||||
C1377T06 waitpid04: waitpidの基本機能の確認
|
||||
C1377T07 waitpid05: waitpidの基本機能の確認
|
||||
C1377T08 waitpid06: waitpidの基本機能の確認
|
||||
C1377T09 waitpid07: waitpidの基本機能の確認
|
||||
C1377T10 waitpid08: waitpidの基本機能の確認
|
||||
C1377T11 waitpid09: waitpidの基本機能の確認
|
||||
C1377T12 waitpid10: waitpidの基本機能の確認
|
||||
C1377T13 waitpid11: waitpidの基本機能の確認
|
||||
C1377T14 waitpid12: waitpidの基本機能の確認
|
||||
C1377T15 waitpid13: waitpidの基本機能の確認
|
||||
|
||||
□ 実行手順
|
||||
$ make test
|
||||
|
||||
McKernelのインストール先や LTP の配置場所は、$HOME/.mck_test_config を
|
||||
参照する。.mck_test_config は、McKernel をビルドした際に生成される
|
||||
mck_test_config.sample ファイルを $HOME にコピーし、適宜編集すること。
|
||||
|
||||
□ 実行結果
|
||||
C1377_x86_64.txt(x86_64実行結果)、C1377_arm64.txt(arm64実行結果)参照。
|
||||
全ての項目が PASS していることを確認。
|
||||
26
test/issues/1380/C1380.sh
Executable file
26
test/issues/1380/C1380.sh
Executable file
@ -0,0 +1,26 @@
|
||||
#/bin/sh
|
||||
|
||||
USELTP=1
|
||||
USEOSTEST=0
|
||||
|
||||
. ../../common.sh
|
||||
|
||||
issue="1380"
|
||||
tid=01
|
||||
|
||||
for tp in tgkill03 tgkill01 tkill01 tkill02
|
||||
do
|
||||
tname=`printf "C${issue}T%02d" ${tid}`
|
||||
echo "*** ${tname} start *******************************"
|
||||
sudo $MCEXEC $LTPBIN/$tp 2>&1 | tee $tp.txt
|
||||
ok=`grep PASS $tp.txt | wc -l`
|
||||
ng=`grep FAIL $tp.txt | wc -l`
|
||||
if [ $ng = 0 ]; then
|
||||
echo "*** ${tname} PASSED ($ok)"
|
||||
else
|
||||
echo "*** ${tname} FAILED (ok=$ok ng=$ng)"
|
||||
fi
|
||||
let tid++
|
||||
echo ""
|
||||
done
|
||||
|
||||
11
test/issues/1380/Makefile
Normal file
11
test/issues/1380/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
CFLAGS=-g
|
||||
LDFLAGS=
|
||||
|
||||
TARGET=
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
test: all
|
||||
./C1380.sh
|
||||
clean:
|
||||
rm -f $(TARGET) *.o *.txt
|
||||
21
test/issues/1380/README
Normal file
21
test/issues/1380/README
Normal file
@ -0,0 +1,21 @@
|
||||
【Issue#1324 動作確認】
|
||||
□ テスト内容
|
||||
1. 以下のLTPを用いてIssueで報告された症状が発生しないことを確認
|
||||
- tgkill03
|
||||
|
||||
3. 以下のLTPを用いて既存機能に影響が無いことを確認
|
||||
- tgkill01
|
||||
- tkill01
|
||||
- tkill02
|
||||
|
||||
□ 実行手順
|
||||
$ make test
|
||||
|
||||
McKernelのインストール先や、OSTEST, LTPの配置場所は、
|
||||
$HOME/.mck_test_config を参照している
|
||||
.mck_test_config は、McKernelをビルドした際に生成されるmck_test_config.sample ファイルを
|
||||
$HOMEにコピーし、適宜編集する
|
||||
|
||||
□ 実行結果
|
||||
x86_64_result.log aarch64_result.log 参照。
|
||||
すべての項目をPASSしていることを確認。
|
||||
37
test/issues/1380/aarch64_result.log
Normal file
37
test/issues/1380/aarch64_result.log
Normal file
@ -0,0 +1,37 @@
|
||||
*** C1380T01 start *******************************
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
tgkill03.c:92: PASS: Invalid tgid failed as expected: EINVAL
|
||||
tgkill03.c:92: PASS: Invalid tid failed as expected: EINVAL
|
||||
tgkill03.c:92: PASS: Invalid signal failed as expected: EINVAL
|
||||
tgkill03.c:92: PASS: Defunct tid failed as expected: ESRCH
|
||||
tgkill03.c:92: PASS: Defunct tgid failed as expected: ESRCH
|
||||
tgkill03.c:99: PASS: Valid tgkill call succeeded
|
||||
|
||||
Summary:
|
||||
passed 6
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1380T01 PASSED (6)
|
||||
|
||||
*** C1380T02 start *******************************
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
tgkill01.c:99: PASS: SIGUSR1 delivered to correct threads
|
||||
|
||||
Summary:
|
||||
passed 1
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1380T02 PASSED (1)
|
||||
|
||||
*** C1380T03 start *******************************
|
||||
tkill01 1 TPASS : tkill call succeeded
|
||||
tkill01 2 TPASS : tkill call succeeded
|
||||
*** C1380T03 PASSED (2)
|
||||
|
||||
*** C1380T04 start *******************************
|
||||
tkill02 1 TPASS : tkill(-1, SIGUSR1) failed as expected: TEST_ERRNO=EINVAL(22): Invalid argument
|
||||
tkill02 2 TPASS : tkill(29822, SIGUSR1) failed as expected: TEST_ERRNO=ESRCH(3): No such process
|
||||
*** C1380T04 PASSED (2)
|
||||
|
||||
37
test/issues/1380/x86_64_result.log
Normal file
37
test/issues/1380/x86_64_result.log
Normal file
@ -0,0 +1,37 @@
|
||||
*** C1380T01 start *******************************
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
tgkill03.c:92: PASS: Invalid tgid failed as expected: EINVAL
|
||||
tgkill03.c:92: PASS: Invalid tid failed as expected: EINVAL
|
||||
tgkill03.c:92: PASS: Invalid signal failed as expected: EINVAL
|
||||
tgkill03.c:92: PASS: Defunct tid failed as expected: ESRCH
|
||||
tgkill03.c:92: PASS: Defunct tgid failed as expected: ESRCH
|
||||
tgkill03.c:99: PASS: Valid tgkill call succeeded
|
||||
|
||||
Summary:
|
||||
passed 6
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1380T01 PASSED (6)
|
||||
|
||||
*** C1380T02 start *******************************
|
||||
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
|
||||
tgkill01.c:99: PASS: SIGUSR1 delivered to correct threads
|
||||
|
||||
Summary:
|
||||
passed 1
|
||||
failed 0
|
||||
skipped 0
|
||||
warnings 0
|
||||
*** C1380T02 PASSED (1)
|
||||
|
||||
*** C1380T03 start *******************************
|
||||
tkill01 1 TPASS : tkill call succeeded
|
||||
tkill01 2 TPASS : tkill call succeeded
|
||||
*** C1380T03 PASSED (2)
|
||||
|
||||
*** C1380T04 start *******************************
|
||||
tkill02 1 TPASS : tkill(-1, SIGUSR1) failed as expected: TEST_ERRNO=EINVAL(22): Invalid argument
|
||||
tkill02 2 TPASS : tkill(32768, SIGUSR1) failed as expected: TEST_ERRNO=ESRCH(3): No such process
|
||||
*** C1380T04 PASSED (2)
|
||||
|
||||
41
test/issues/1399/C1399.sh
Executable file
41
test/issues/1399/C1399.sh
Executable file
@ -0,0 +1,41 @@
|
||||
#/bin/sh
|
||||
|
||||
USELTP=1
|
||||
USEOSTEST=0
|
||||
|
||||
. ../../common.sh
|
||||
|
||||
issue="1399"
|
||||
tid=01
|
||||
|
||||
for tno in 01
|
||||
do
|
||||
tname=`printf "C${issue}T%02d" ${tid}`
|
||||
echo "*** ${tname} start *******************************"
|
||||
sudo ${MCEXEC} ./C1399T${tno}
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "*** ${tname} PASSED ******************************"
|
||||
else
|
||||
echo "*** ${tname} FAILED ******************************"
|
||||
fi
|
||||
let tid++
|
||||
echo ""
|
||||
done
|
||||
|
||||
for tp in set_robust_list01 get_robust_list01
|
||||
do
|
||||
tname=`printf "C${issue}T%02d" ${tid}`
|
||||
echo "*** ${tname} start *******************************"
|
||||
sudo $MCEXEC $LTPBIN/$tp 2>&1 | tee $tp.txt
|
||||
ok=`grep PASS $tp.txt | wc -l`
|
||||
ng=`grep FAIL $tp.txt | wc -l`
|
||||
if [ $ng = 0 ]; then
|
||||
echo "*** ${tname} PASSED ($ok)"
|
||||
else
|
||||
echo "*** ${tname} FAILED (ok=$ok ng=$ng)"
|
||||
fi
|
||||
let tid++
|
||||
echo ""
|
||||
done
|
||||
|
||||
36
test/issues/1399/C1399T01.c
Normal file
36
test/issues/1399/C1399T01.c
Normal file
@ -0,0 +1,36 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/futex.h>
|
||||
#include <syscall.h>
|
||||
#include <errno.h>
|
||||
|
||||
int main(int argc, void *argv[])
|
||||
{
|
||||
struct robust_list_head rlh;
|
||||
size_t len = sizeof(struct robust_list_head);
|
||||
int rc = 0, ret = 0;
|
||||
|
||||
errno = 0;
|
||||
rc = syscall(__NR_set_robust_list, &rlh, len + 1);
|
||||
if (rc == -1 && errno == EINVAL) {
|
||||
printf("[OK] invalid len (1 greater than correct): EINVAL\n");
|
||||
} else {
|
||||
printf("[NG] invalid len (1 greater than correct): Succeed\n");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
rc = syscall(__NR_set_robust_list, &rlh, len - 1);
|
||||
if (rc == -1 && errno == EINVAL) {
|
||||
printf("[OK] invalid len (1 less than correct): EINVAL\n");
|
||||
} else {
|
||||
printf("[NG] invalid len (1 less than correct): Succeed\n");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
11
test/issues/1399/Makefile
Normal file
11
test/issues/1399/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
CFLAGS=-g
|
||||
LDFLAGS=
|
||||
|
||||
TARGET=C1399T01
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
test: all
|
||||
./C1399.sh
|
||||
clean:
|
||||
rm -f $(TARGET) *.o *.txt
|
||||
24
test/issues/1399/README
Normal file
24
test/issues/1399/README
Normal file
@ -0,0 +1,24 @@
|
||||
【Issue#1399 動作確認】
|
||||
□ テスト内容
|
||||
1. 下記のテストプログラムを実行し、症状が発生しないことを確認する
|
||||
C1399T01:
|
||||
1. struct robust_list_head のサイズよりも1大きい値をサイズとして指定して
|
||||
set_robsut_list を呼び出し、EINVALで失敗することを確認
|
||||
2. struct robust_list_head のサイズよりも1小さい値をサイズとして指定して
|
||||
set_robsut_list を呼び出し、EINVALで失敗することを確認
|
||||
|
||||
2. 以下のLTPを用いて既存のrobust_list機能に影響が無いことを確認
|
||||
- set_robst_list01
|
||||
- get_robst_list01
|
||||
|
||||
□ 実行手順
|
||||
$ make test
|
||||
|
||||
McKernelのインストール先や、OSTEST, LTPの配置場所は、
|
||||
$HOME/.mck_test_config を参照している
|
||||
.mck_test_config は、McKernelをビルドした際に生成されるmck_test_config.sample ファイルを
|
||||
$HOMEにコピーし、適宜編集する
|
||||
|
||||
□ 実行結果
|
||||
x86_64_result.log aarch64_result.log 参照。
|
||||
すべての項目をPASSしていることを確認。
|
||||
18
test/issues/1399/aarch64_result.log
Normal file
18
test/issues/1399/aarch64_result.log
Normal file
@ -0,0 +1,18 @@
|
||||
*** C1399T01 start *******************************
|
||||
[OK] invalid len (1 greater than correct): EINVAL
|
||||
[OK] invalid len (1 less than correct): EINVAL
|
||||
*** C1399T01 PASSED ******************************
|
||||
|
||||
*** C1399T02 start *******************************
|
||||
set_robust_list01 1 TPASS : set_robust_list: retval = -1 (expected -1), errno = 22 (expected 22)
|
||||
set_robust_list01 2 TPASS : set_robust_list: retval = 0 (expected 0), errno = 0 (expected 0)
|
||||
*** C1399T02 PASSED (2)
|
||||
|
||||
*** C1399T03 start *******************************
|
||||
get_robust_list01 1 TPASS : get_robust_list failed as expected with EFAULT
|
||||
get_robust_list01 2 TPASS : get_robust_list failed as expected with EFAULT
|
||||
get_robust_list01 3 TPASS : get_robust_list failed as expected with ESRCH
|
||||
get_robust_list01 4 TPASS : get_robust_list succeeded
|
||||
get_robust_list01 5 TPASS : get_robust_list failed as expected with EPERM
|
||||
*** C1399T03 PASSED (5)
|
||||
|
||||
18
test/issues/1399/x86_64_result.log
Normal file
18
test/issues/1399/x86_64_result.log
Normal file
@ -0,0 +1,18 @@
|
||||
*** C1399T01 start *******************************
|
||||
[OK] invalid len (1 greater than correct): EINVAL
|
||||
[OK] invalid len (1 less than correct): EINVAL
|
||||
*** C1399T01 PASSED ******************************
|
||||
|
||||
*** C1399T02 start *******************************
|
||||
set_robust_list01 1 TPASS : set_robust_list: retval = -1 (expected -1), errno = 22 (expected 22)
|
||||
set_robust_list01 2 TPASS : set_robust_list: retval = 0 (expected 0), errno = 0 (expected 0)
|
||||
*** C1399T02 PASSED (2)
|
||||
|
||||
*** C1399T03 start *******************************
|
||||
get_robust_list01 1 TPASS : get_robust_list failed as expected with EFAULT
|
||||
get_robust_list01 2 TPASS : get_robust_list failed as expected with EFAULT
|
||||
get_robust_list01 3 TPASS : get_robust_list failed as expected with ESRCH
|
||||
get_robust_list01 4 TPASS : get_robust_list succeeded
|
||||
get_robust_list01 5 TPASS : get_robust_list failed as expected with EPERM
|
||||
*** C1399T03 PASSED (5)
|
||||
|
||||
43
test/issues/1425/C1425.sh
Executable file
43
test/issues/1425/C1425.sh
Executable file
@ -0,0 +1,43 @@
|
||||
#/bin/sh
|
||||
|
||||
USELTP=1
|
||||
USEOSTEST=0
|
||||
|
||||
. ../../common.sh
|
||||
|
||||
issue="1425"
|
||||
tid=01
|
||||
|
||||
STOPSIG_LIST="TSTP TTIN TTOU"
|
||||
|
||||
for signame in ${STOPSIG_LIST}
|
||||
do
|
||||
tname=`printf "C${issue}T%02d" ${tid}`
|
||||
echo "*** ${tname} start *******************************"
|
||||
sh ./check_stopsig.sh ${MCEXEC} ${signame}
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "*** ${tname} PASSED ******************************"
|
||||
else
|
||||
echo "*** ${tname} FAILED ******************************"
|
||||
fi
|
||||
let tid++
|
||||
echo ""
|
||||
done
|
||||
|
||||
for tp in kill01 kill02 kill06 kill07 kill08 kill09 signal01 signal03 signal04 signal05
|
||||
do
|
||||
tname=`printf "C${issue}T%02d" ${tid}`
|
||||
echo "*** ${tname} start *******************************"
|
||||
sudo $MCEXEC $LTPBIN/$tp 2>&1 | tee $tp.txt
|
||||
ok=`grep PASS $tp.txt | wc -l`
|
||||
ng=`grep FAIL $tp.txt | wc -l`
|
||||
if [ $ng = 0 ]; then
|
||||
echo "*** ${tname} PASSED ($ok)"
|
||||
else
|
||||
echo "*** ${tname} FAILED (ok=$ok ng=$ng)"
|
||||
fi
|
||||
let tid++
|
||||
echo ""
|
||||
done
|
||||
|
||||
11
test/issues/1425/Makefile
Normal file
11
test/issues/1425/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
CFLAGS=-g
|
||||
LDFLAGS=
|
||||
|
||||
TARGET=
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
test: all
|
||||
sh ./C1425.sh
|
||||
clean:
|
||||
rm -f $(TARGET) *.o *.txt
|
||||
37
test/issues/1425/README
Normal file
37
test/issues/1425/README
Normal file
@ -0,0 +1,37 @@
|
||||
【Issue#1425 動作確認】
|
||||
□ テスト内容
|
||||
1. 本修正ではmcexecにてSIGTSTP, SIGTTIN, SIGTTOU を補足しないようにする
|
||||
修正を実施した。
|
||||
上記のシグナルのデフォルト動作はプロセスの停止である。
|
||||
それぞれのシグナルについて、以下を確認する。
|
||||
- 実行中のMcKernelプロセスに通知した際、通知先のプロセスが停止する
|
||||
- 停止されたプロセスに対してSIGCONTを通知することで、プロセスが再開できる
|
||||
|
||||
C1425T01: SIGTSTP の動作を確認
|
||||
C1425T02: SIGTTIN の動作を確認
|
||||
C1425T03: SIGTTOU の動作を確認
|
||||
|
||||
2. 以下のLTPを用いて既存のsignal機能に影響が無いことを確認
|
||||
- kill01
|
||||
- kill02
|
||||
- kill06
|
||||
- kill07
|
||||
- kill08
|
||||
- kill09
|
||||
- signal01
|
||||
- signal03
|
||||
- signal04
|
||||
- signal05
|
||||
|
||||
□ 実行手順
|
||||
・下記の手順でテストを実行する
|
||||
$ make test
|
||||
|
||||
McKernelのインストール先や、OSTEST, LTPの配置場所は、
|
||||
$HOME/.mck_test_config を参照している
|
||||
.mck_test_config は、McKernelをビルドした際に生成されるmck_test_config.sample ファイルを
|
||||
$HOMEにコピーし、適宜編集する
|
||||
|
||||
□ 実行結果
|
||||
x86_64_result.log, aarch64_result.log 参照。
|
||||
すべての項目をPASSしていることを確認。
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user