Compare commits

...

12 Commits

Author SHA1 Message Date
56b51d4f97 spec: prerelase 0.6 for testing cpuinfo and mmap overcommit
Change-Id: Iab5acc2c08ebe19251c37782cff87a4b5c914448
2020-07-13 10:14:23 +09:00
bafe540d86 mmap: allow unlimited overcommit
Change-Id: Iba07b5c504b4a202cd163ce682f3fc72a31284a0
2020-07-10 14:52:57 +09:00
d78a0fd05d sysinfo: support basic entries
Change-Id: I27f3e55058cc29f895831a1dddfafbc8585746a5
refs: #1389
2020-07-10 14:51:25 +09:00
999bc91b4f arch: Move some functions from arch-dependent to common part
Moved syscall rt_sigaction and functions related to signal.

Change-Id: I39f619e008d9c6018d91099a76dfb30e48757673
Refs: 1487
2020-07-10 03:54:28 +00:00
b3bd2ea9b3 procfs cpuinfo: use sequence number as processor
Change-Id: Id54ea74c5fda198a0bb9c9b6a19e6799fee0ed3f
2020-07-09 13:10:08 +09:00
d3d9e2400d test: ihklib: syscall_list.h: add robust marker for patch
Change-Id: Ie5f72b4b296db4d44e9839f38fd9a68854be78c3
2020-07-06 16:25:11 +09:00
199407b2a1 spec: prerelease 0.5 for testing ppoll
Change-Id: I51deb1c1703a986ba0aa4e02da9f53009554dbb7
2020-07-01 08:49:08 +09:00
5973d66e2d Revert "epoll_wait(): make sure to schedule in offload"
This reverts commit 5e44c9c9f9.

Change-Id: I826336f1ece31a84072c3e62c6c6c68a641e8fb5
2020-06-30 17:11:26 +09:00
d7ef74659b Revert "epoll, ppoll: deschedule on offload, don't do it when exiting system call"
This reverts commit d4056acfc3.

Change-Id: I7df15b9d3957ca571f4b4e2d576799f8b97ae299
2020-06-30 17:11:23 +09:00
ac86affecc mcexec: fix FLIB_AFFINITY_ON_PROCESS mask for McKernel CPU numbers (Fugaku)
Change-Id: If42b139fb53866bcff0809d898d4a2a712946f0c
2020-06-30 16:29:03 +09:00
2026cf8dad mcexec: explicit CPU list in partitoned execution (for Fujitsu's FLIB_AFFINITY_ON_PROCESS)
Change-Id: I05c11f73553de8ccb5f79083ce2115ac57e62584
2020-06-30 16:29:00 +09:00
1d135492c3 mcexec: detect mismatch of mcexec -n and mpirun -ppn
Change-Id: I0c42e3119143da40ea2e69cd9ec99bde78a0ad2a
Refs: #929
2020-06-30 16:28:08 +09:00
37 changed files with 1544 additions and 619 deletions

View File

@ -10,7 +10,7 @@ project(mckernel C ASM)
set(MCKERNEL_VERSION "1.7.0") set(MCKERNEL_VERSION "1.7.0")
# See "Fedora Packaging Guidlines -- Versioning" # See "Fedora Packaging Guidlines -- Versioning"
set(MCKERNEL_RELEASE "0.4") set(MCKERNEL_RELEASE "0.6")
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules) set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules)
# for rpmbuild # for rpmbuild

View File

@ -535,3 +535,6 @@ Restrictions on McKernel
25. The behaviors of madvise and mbind are changed to do nothing and 25. The behaviors of madvise and mbind are changed to do nothing and
report success as a workaround for Fugaku. report success as a workaround for Fugaku.
26. mmap() allows unlimited overcommit. Note that it corresponds to
setting sysctl ``vm.overcommit_memory`` to 1.

View File

@ -1279,7 +1279,7 @@ long ihk_mc_show_cpuinfo(char *buf, size_t buf_size, unsigned long read_off, int
/* generate strings */ /* generate strings */
loff += scnprintf(lbuf + loff, lbuf_size - loff, loff += scnprintf(lbuf + loff, lbuf_size - loff,
"processor\t: %d\n", cpuinfo->hwid); "processor\t: %d\n", i);
loff += scnprintf(lbuf + loff, lbuf_size - loff, "Features\t:"); loff += scnprintf(lbuf + loff, lbuf_size - loff, "Features\t:");
for (j = 0; hwcap_str[j]; j++) { for (j = 0; hwcap_str[j]; j++) {

View File

@ -83,6 +83,7 @@ SYSCALL_HANDLED(175, geteuid)
SYSCALL_HANDLED(176, getgid) SYSCALL_HANDLED(176, getgid)
SYSCALL_HANDLED(177, getegid) SYSCALL_HANDLED(177, getegid)
SYSCALL_HANDLED(178, gettid) SYSCALL_HANDLED(178, gettid)
SYSCALL_HANDLED(179, sysinfo)
SYSCALL_DELEGATED(188, msgrcv) SYSCALL_DELEGATED(188, msgrcv)
SYSCALL_DELEGATED(189, msgsnd) SYSCALL_DELEGATED(189, msgsnd)
SYSCALL_DELEGATED(192, semtimedop) SYSCALL_DELEGATED(192, semtimedop)
@ -143,3 +144,8 @@ SYSCALL_DELEGATED(1049, stat)
SYSCALL_DELEGATED(1060, getpgrp) SYSCALL_DELEGATED(1060, getpgrp)
SYSCALL_HANDLED(1062, time) SYSCALL_HANDLED(1062, time)
SYSCALL_DELEGATED(1069, epoll_wait) 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.
*/

View File

@ -142,17 +142,6 @@ int obtain_clone_cpuid(cpu_set_t *cpu_set, int use_last)
return min_cpu; 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 */ /* archtecture-depended syscall handlers */
extern unsigned long do_fork(int clone_flags, unsigned long newsp, extern unsigned long do_fork(int clone_flags, unsigned long newsp,
unsigned long parent_tidptr, unsigned long child_tidptr, unsigned long parent_tidptr, unsigned long child_tidptr,
@ -185,33 +174,6 @@ SYSCALL_DECLARE(clone)
return ret; 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) SYSCALL_DECLARE(prctl)
{ {
struct process *proc = cpu_local_var(current)->proc; struct process *proc = cpu_local_var(current)->proc;
@ -1368,70 +1330,6 @@ out:
return restart; 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 int
interrupt_from_user(void *regs0) interrupt_from_user(void *regs0)
{ {
@ -1455,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 unsigned long
do_kill(struct thread * thread, int pid, int tid, int sig, siginfo_t *info, int ptracecont) do_kill(struct thread * thread, int pid, int tid, int sig, siginfo_t *info, int ptracecont)
{ {

View File

@ -74,6 +74,7 @@ SYSCALL_DELEGATED(89, readlink)
SYSCALL_HANDLED(96, gettimeofday) SYSCALL_HANDLED(96, gettimeofday)
SYSCALL_HANDLED(97, getrlimit) SYSCALL_HANDLED(97, getrlimit)
SYSCALL_HANDLED(98, getrusage) SYSCALL_HANDLED(98, getrusage)
SYSCALL_HANDLED(99, sysinfo)
SYSCALL_HANDLED(100, times) SYSCALL_HANDLED(100, times)
SYSCALL_HANDLED(101, ptrace) SYSCALL_HANDLED(101, ptrace)
SYSCALL_HANDLED(102, getuid) SYSCALL_HANDLED(102, getuid)
@ -179,4 +180,8 @@ SYSCALL_HANDLED(802, linux_mlock)
SYSCALL_HANDLED(803, suspend_threads) SYSCALL_HANDLED(803, suspend_threads)
SYSCALL_HANDLED(804, resume_threads) SYSCALL_HANDLED(804, resume_threads)
SYSCALL_HANDLED(811, linux_spawn) 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.
*/

View File

@ -147,44 +147,6 @@ int obtain_clone_cpuid(cpu_set_t *cpu_set, int use_last) {
return min_cpu; 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) SYSCALL_DECLARE(prctl)
{ {
struct process *proc = cpu_local_var(current)->proc; struct process *proc = cpu_local_var(current)->proc;
@ -1039,82 +1001,6 @@ out:
return restart; 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 int
interrupt_from_user(void *regs0) interrupt_from_user(void *regs0)
{ {
@ -1129,175 +1015,6 @@ void save_syscall_return_value(int num, unsigned long rc)
return; 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 unsigned long
do_kill(struct thread *thread, int pid, int tid, int sig, siginfo_t *info, do_kill(struct thread *thread, int pid, int tid, int sig, siginfo_t *info,
int ptracecont) int ptracecont)

View File

@ -91,7 +91,10 @@ struct program_image_section {
struct get_cpu_set_arg { struct get_cpu_set_arg {
int nr_processes; int nr_processes;
char *req_cpu_list; // Requested by user-space
int req_cpu_list_len; // Lenght of request string
int *process_rank; int *process_rank;
pid_t ppid;
void *cpu_set; void *cpu_set;
size_t cpu_set_size; // Size in bytes size_t cpu_set_size; // Size in bytes
int *target_core; int *target_core;

View File

@ -587,13 +587,14 @@ extern int mckernel_cpu_2_linux_cpu(struct mcctrl_usrdata *udp, int cpu_id);
static long mcexec_get_cpuset(ihk_os_t os, unsigned long arg) static long mcexec_get_cpuset(ihk_os_t os, unsigned long arg)
{ {
struct mcctrl_usrdata *udp = ihk_host_os_get_usrdata(os); struct mcctrl_usrdata *udp = ihk_host_os_get_usrdata(os);
struct mcctrl_part_exec *pe; struct mcctrl_part_exec *pe = NULL, *pe_itr;
struct get_cpu_set_arg req; struct get_cpu_set_arg req;
struct mcctrl_cpu_topology *cpu_top, *cpu_top_i; struct mcctrl_cpu_topology *cpu_top, *cpu_top_i;
struct cache_topology *cache_top; struct cache_topology *cache_top;
int cpu, cpus_assigned, cpus_to_assign, cpu_prev; int cpu, cpus_assigned, cpus_to_assign, cpu_prev;
int ret = 0; int ret = 0;
int mcexec_linux_numa; int mcexec_linux_numa;
int pe_list_len = 0;
cpumask_t *mcexec_cpu_set = NULL; cpumask_t *mcexec_cpu_set = NULL;
cpumask_t *cpus_used = NULL; cpumask_t *cpus_used = NULL;
cpumask_t *cpus_to_use = NULL; cpumask_t *cpus_to_use = NULL;
@ -613,24 +614,126 @@ static long mcexec_get_cpuset(ihk_os_t os, unsigned long arg)
return -EINVAL; return -EINVAL;
} }
pe = &udp->part_exec;
mutex_lock(&pe->lock);
if (copy_from_user(&req, (void *)arg, sizeof(req))) { if (copy_from_user(&req, (void *)arg, sizeof(req))) {
printk("%s: error copying user request\n", __FUNCTION__); pr_err("%s: error copying user request\n", __func__);
ret = -EINVAL; ret = -EINVAL;
goto put_and_unlock_out; goto put_out;
} }
/* First process to enter CPU partitioning */ /* User requested CPU mask? */
if (pe->nr_processes == -1) { 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) {
pe_list_len++;
if (pe_itr->node_proxy_pid == req.ppid) {
pe = pe_itr;
break;
}
}
if (!pe) {
/* First process to enter CPU partitioning */
pr_debug("%s: pe_list_len:%d\n", __func__, pe_list_len);
if (pe_list_len >= PE_LIST_MAXLEN) {
/* delete head entry of pe_list */
pe_itr = list_first_entry(&udp->part_exec_list,
struct mcctrl_part_exec, chain);
list_del(&pe_itr->chain);
kfree(pe_itr);
}
pe = kzalloc(sizeof(struct mcctrl_part_exec), GFP_KERNEL);
if (!pe) {
mutex_unlock(&udp->part_exec_lock);
ret = -ENOMEM;
goto put_out;
}
/* Init part_exec */
mutex_init(&pe->lock);
INIT_LIST_HEAD(&pe->pli_list);
pe->nr_processes = req.nr_processes; pe->nr_processes = req.nr_processes;
pe->nr_processes_left = req.nr_processes; pe->nr_processes_left = req.nr_processes;
pe->nr_processes_joined = 0;
pe->node_proxy_pid = req.ppid;
list_add_tail(&pe->chain, &udp->part_exec_list);
dprintk("%s: nr_processes: %d (partitioned exec starts)\n", dprintk("%s: nr_processes: %d (partitioned exec starts)\n",
__FUNCTION__, __func__, pe->nr_processes);
pe->nr_processes);
} }
mutex_unlock(&udp->part_exec_lock);
mutex_lock(&pe->lock);
if (pe->nr_processes != req.nr_processes) { if (pe->nr_processes != req.nr_processes) {
printk("%s: error: requested number of processes" printk("%s: error: requested number of processes"
@ -640,7 +743,15 @@ static long mcexec_get_cpuset(ihk_os_t os, unsigned long arg)
goto put_and_unlock_out; goto put_and_unlock_out;
} }
if (pe->nr_processes_joined >= pe->nr_processes) {
printk("%s: too many processes have joined to the group of %d\n",
__func__, req.ppid);
ret = -EINVAL;
goto put_and_unlock_out;
}
--pe->nr_processes_left; --pe->nr_processes_left;
++pe->nr_processes_joined;
dprintk("%s: nr_processes: %d, nr_processes_left: %d\n", dprintk("%s: nr_processes: %d, nr_processes_left: %d\n",
__FUNCTION__, __FUNCTION__,
pe->nr_processes, pe->nr_processes,
@ -726,8 +837,6 @@ static long mcexec_get_cpuset(ihk_os_t os, unsigned long arg)
wake_up_interruptible(&pli_next->pli_wq); wake_up_interruptible(&pli_next->pli_wq);
} }
/* Reset process counter to start state */
pe->nr_processes = -1;
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
goto put_and_unlock_out; goto put_and_unlock_out;
} }
@ -975,16 +1084,8 @@ next_cpu:
/* Commit used cores to OS structure */ /* Commit used cores to OS structure */
memcpy(&pe->cpus_used, cpus_used, sizeof(*cpus_used)); memcpy(&pe->cpus_used, cpus_used, sizeof(*cpus_used));
/* Reset if last process */ /* If not last process, wake up next process in list */
if (pe->nr_processes_left == 0) { if (pe->nr_processes_left != 0) {
dprintk("%s: nr_processes: %d (partitioned exec ends)\n",
__FUNCTION__,
pe->nr_processes);
pe->nr_processes = -1;
memset(&pe->cpus_used, 0, sizeof(pe->cpus_used));
}
/* Otherwise wake up next process in list */
else {
++pe->process_rank; ++pe->process_rank;
pli_next = list_first_entry(&pe->pli_list, pli_next = list_first_entry(&pe->pli_list,
struct process_list_item, list); struct process_list_item, list);
@ -997,11 +1098,14 @@ next_cpu:
ret = 0; ret = 0;
put_and_unlock_out: put_and_unlock_out:
mutex_unlock(&pe->lock);
put_out:
mcctrl_put_per_proc_data(ppd);
kfree(cpus_to_use); kfree(cpus_to_use);
kfree(cpus_used); kfree(cpus_used);
kfree(mcexec_cpu_set); kfree(mcexec_cpu_set);
mcctrl_put_per_proc_data(ppd);
mutex_unlock(&pe->lock);
return ret; return ret;
} }

View File

@ -513,6 +513,7 @@ int prepare_ikc_channels(ihk_os_t os)
init_waitqueue_head(&usrdata->wq_procfs); init_waitqueue_head(&usrdata->wq_procfs);
mutex_init(&usrdata->reserve_lock); mutex_init(&usrdata->reserve_lock);
mutex_init(&usrdata->part_exec_lock);
for (i = 0; i < MCCTRL_PER_PROC_DATA_HASH_SIZE; ++i) { for (i = 0; i < MCCTRL_PER_PROC_DATA_HASH_SIZE; ++i) {
INIT_LIST_HEAD(&usrdata->per_proc_data_hash[i]); INIT_LIST_HEAD(&usrdata->per_proc_data_hash[i]);
@ -521,10 +522,8 @@ int prepare_ikc_channels(ihk_os_t os)
INIT_LIST_HEAD(&usrdata->cpu_topology_list); INIT_LIST_HEAD(&usrdata->cpu_topology_list);
INIT_LIST_HEAD(&usrdata->node_topology_list); INIT_LIST_HEAD(&usrdata->node_topology_list);
INIT_LIST_HEAD(&usrdata->part_exec_list);
mutex_init(&usrdata->part_exec.lock);
INIT_LIST_HEAD(&usrdata->part_exec.pli_list);
usrdata->part_exec.nr_processes = -1;
INIT_LIST_HEAD(&usrdata->wakeup_descs_list); INIT_LIST_HEAD(&usrdata->wakeup_descs_list);
spin_lock_init(&usrdata->wakeup_descs_lock); spin_lock_init(&usrdata->wakeup_descs_lock);
@ -580,6 +579,18 @@ void destroy_ikc_channels(ihk_os_t os)
kfree(usrdata->channels); kfree(usrdata->channels);
kfree(usrdata->ikc2linux); kfree(usrdata->ikc2linux);
mutex_lock(&usrdata->part_exec_lock);
while (!list_empty(&usrdata->part_exec_list)) {
struct mcctrl_part_exec *pe;
pe = list_first_entry(&usrdata->part_exec_list,
struct mcctrl_part_exec, chain);
list_del(&pe->chain);
kfree(pe);
}
mutex_unlock(&usrdata->part_exec_lock);
kfree(usrdata); kfree(usrdata);
} }

View File

@ -324,13 +324,20 @@ struct process_list_item {
wait_queue_head_t pli_wq; wait_queue_head_t pli_wq;
}; };
#define PE_LIST_MAXLEN 5
struct mcctrl_part_exec { struct mcctrl_part_exec {
struct mutex lock; struct mutex lock;
int nr_processes; int nr_processes;
/* number of processes to let in / out the synchronization point */
int nr_processes_left; int nr_processes_left;
/* number of processes which have joined the partition */
int nr_processes_joined;
int process_rank; int process_rank;
pid_t node_proxy_pid;
cpumask_t cpus_used; cpumask_t cpus_used;
struct list_head pli_list; struct list_head pli_list;
struct list_head chain;
}; };
#define CPU_LONGS (((NR_CPUS) + (BITS_PER_LONG) - 1) / (BITS_PER_LONG)) #define CPU_LONGS (((NR_CPUS) + (BITS_PER_LONG) - 1) / (BITS_PER_LONG))
@ -353,6 +360,7 @@ struct mcctrl_usrdata {
int job_pos; int job_pos;
int mcctrl_dma_abort; int mcctrl_dma_abort;
struct mutex reserve_lock; struct mutex reserve_lock;
struct mutex part_exec_lock;
unsigned long last_thread_exec; unsigned long last_thread_exec;
wait_queue_head_t wq_procfs; wait_queue_head_t wq_procfs;
struct list_head per_proc_data_hash[MCCTRL_PER_PROC_DATA_HASH_SIZE]; struct list_head per_proc_data_hash[MCCTRL_PER_PROC_DATA_HASH_SIZE];
@ -368,7 +376,7 @@ struct mcctrl_usrdata {
nodemask_t numa_online; nodemask_t numa_online;
struct list_head cpu_topology_list; struct list_head cpu_topology_list;
struct list_head node_topology_list; struct list_head node_topology_list;
struct mcctrl_part_exec part_exec; struct list_head part_exec_list;
int perf_event_num; int perf_event_num;
}; };

View File

@ -2211,6 +2211,64 @@ int main(int argc, char **argv)
pthread_spin_init(&overlay_fd_lock, 0); 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(); ld_preload_init();
#ifdef ADD_ENVS_OPTION #ifdef ADD_ENVS_OPTION
@ -2483,9 +2541,12 @@ int main(int argc, char **argv)
CPU_ZERO(&mcexec_cpu_set); 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 = (void *)&desc->cpu_set;
cpu_set_arg.cpu_set_size = sizeof(desc->cpu_set); cpu_set_arg.cpu_set_size = sizeof(desc->cpu_set);
cpu_set_arg.nr_processes = nr_processes; cpu_set_arg.nr_processes = nr_processes;
cpu_set_arg.ppid = getppid();
cpu_set_arg.target_core = &target_core; cpu_set_arg.target_core = &target_core;
cpu_set_arg.process_rank = &process_rank; cpu_set_arg.process_rank = &process_rank;
cpu_set_arg.mcexec_linux_numa = &mcexec_linux_numa; cpu_set_arg.mcexec_linux_numa = &mcexec_linux_numa;
@ -2493,6 +2554,16 @@ int main(int argc, char **argv)
cpu_set_arg.mcexec_cpu_set_size = sizeof(mcexec_cpu_set); cpu_set_arg.mcexec_cpu_set_size = sizeof(mcexec_cpu_set);
cpu_set_arg.ikc_mapped = &ikc_mapped; 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) { if (ioctl(fd, MCEXEC_UP_GET_CPUSET, (void *)&cpu_set_arg) != 0) {
perror("getting CPU set for partitioned execution"); perror("getting CPU set for partitioned execution");
close(fd); close(fd);
@ -2501,6 +2572,12 @@ int main(int argc, char **argv)
desc->cpu = target_core; desc->cpu = target_core;
desc->process_rank = process_rank; 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 */ /* Bind to CPU cores where the LWK process' IKC target maps to */
if (ikc_mapped && !no_bind_ikc_map) { if (ikc_mapped && !no_bind_ikc_map) {

2
ihk

Submodule ihk updated: 1a6150c5bb...7c4b8d6b40

View File

@ -72,4 +72,11 @@
#define MS_INVALIDATE 0x02 #define MS_INVALIDATE 0x02
#define MS_SYNC 0x04 #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 */ #endif /* HEADER_MMAN_H */

View File

@ -11,6 +11,7 @@
#include <ihk/ihk_monitor.h> #include <ihk/ihk_monitor.h>
#include <ihk/debug.h> #include <ihk/debug.h>
#include <memory.h> #include <memory.h>
#include <mman.h>
#ifdef ENABLE_RUSAGE #ifdef ENABLE_RUSAGE
@ -56,6 +57,24 @@ rusage_total_memory_add(unsigned long size)
#endif #endif
} }
static inline unsigned long
rusage_get_total_memory()
{
return rusage.total_memory;
}
static inline unsigned long
rusage_get_free_memory()
{
return rusage.total_memory - rusage.total_memory_usage;
}
static inline unsigned long
rusage_get_usage_memory()
{
return rusage.total_memory_usage;
}
static inline void static inline void
rusage_rss_add(unsigned long size) rusage_rss_add(unsigned long size)
{ {
@ -293,6 +312,9 @@ rusage_check_overmap(size_t len, int pgshift)
{ {
int npages = 0, remain_pages = 0; int npages = 0, remain_pages = 0;
if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS)
return 0;
npages = (len + (1UL << pgshift) - 1) >> pgshift; npages = (len + (1UL << pgshift) - 1) >> pgshift;
remain_pages = (rusage.total_memory - rusage.total_memory_usage) remain_pages = (rusage.total_memory - rusage.total_memory_usage)
>> pgshift; >> pgshift;
@ -399,6 +421,24 @@ rusage_rss_add(unsigned long size)
{ {
} }
static inline unsigned long
rusage_get_total_memory()
{
return 0;
}
static inline unsigned long
rusage_get_free_memory()
{
return 0;
}
static inline unsigned long
rusage_get_usage_memory()
{
return 0;
}
static inline void static inline void
rusage_rss_sub(unsigned long size) rusage_rss_sub(unsigned long size)
{ {

View File

@ -443,6 +443,22 @@ struct rusage {
long ru_nivcsw; long ru_nivcsw;
}; };
struct sysinfo {
long uptime; /* Seconds since boot */
unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
unsigned long totalram; /* Total usable main memory size */
unsigned long freeram; /* Available memory size */
unsigned long sharedram; /* Amount of shared memory */
unsigned long bufferram; /* Memory used by buffers */
unsigned long totalswap; /* Total swap space size */
unsigned long freeswap; /* swap space still available */
unsigned short procs; /* Number of current processes */
unsigned long totalhigh; /* Total high memory size */
unsigned long freehigh; /* Available high memory size */
unsigned int mem_unit; /* Memory unit size in bytes */
char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding for libc5 */
};
extern void terminate(int, int); extern void terminate(int, int);
struct tod_data_s { struct tod_data_s {
@ -635,4 +651,6 @@ extern int (*linux_clock_gettime)(clockid_t clk_id, struct timespec *tp);
#define COREDUMP_TO_BE_WOKEN 2 #define COREDUMP_TO_BE_WOKEN 2
extern void terminate_host(int pid, struct thread *thread); 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 #endif

View File

@ -62,6 +62,7 @@ extern int interrupt_from_user(void *);
struct tlb_flush_entry tlb_flush_vector[IHK_TLB_FLUSH_IRQ_VECTOR_SIZE]; struct tlb_flush_entry tlb_flush_vector[IHK_TLB_FLUSH_IRQ_VECTOR_SIZE];
int anon_on_demand = 0; int anon_on_demand = 0;
int sysctl_overcommit_memory = OVERCOMMIT_ALWAYS;
static struct ihk_mc_pa_ops *pa_ops; static struct ihk_mc_pa_ops *pa_ops;

View File

@ -120,7 +120,6 @@ extern int num_processors;
extern unsigned long ihk_mc_get_ns_per_tsc(void); extern unsigned long ihk_mc_get_ns_per_tsc(void);
extern int ptrace_detach(int pid, int data); extern int ptrace_detach(int pid, int data);
extern void debug_log(unsigned long); extern void debug_log(unsigned long);
extern int arch_clear_host_user_space();
extern long arch_ptrace(long request, int pid, long addr, long data); extern long arch_ptrace(long request, int pid, long addr, long data);
extern struct cpu_local_var *clv; extern struct cpu_local_var *clv;
@ -242,11 +241,6 @@ long do_syscall(struct syscall_request *req, int cpu)
unsigned long flags; unsigned long flags;
DECLARE_WAITQ_ENTRY(scd_wq_entry, cpu_local_var(current)); DECLARE_WAITQ_ENTRY(scd_wq_entry, cpu_local_var(current));
if (req->number == __NR_epoll_wait ||
req->number == __NR_epoll_pwait ||
req->number == __NR_ppoll)
goto schedule;
cpu_pause(); cpu_pause();
/* Spin if not preemptable */ /* Spin if not preemptable */
@ -275,7 +269,6 @@ long do_syscall(struct syscall_request *req, int cpu)
continue; continue;
} }
schedule:
flags = cpu_disable_interrupt_save(); flags = cpu_disable_interrupt_save();
/* Try to sleep until notified */ /* Try to sleep until notified */
@ -2660,10 +2653,8 @@ static int do_execveat(ihk_mc_user_context_t *ctx, int dirfd,
} }
/* Clear host user space PTEs */ /* Clear host user space PTEs */
if (arch_clear_host_user_space()) { clear_host_pte(vm->region.user_start,
kprintf("execve(): ERROR: clearing PTEs in host process\n"); (vm->region.user_end - vm->region.user_start), 0);
panic("");
}
/* Request host to transfer ELF image */ /* Request host to transfer ELF image */
request.number = __NR_execve; request.number = __NR_execve;
@ -5140,6 +5131,37 @@ SYSCALL_DECLARE(rt_sigsuspend)
return do_sigsuspend(thread, &wset); return do_sigsuspend(thread, &wset);
} }
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(sigaltstack) SYSCALL_DECLARE(sigaltstack)
{ {
struct thread *thread = cpu_local_var(current); struct thread *thread = cpu_local_var(current);
@ -6686,6 +6708,27 @@ SYSCALL_DECLARE(getrusage)
return 0; return 0;
} }
SYSCALL_DECLARE(sysinfo)
{
struct sysinfo *sysinfo = (struct sysinfo *)ihk_mc_syscall_arg0(ctx);
struct sysinfo __sysinfo;
int ret = 0;
memset(&__sysinfo, '\0', sizeof(struct sysinfo));
__sysinfo.totalram = rusage_get_total_memory();
__sysinfo.freeram = rusage_get_free_memory();
__sysinfo.mem_unit = 1; // always one unit for McKernel
if (copy_to_user(sysinfo, &__sysinfo, sizeof(struct sysinfo))) {
ret = -EFAULT;
goto out;
}
out:
return ret;
}
extern int ptrace_traceme(void); extern int ptrace_traceme(void);
extern void set_single_step(struct thread *thread); extern void set_single_step(struct thread *thread);
@ -10320,11 +10363,7 @@ long syscall(int num, ihk_mc_user_context_t *ctx)
} }
#endif // PROFILE_ENABLE #endif // PROFILE_ENABLE
/* Do not deschedule when returning from an event (e.g., MPI) */ if (smp_load_acquire(&v->flags) & CPU_FLAG_NEED_RESCHED) {
if (!(num == __NR_epoll_wait ||
num == __NR_epoll_pwait ||
num == __NR_ppoll) &&
smp_load_acquire(&v->flags) & CPU_FLAG_NEED_RESCHED) {
check_need_resched(); check_need_resched();
} }
@ -10345,3 +10384,275 @@ long syscall(int num, ihk_mc_user_context_t *ctx)
return l; return l;
} }
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;
}
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);
}
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);
}
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;
}
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);
}

43
test/issues/1389/C1389.sh Executable file
View File

@ -0,0 +1,43 @@
#/bin/sh
USELTP=1
USEOSTEST=0
BOOTPARAM="-c 1-7 -m 10G@0,10G@1 -O"
. ../../common.sh
issue="1389"
tid=01
for tsuf in "01" "02.sh"
do
tname=`printf "C${issue}T%02d" ${tid}`
echo "*** ${tname} start *******************************"
${MCEXEC} ./C1389T${tsuf}
if [ $? -eq 0 ]; then
echo "*** ${tname} PASSED ******************************"
else
echo "*** ${tname} FAILED ******************************"
fi
let tid++
echo ""
done
for tp in "mtest01 -p80" "mtest01 -p80 -w" "mem01"
do
tname=`printf "C${issue}T%02d" ${tid}`
echo "*** ${tname} start *******************************"
echo ${tp}
sudo $MCEXEC $LTPBIN/$tp 2>&1 | tee ${tname}.txt
ok=`grep PASS ${tname}.txt | wc -l`
ng=`grep FAIL ${tname}.txt | wc -l`
if [ $ng = 0 ]; then
echo "*** ${tname} PASSED ($ok)"
else
echo "*** ${tname} FAILED (ok=$ok ng=$ng)"
fi
let tid++
echo ""
done

View File

@ -0,0 +1,65 @@
#include <stdio.h>
#include <stdlib.h>
#include <linux/kernel.h>
#include <sys/sysinfo.h>
#include <errno.h>
int main(void)
{
struct sysinfo *info;
int ret = 0, rc = 0;
unsigned long assigned_mem = (20UL << 30);
unsigned long _totalram, _freeram;
unsigned int _mem_unit;
info = malloc(sizeof(struct sysinfo));
rc = sysinfo(info);
if (rc) {
perror("sysinfo fail: ");
ret = -1;
goto out;
}
_totalram = info->totalram;
_freeram = info->freeram;
_mem_unit = info->mem_unit;
// Check totalram
if (0.95 * assigned_mem < _totalram &&
_totalram < assigned_mem) {
printf("[OK] totalram: %ld\n", _totalram);
}
else {
printf("[NG] unexpected totalram: %ld\n", _totalram);
printf(" expected range: %ld - %ld\n",
(unsigned long)(0.95 * assigned_mem),
assigned_mem);
ret = -1;
goto out;
}
// Check freeram
if (0.95 * _totalram < _freeram &&
_freeram < _totalram) {
printf("[OK] freeram: %ld\n", _freeram);
}
else {
printf("[NG] unexpected freeram: %ld\n", _freeram);
ret = -1;
goto out;
}
// Check mem_unit
if (_mem_unit == 1) {
printf("[OK] mem_unit: %ld\n", _mem_unit);
}
else {
printf("[NG] unexpected mem_unit: %ld\n", _mem_unit);
ret = -1;
goto out;
}
free(info);
out:
return ret;
}

88
test/issues/1389/C1389T02.sh Executable file
View File

@ -0,0 +1,88 @@
#!/bin/sh
ASSIGNED_MEM=`echo '1024 * 1024 * 1024 * 20' | bc`
cat /proc/meminfo > ./cur_meminfo.txt
# Check MemTotal
MemTotalTxt=`cat ./cur_meminfo.txt | grep MemTotal | awk '{print $(NF-1)}'`
MemTotal=`echo "1024 * ${MemTotalTxt}" | bc`
lower_limit=`echo "${ASSIGNED_MEM} * 0.95" | bc`
lower_limit=${lower_limit%.*}
upper_limit=${ASSIGNED_MEM}
tgt=${MemTotal}
if [ ${tgt} -ge ${lower_limit} -a ${tgt} -lt ${upper_limit} ]; then
echo "[OK] MemTotal: ${tgt}"
else
echo "[NG] unexpected MemTotal: ${tgt}"
exit 1
fi
# Check MemFree
MemFreeTxt=`cat ./cur_meminfo.txt | grep MemFree | awk '{print $(NF-1)}'`
MemFree=`echo "1024 * ${MemFreeTxt}" | bc`
lower_limit=`echo "${MemTotal} * 0.95" | bc`
lower_limit=${lower_limit%.*}
upper_limit=${MemTotal}
tgt=${MemFree}
if [ ${tgt} -ge ${lower_limit} -a ${tgt} -lt ${upper_limit} ]; then
echo "[OK] MemFree: ${tgt}"
else
echo "[NG] unexpected MemFree: ${tgt}"
exit 1
fi
# Check SwapTotal
SwapTotalTxt=`cat ./cur_meminfo.txt | grep SwapTotal | awk '{print $(NF-1)}'`
SwapTotal=`echo "1024 * ${SwapTotalTxt}" | bc`
tgt=${SwapTotal}
if [ ${tgt} -eq 0 ]; then
echo "[OK] SwapTotal: ${tgt}"
else
echo "[NG] unexpected SwapTotal: ${tgt}"
exit 1
fi
# Check SwapFree
SwapFreeTxt=`cat ./cur_meminfo.txt | grep SwapFree | awk '{print $(NF-1)}'`
SwapFree=`echo "1024 * ${SwapFreeTxt}" | bc`
tgt=${SwapFree}
if [ ${tgt} -eq 0 ]; then
echo "[OK] SwapFree: ${tgt}"
else
echo "[NG] unexpected SwapFree: ${tgt}"
exit 1
fi
# Check CommitLimit
CommitLimitTxt=`cat ./cur_meminfo.txt | grep CommitLimit | awk '{print $(NF-1)}'`
CommitLimit=`echo "1024 * ${CommitLimitTxt}" | bc`
tgt=${CommitLimit}
if [ ${tgt} -eq ${MemFree} ]; then
echo "[OK] CommitLimit: ${tgt}"
else
echo "[NG] unexpected CommitLimit: ${tgt}"
exit 1
fi
# Check Committed_AS
Committed_ASTxt=`cat ./cur_meminfo.txt | grep Committed_AS | awk '{print $(NF-1)}'`
Committed_AS=`echo "1024 * ${Committed_ASTxt}" | bc`
tgt=${Committed_AS}
if [ ${tgt} -eq $((${MemTotal} - ${MemFree})) ]; then
echo "[OK] Committed_AS: ${tgt}"
else
echo "[NG] unexpected Committed_AS: ${tgt}"
exit 1
fi

11
test/issues/1389/Makefile Normal file
View File

@ -0,0 +1,11 @@
CFLAGS=-g
LDFLAGS=
TARGET=C1389T01
all: $(TARGET)
test: all
sh ./C1389.sh
clean:
rm -f $(TARGET) *.o *.txt

46
test/issues/1389/README Normal file
View File

@ -0,0 +1,46 @@
【Issue#1389 動作確認】
□ テスト内容
本Issueの対応で、sysinfo()と/proc/meminfo の下記項目においてMcKernelの情報を
返すようにした。
[sysinfo]
totalram : rusage_global の total_memory
freeram : rusage_global の total_memory - usage_memory
mem_unit : 常に1
[/proc/meminfo]
MemTotal : rusage_global の total_memory
MemFree : rusage_global の total_memory - usage_memory
SwapTotal : 常に0
SwapFree : 常に0
CommitLimit : rusage_global の total_memory - usage_memory
Committed_AS : rusage_global の usage_memory
1. 本Issueで対応したsysinfo() と /proc/meminfo の値が想定どおりとなっていることを確認
McKernelへのメモリ割り当てを 10G@0,10G@1 とした状態で下記プログラムを実行
C1389T01: sysinfo() で取得される値が下記のとおりであることを確認
totalram : 20GiB * 0.95 以上、20GiB 未満であること
freeram : totralram * 0.95 以上、totalram 未満であること
mem_unit : 1 であること
C1389T02: /proc/meminfo から取得される値が下記のとおりであることを確認
MemTotal : 20GiB * 0.95 以上、20GiB 未満であること
MemFree : MemTotal * 0.95 以上、MemTotal 未満であること
SwapTotal : 0 であること
SwapFree : 0 であること
CommitLimit : MemFreeと同値であること
Committed_AS : MemTotal - MemFree と同値であること
2. 本Issueで対応したsysinfo() の項目を利用する以下のLTPを実行し、PASSすることを確認
- mtest01 -p80
- mtest01 -p80 -w
- mem01
□ 実行手順
$ 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していることを確認。

View File

@ -0,0 +1,77 @@
sh ./C1389.sh
mcstop+release.sh ... done
mcreboot.sh -c 1-7 -m 10G@0,10G@1 -O ... done
*** C1389T01 start *******************************
[OK] totalram: 21472215040
[OK] freeram: 21461794816
[OK] mem_unit: 1
*** C1389T01 PASSED ******************************
*** C1389T02 start *******************************
[OK] MemTotal: 21472215040
[OK] MemFree: 21452750848
[OK] SwapTotal: 0
[OK] SwapFree: 0
[OK] CommitLimit: 21452750848
[OK] Committed_AS: 19464192
*** C1389T02 PASSED ******************************
*** C1389T03 start *******************************
mtest01 -p80
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
mtest01.c:134: INFO: Filling up 80% of free ram which is 16760729 kbytes
mtest01.c:149: INFO: ... child 50935 starting
mtest01.c:149: INFO: ... child 50944 starting
mtest01.c:149: INFO: ... child 50953 starting
mtest01.c:149: INFO: ... child 50962 starting
mtest01.c:149: INFO: ... child 50971 starting
mtest01.c:149: INFO: ... child 50980 starting
mtest01.c:169: INFO: ... [t=300] 1434451968 bytes allocated only in child 50980
mtest01.c:169: INFO: ... [t=299] 3145728000 bytes allocated only in child 50935
mtest01.c:169: INFO: ... [t=299] 3145728000 bytes allocated only in child 50944
mtest01.c:169: INFO: ... [t=299] 3145728000 bytes allocated only in child 50953
mtest01.c:169: INFO: ... [t=299] 3145728000 bytes allocated only in child 50962
mtest01.c:169: INFO: ... [t=299] 3145728000 bytes allocated only in child 50971
mtest01.c:221: PASS: 16760729 kbytes allocated
Summary:
passed 1
failed 0
skipped 0
warnings 0
*** C1389T03 PASSED (1)
*** C1389T04 start *******************************
mtest01 -p80 -w
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
mtest01.c:134: INFO: Filling up 80% of free ram which is 16759654 kbytes
mtest01.c:149: INFO: ... child 51017 starting
mtest01.c:149: INFO: ... child 51026 starting
mtest01.c:149: INFO: ... child 51035 starting
mtest01.c:149: INFO: ... child 51044 starting
mtest01.c:149: INFO: ... child 51053 starting
mtest01.c:149: INFO: ... child 51062 starting
mtest01.c:166: INFO: ... [t=300] 1433403392 bytes allocated and used in child 51062
mtest01.c:166: INFO: ... [t=299] 3145728000 bytes allocated and used in child 51017
mtest01.c:166: INFO: ... [t=299] 3145728000 bytes allocated and used in child 51026
mtest01.c:166: INFO: ... [t=299] 3145728000 bytes allocated and used in child 51035
mtest01.c:166: INFO: ... [t=299] 3145728000 bytes allocated and used in child 51044
mtest01.c:166: INFO: ... [t=299] 3145728000 bytes allocated and used in child 51053
mtest01.c:221: PASS: 16759654 kbytes allocated (and written to)
Summary:
passed 1
failed 0
skipped 0
warnings 0
*** C1389T04 PASSED (1)
*** C1389T05 start *******************************
mem01
mem01 0 TINFO : Free Mem: 20465 Mb
mem01 0 TINFO : Free Swap: 0 Mb
mem01 0 TINFO : Total Free: 20465 Mb
mem01 0 TINFO : Total Tested: 3056 Mb
mem01 0 TINFO : touching 3056MB of malloc'ed memory (linear)
mem01 1 TPASS : malloc - alloc of 3056MB succeeded
*** C1389T05 PASSED (1)

View File

@ -0,0 +1,77 @@
sh ./C1389.sh
mcstop+release.sh ... done
mcreboot.sh -c 1-7 -m 10G@0,10G@1 -O ... done
*** C1389T01 start *******************************
[OK] totalram: 21463240704
[OK] freeram: 21459673088
[OK] mem_unit: 1
*** C1389T01 PASSED ******************************
*** C1389T02 start *******************************
[OK] MemTotal: 21463240704
[OK] MemFree: 21453983744
[OK] SwapTotal: 0
[OK] SwapFree: 0
[OK] CommitLimit: 21453983744
[OK] Committed_AS: 9256960
*** C1389T02 PASSED ******************************
*** C1389T03 start *******************************
mtest01 -p80
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
mtest01.c:134: INFO: Filling up 80% of free ram which is 16762396 kbytes
mtest01.c:149: INFO: ... child 20718 starting
mtest01.c:149: INFO: ... child 20727 starting
mtest01.c:149: INFO: ... child 20736 starting
mtest01.c:149: INFO: ... child 20745 starting
mtest01.c:149: INFO: ... child 20754 starting
mtest01.c:149: INFO: ... child 20763 starting
mtest01.c:169: INFO: ... [t=300] 1436549120 bytes allocated only in child 20763
mtest01.c:169: INFO: ... [t=299] 3145728000 bytes allocated only in child 20718
mtest01.c:169: INFO: ... [t=299] 3145728000 bytes allocated only in child 20727
mtest01.c:169: INFO: ... [t=299] 3145728000 bytes allocated only in child 20736
mtest01.c:169: INFO: ... [t=299] 3145728000 bytes allocated only in child 20745
mtest01.c:169: INFO: ... [t=299] 3145728000 bytes allocated only in child 20754
mtest01.c:221: PASS: 16762396 kbytes allocated
Summary:
passed 1
failed 0
skipped 0
warnings 0
*** C1389T03 PASSED (1)
*** C1389T04 start *******************************
mtest01 -p80 -w
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
mtest01.c:134: INFO: Filling up 80% of free ram which is 16761132 kbytes
mtest01.c:149: INFO: ... child 20802 starting
mtest01.c:149: INFO: ... child 20811 starting
mtest01.c:149: INFO: ... child 20820 starting
mtest01.c:149: INFO: ... child 20829 starting
mtest01.c:149: INFO: ... child 20838 starting
mtest01.c:149: INFO: ... child 20847 starting
mtest01.c:166: INFO: ... [t=300] 1435500544 bytes allocated and used in child 20847
mtest01.c:166: INFO: ... [t=299] 3145728000 bytes allocated and used in child 20802
mtest01.c:166: INFO: ... [t=299] 3145728000 bytes allocated and used in child 20811
mtest01.c:166: INFO: ... [t=299] 3145728000 bytes allocated and used in child 20820
mtest01.c:166: INFO: ... [t=299] 3145728000 bytes allocated and used in child 20829
mtest01.c:166: INFO: ... [t=299] 3145728000 bytes allocated and used in child 20838
mtest01.c:221: PASS: 16761132 kbytes allocated (and written to)
Summary:
passed 1
failed 0
skipped 0
warnings 0
*** C1389T04 PASSED (1)
*** C1389T05 start *******************************
mem01
mem01 0 TINFO : Free Mem: 20463 Mb
mem01 0 TINFO : Free Swap: 0 Mb
mem01 0 TINFO : Total Free: 20463 Mb
mem01 0 TINFO : Total Tested: 3056 Mb
mem01 0 TINFO : touching 3056MB of malloc'ed memory (linear)
mem01 1 TPASS : malloc - alloc of 3056MB succeeded
*** C1389T05 PASSED (1)

63
test/issues/1457/C1457.py Normal file
View File

@ -0,0 +1,63 @@
#
# Test script for issue #1439
#
import os
import sys
import subprocess
def get_command_result(cmd):
results = subprocess.Popen(
cmd, stdout=subprocess.PIPE,
shell=True).stdout.readlines()
return [str(x).rstrip("\n") for x in results]
def enumerate_cpu(cpu_list):
allcpus = []
for ranged_cpu in cpu_list.split(','):
try:
cpu_begin, cpu_end = ranged_cpu.split('-')
except ValueError:
cpu_begin = cpu_end = ranged_cpu
for i in range(int(cpu_begin), int(cpu_end) + 1):
allcpus.append(i)
allcpus.sort()
return allcpus
def get_online_cpu():
online_file = open('/sys/devices/system/cpu/online', 'r')
return online_file.readlines()[0].strip()
def get_cpuinfo_processors():
processors = []
cpuinfo_file = open('/proc/cpuinfo', 'r')
for line in cpuinfo_file.readlines():
if line.startswith('processor'):
processor = int(line.strip().split()[-1])
processors.append(processor)
return processors
def main():
onlines = enumerate_cpu(get_online_cpu())
processors = get_cpuinfo_processors()
print '# of online cpus:', len(onlines)
print '# of cpuinfo processors:', len(processors)
if len(onlines) != len(processors):
print 'ERROR: # of processors is not equal to # of cpus'
print 'FAIL'
exit()
i = 0
for cpu in processors:
print i, 'processor:', cpu
if i != cpu:
print 'ERROR: processor number is not ordered'
print 'FAIL'
exit()
i = i + 1
print 'SUCCESS'
if __name__ == '__main__':
main()

7
test/issues/1457/C1457.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
. ${HOME}/.mck_test_config
export MCK_DIR
sudo ${MCK_DIR}/sbin/mcreboot.sh 1,3,5,7,9-12,50-58
${MCK_DIR}/bin/mcexec python C1457.py
sudo ${MCK_DIR}/sbin/mcstop+release.sh

View File

@ -0,0 +1,2 @@
test::
./C1457.shy

22
test/issues/1457/README Normal file
View File

@ -0,0 +1,22 @@
□ テスト内容
arm64環境における/proc/cpuinfoについて、以下を確かめる。
(1) "processor" フィールドが/sys/devices/system/cpu/onlineファイルが示す
CPUの数だけ存在すること。
(2) "processor" フィールドの値が0からはじまる連番であること。
□ 実行手順
(1) $HOME/.mck_test_configを、MCK_DIRがMcKernelのインストール先を指すように編集する
(2) 以下を実行する
$ make test
□ 確認方法
標準出力にSUCCESSが出力されること

View File

@ -0,0 +1,31 @@
# of online cpus: 28
# of cpuinfo processors: 28
0 processor: 0
1 processor: 1
2 processor: 2
3 processor: 3
4 processor: 4
5 processor: 5
6 processor: 6
7 processor: 7
8 processor: 8
9 processor: 9
10 processor: 10
11 processor: 11
12 processor: 12
13 processor: 13
14 processor: 14
15 processor: 15
16 processor: 16
17 processor: 17
18 processor: 18
19 processor: 19
20 processor: 20
21 processor: 21
22 processor: 22
23 processor: 23
24 processor: 24
25 processor: 25
26 processor: 26
27 processor: 27
SUCCESS

145
test/issues/929/C929.sh Executable file
View File

@ -0,0 +1,145 @@
#/bin/sh
USELTP=0
USEOSTEST=0
. ../../common.sh
issue="929"
tid=01
tname=`printf "C${issue}T%02d" ${tid}`
echo "*** ${tname} start *******************************"
TEST_CMD="mpirun -f ./hostfile -ppn 5 ${MCEXEC} -n 5 ./test_prog.sh"
echo ${TEST_CMD}
${TEST_CMD} &> ${tname}.txt
mpi_ret=$?
cat ./${tname}.txt
started_num=`grep 'test_prog is started' ./${tname}.txt | wc -l`
if [ ${mpi_ret} -eq 0 -a ${started_num} -eq 5 ]; then
echo "*** ${tname} PASSED ******************************"
else
echo "*** ${tname} FAILED ******************************"
fi
let tid++
echo ""
tname=`printf "C${issue}T%02d" ${tid}`
echo "*** ${tname} start *******************************"
TEST_CMD="mpirun -f ./hostfile -ppn 5 ${MCEXEC} -n 3 ./test_prog.sh"
echo ${TEST_CMD}
${TEST_CMD} &> ${tname}.txt
mpi_ret=$?
cat ./${tname}.txt
started_num=`grep 'test_prog is started' ./${tname}.txt | wc -l`
if [ ${mpi_ret} -ne 0 -a ${started_num} -eq 3 ]; then
echo "*** ${tname} PASSED ******************************"
else
echo "*** ${tname} FAILED ******************************"
fi
let tid++
echo ""
tname=`printf "C${issue}T%02d" ${tid}`
echo "*** ${tname} start *******************************"
TEST_CMD="mpirun -f ./hostfile -ppn 3 ${MCEXEC} -n 5 ./test_prog.sh"
echo ${TEST_CMD}
${TEST_CMD} &> ${tname}.txt
mpi_ret=$?
cat ./${tname}.txt
started_num=`grep 'test_prog is started' ./${tname}.txt | wc -l`
if [ ${mpi_ret} -ne 0 -a ${started_num} -eq 0 ]; then
echo "*** ${tname} PASSED ******************************"
else
echo "*** ${tname} FAILED ******************************"
fi
let tid++
echo ""
tname=`printf "C${issue}T%02d" ${tid}`
echo "*** ${tname} start *******************************"
TEST_CMD="mpirun -f ./hostfile -ppn 6 ${MCEXEC} -n 3 ./test_prog.sh"
echo ${TEST_CMD}
${TEST_CMD} &> ${tname}.txt
mpi_ret=$?
cat ./${tname}.txt
started_num=`grep 'test_prog is started' ./${tname}.txt | wc -l`
if [ ${mpi_ret} -ne 0 -a ${started_num} -eq 3 ]; then
echo "*** ${tname} PASSED ******************************"
else
echo "*** ${tname} FAILED ******************************"
fi
let tid++
echo ""
tname=`printf "C${issue}T%02d" ${tid}`
echo "*** ${tname} start *******************************"
TEST_CMD="mpirun -f ./hostfile -ppn 250 ${MCEXEC} -n 250 ./test_prog.sh"
echo ${TEST_CMD}
${TEST_CMD} &> ${tname}.txt
mpi_ret=$?
head -n 10 ./${tname}.txt
echo "..."
started_num=`grep 'test_prog is started' ./${tname}.txt | wc -l`
if [ ${mpi_ret} -ne 0 -a ${started_num} -eq 0 ]; then
echo "*** ${tname} PASSED ******************************"
else
echo "*** ${tname} FAILED ******************************"
fi
let tid++
echo ""
tname=`printf "C${issue}T%02d" ${tid}`
echo "*** ${tname} start *******************************"
ng=0
TEST_CMD="mpirun -f ./hostfile -ppn 5 ${MCEXEC} -n 5 ./test_prog.sh"
echo "** reboot mcrernel for check pe_list_len"
mcreboot
echo "** enable debug message in mcexec_get_cpuset"
sudo sh -c "echo -n 'func mcexec_get_cpuset +p' > /sys/kernel/debug/dynamic_debug/control"
echo ${TEST_CMD}
for i in `seq 1 20`
do
${TEST_CMD} &> ${tname}.txt
mpi_ret=$?
started_num=`grep 'test_prog is started' ./${tname}.txt | wc -l`
if [ ${mpi_ret} -eq 0 -a ${started_num} -eq 5 ]; then
echo "[OK] exec: $i"
else
echo "[NG] exec: $i"
let ng++
fi
done
echo "** check pe_list_len"
dmesg --notime | grep "mcexec_get_cpuset: pe_list" | tail -n 20 | cut -f 2-3 -d ':' > ./pe_list_len.txt
cat ./pe_list_len.txt | while read line
do
len=`echo ${line} | cut -f 2 -d ':'`
if [ ${len} -ge 0 -a ${len} -le 5 ]; then
echo "[OK] ${line}"
else
echo "[NG] ${line}"
let ng++
fi
done
echo "** disable debug message in mcexec_get_cpuset"
sudo sh -c "echo -n 'func mcexec_get_cpuset -p' > /sys/kernel/debug/dynamic_debug/control"
if [ ${ng} -eq 0 ]; then
echo "*** ${tname} PASSED ******************************"
else
echo "*** ${tname} FAILED ******************************"
fi
let tid++
echo ""

11
test/issues/929/Makefile Normal file
View File

@ -0,0 +1,11 @@
CFLAGS=-g
LDFLAGS=
TARGET=
all: $(TARGET)
test: all
./C929.sh
clean:
rm -f $(TARGET) *.o *.txt

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

@ -0,0 +1,36 @@
【Issue#929 動作確認】
□ テスト内容
1. mpirunで指定する-ppnと、mcexecで指定する-n の指定状況ごとに
想定どおりの動作となることを確認
C929T01:
-ppn == -n の場合に、プログラムが実行され、mpirunが成功する
C929T02:
-ppn > -n の場合に、プログラムの一部が実行され、mpirunが失敗する
C929T03:
-ppn < -n の場合に、プログラムが実行されず、mpirunが失敗する
C929T04:
-ppn が -n の整数倍である場合に、プログラムの一部が実行され、mpirunが失敗する
C929T05:
-ppn と -n がMcKernelに割り当てたCPU数よりも大きい場合に、
プログラムが実行されず、mpirunが失敗する
C929T06:
-ppn == -n での正常実行を20回連続で行った場合に、
プログラムが実行され、mpirunが成功する
また、mcctrlで管理しているpart_exec_list の要素数が5を超えない
□ 実行手順
$ 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していることを確認。

View File

@ -0,0 +1,99 @@
*** C929T01 start *******************************
mpirun -f ./hostfile -ppn 5 /home/satoken/ihk+mckernel/bin/mcexec -n 5 ./test_prog.sh
test_prog is started.
test_prog is started.
test_prog is started.
test_prog is started.
test_prog is started.
*** C929T01 PASSED ******************************
*** C929T02 start *******************************
mpirun -f ./hostfile -ppn 5 /home/satoken/ihk+mckernel/bin/mcexec -n 3 ./test_prog.sh
getting CPU set for partitioned execution: Invalid argument
getting CPU set for partitioned execution: Invalid argument
test_prog is started.
test_prog is started.
test_prog is started.
*** C929T02 PASSED ******************************
*** C929T03 start *******************************
mpirun -f ./hostfile -ppn 3 /home/satoken/ihk+mckernel/bin/mcexec -n 5 ./test_prog.sh
getting CPU set for partitioned execution: Connection timed out
getting CPU set for partitioned execution: Connection timed out
getting CPU set for partitioned execution: Connection timed out
*** C929T03 PASSED ******************************
*** C929T04 start *******************************
mpirun -f ./hostfile -ppn 6 /home/satoken/ihk+mckernel/bin/mcexec -n 3 ./test_prog.sh
getting CPU set for partitioned execution: Invalid argument
getting CPU set for partitioned execution: Invalid argument
getting CPU set for partitioned execution: Invalid argument
test_prog is started.
test_prog is started.
test_prog is started.
*** C929T04 PASSED ******************************
*** C929T05 start *******************************
mpirun -f ./hostfile -ppn 250 /home/satoken/ihk+mckernel/bin/mcexec -n 250 ./test_prog.sh
error: nr_processes can't exceed nr. of CPUs
error: nr_processes can't exceed nr. of CPUs
error: nr_processes can't exceed nr. of CPUs
error: nr_processes can't exceed nr. of CPUs
error: nr_processes can't exceed nr. of CPUs
error: nr_processes can't exceed nr. of CPUs
error: nr_processes can't exceed nr. of CPUs
error: nr_processes can't exceed nr. of CPUs
error: nr_processes can't exceed nr. of CPUs
error: nr_processes can't exceed nr. of CPUs
...
*** C929T05 PASSED ******************************
*** C929T06 start *******************************
** reboot mcrernel for check pe_list_len
mcreboot.sh -c 1-6,29-34 -m 50G@0,50G@1 -r 1-6:0+29-34:28 -O ... done
** enable debug message in mcexec_get_cpuset
mpirun -f ./hostfile -ppn 5 /home/satoken/ihk+mckernel/bin/mcexec -n 5 ./test_prog.sh
[OK] exec: 1
[OK] exec: 2
[OK] exec: 3
[OK] exec: 4
[OK] exec: 5
[OK] exec: 6
[OK] exec: 7
[OK] exec: 8
[OK] exec: 9
[OK] exec: 10
[OK] exec: 11
[OK] exec: 12
[OK] exec: 13
[OK] exec: 14
[OK] exec: 15
[OK] exec: 16
[OK] exec: 17
[OK] exec: 18
[OK] exec: 19
[OK] exec: 20
** check pe_list_len
[OK] pe_list_len:0
[OK] pe_list_len:1
[OK] pe_list_len:2
[OK] pe_list_len:3
[OK] pe_list_len:4
[OK] pe_list_len:5
[OK] pe_list_len:5
[OK] pe_list_len:5
[OK] pe_list_len:5
[OK] pe_list_len:5
[OK] pe_list_len:5
[OK] pe_list_len:5
[OK] pe_list_len:5
[OK] pe_list_len:5
[OK] pe_list_len:5
[OK] pe_list_len:5
[OK] pe_list_len:5
[OK] pe_list_len:5
[OK] pe_list_len:5
[OK] pe_list_len:5
** disable debug message in mcexec_get_cpuset
*** C929T06 PASSED ******************************

1
test/issues/929/hostfile Normal file
View File

@ -0,0 +1 @@
localhost

3
test/issues/929/test_prog.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
echo "test_prog is started."

View File

@ -0,0 +1,74 @@
*** C929T01 start *******************************
mpirun -f ./hostfile -ppn 5 /home/satoken/ihk+mckernel/bin/mcexec -n 5 ./test_prog.sh
test_prog is started.
test_prog is started.
test_prog is started.
test_prog is started.
test_prog is started.
*** C929T01 PASSED ******************************
*** C929T02 start *******************************
mpirun -f ./hostfile -ppn 5 /home/satoken/ihk+mckernel/bin/mcexec -n 3 ./test_prog.sh
getting CPU set for partitioned execution: Invalid argument
getting CPU set for partitioned execution: Invalid argument
test_prog is started.
test_prog is started.
test_prog is started.
*** C929T02 PASSED ******************************
*** C929T03 start *******************************
mpirun -f ./hostfile -ppn 3 /home/satoken/ihk+mckernel/bin/mcexec -n 5 ./test_prog.sh
getting CPU set for partitioned execution: Connection timed out
getting CPU set for partitioned execution: Connection timed out
getting CPU set for partitioned execution: Connection timed out
*** C929T03 PASSED ******************************
*** C929T04 start *******************************
mpirun -f ./hostfile -ppn 6 /home/satoken/ihk+mckernel/bin/mcexec -n 3 ./test_prog.sh
getting CPU set for partitioned execution: Invalid argument
getting CPU set for partitioned execution: Invalid argument
getting CPU set for partitioned execution: Invalid argument
test_prog is started.
test_prog is started.
test_prog is started.
*** C929T04 PASSED ******************************
*** C929T05 start *******************************
mpirun -f ./hostfile -ppn 250 /home/satoken/ihk+mckernel/bin/mcexec -n 250 ./test_prog.sh
error: nr_processes can't exceed nr. of CPUs
error: nr_processes can't exceed nr. of CPUs
error: nr_processes can't exceed nr. of CPUs
error: nr_processes can't exceed nr. of CPUs
error: nr_processes can't exceed nr. of CPUs
error: nr_processes can't exceed nr. of CPUs
error: nr_processes can't exceed nr. of CPUs
error: nr_processes can't exceed nr. of CPUs
error: nr_processes can't exceed nr. of CPUs
error: nr_processes can't exceed nr. of CPUs
...
*** C929T05 PASSED ******************************
*** C929T06 start *******************************
mpirun -f ./hostfile -ppn 5 /home/satoken/ihk+mckernel/bin/mcexec -n 5 ./test_prog.sh
[OK] exec: 1
[OK] exec: 2
[OK] exec: 3
[OK] exec: 4
[OK] exec: 5
[OK] exec: 6
[OK] exec: 7
[OK] exec: 8
[OK] exec: 9
[OK] exec: 10
[OK] exec: 11
[OK] exec: 12
[OK] exec: 13
[OK] exec: 14
[OK] exec: 15
[OK] exec: 16
[OK] exec: 17
[OK] exec: 18
[OK] exec: 19
[OK] exec: 20
*** C929T06 PASSED ******************************