ptrace supports threads

Fujitsu: POSTK_DEBUG_TEMP_FIX_53, POSTK_DEBUG_ARCH_DEP_44
Refs: #771, #1179, #1143
Change-Id: Ie17ece6864f0eeb0c0e550f4e369abb77980a0d0
This commit is contained in:
Tomoki Shirasawa
2018-09-14 14:50:36 +09:00
committed by Dominique Martinet
parent 28c434a230
commit ed1edb152b
17 changed files with 2513 additions and 575 deletions

View File

@ -537,23 +537,32 @@ void ptrace_report_signal(struct thread *thread, int sig)
dkprintf("ptrace_report_signal, tid=%d, pid=%d\n", thread->tid, thread->proc->pid); dkprintf("ptrace_report_signal, tid=%d, pid=%d\n", thread->tid, thread->proc->pid);
mcs_rwlock_writer_lock(&proc->update_lock, &lock); mcs_rwlock_writer_lock(&proc->update_lock, &lock);
if(!(proc->ptrace & PT_TRACED)){ if (!(thread->ptrace & PT_TRACED)) {
mcs_rwlock_writer_unlock(&proc->update_lock, &lock); mcs_rwlock_writer_unlock(&proc->update_lock, &lock);
return; return;
} }
thread->exit_status = sig;
/* Transition thread state */ /* Transition thread state */
proc->status = PS_DELAY_TRACED; thread->exit_status = sig;
thread->status = PS_TRACED; thread->status = PS_TRACED;
proc->ptrace &= ~PT_TRACE_SYSCALL; thread->ptrace &= ~PT_TRACE_SYSCALL;
if (sig == SIGSTOP || sig == SIGTSTP ||
sig == SIGTTIN || sig == SIGTTOU) {
proc->signal_flags |= SIGNAL_STOP_STOPPED;
} else {
proc->signal_flags &= ~SIGNAL_STOP_STOPPED;
}
parent_pid = proc->parent->pid;
save_debugreg(thread->ptrace_debugreg); save_debugreg(thread->ptrace_debugreg);
if (sig == SIGSTOP || sig == SIGTSTP ||
sig == SIGTTIN || sig == SIGTTOU) {
thread->signal_flags |= SIGNAL_STOP_STOPPED;
}
else {
thread->signal_flags &= ~SIGNAL_STOP_STOPPED;
}
if (thread == proc->main_thread) {
proc->status = PS_DELAY_TRACED;
parent_pid = proc->parent->pid;
}
else {
parent_pid = thread->report_proc->pid;
waitq_wakeup(&thread->report_proc->waitpid_q);
}
mcs_rwlock_writer_unlock(&proc->update_lock, &lock); mcs_rwlock_writer_unlock(&proc->update_lock, &lock);
memset(&info, '\0', sizeof info); memset(&info, '\0', sizeof info);
@ -574,9 +583,8 @@ ptrace_arch_prctl(int pid, long code, long addr)
{ {
long rc = -EIO; long rc = -EIO;
struct thread *child; struct thread *child;
struct mcs_rwlock_node_irqsave lock;
child = find_thread(pid, pid, &lock); child = find_thread(pid, pid);
if (!child) if (!child)
return -ESRCH; return -ESRCH;
if (child->proc->status & (PS_TRACED | PS_STOPPED)) { if (child->proc->status & (PS_TRACED | PS_STOPPED)) {
@ -618,7 +626,7 @@ ptrace_arch_prctl(int pid, long code, long addr)
break; break;
} }
} }
thread_unlock(child, &lock); thread_unlock(child);
return rc; return rc;
} }
@ -690,9 +698,9 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
dkprintf("do_signal(): tid=%d, pid=%d, sig=%d\n", thread->tid, proc->pid, sig); dkprintf("do_signal(): tid=%d, pid=%d, sig=%d\n", thread->tid, proc->pid, sig);
orgsig = sig; orgsig = sig;
if((proc->ptrace & PT_TRACED) && if ((thread->ptrace & PT_TRACED) &&
pending->ptracecont == 0 && pending->ptracecont == 0 &&
sig != SIGKILL) { sig != SIGKILL) {
ptraceflag = 1; ptraceflag = 1;
sig = SIGSTOP; sig = SIGSTOP;
} }
@ -835,6 +843,7 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
else { else {
int coredumped = 0; int coredumped = 0;
siginfo_t info; siginfo_t info;
int ptc = pending->ptracecont;
if(ptraceflag){ if(ptraceflag){
if(thread->ptrace_recvsig) if(thread->ptrace_recvsig)
@ -861,22 +870,37 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
info.si_code = CLD_STOPPED; info.si_code = CLD_STOPPED;
info._sifields._sigchld.si_pid = thread->proc->pid; info._sifields._sigchld.si_pid = thread->proc->pid;
info._sifields._sigchld.si_status = (sig << 8) | 0x7f; info._sifields._sigchld.si_status = (sig << 8) | 0x7f;
do_kill(cpu_local_var(current), thread->proc->parent->pid, -1, SIGCHLD, &info, 0); if (ptc == 2 &&
dkprintf("do_signal,SIGSTOP,changing state\n"); thread != thread->proc->main_thread) {
thread->signal_flags =
SIGNAL_STOP_STOPPED;
thread->status = PS_STOPPED;
thread->exit_status = SIGSTOP;
do_kill(thread,
thread->report_proc->pid, -1,
SIGCHLD, &info, 0);
waitq_wakeup(
&thread->report_proc->waitpid_q);
}
else {
/* Update thread state in fork tree */
mcs_rwlock_writer_lock(
&proc->update_lock, &lock);
proc->group_exit_status = SIGSTOP;
/* Update thread state in fork tree */ /* Reap and set new signal_flags */
mcs_rwlock_writer_lock(&proc->update_lock, &lock); proc->main_thread->signal_flags =
proc->group_exit_status = SIGSTOP; SIGNAL_STOP_STOPPED;
/* Reap and set new signal_flags */ proc->status = PS_DELAY_STOPPED;
proc->signal_flags = SIGNAL_STOP_STOPPED; thread->status = PS_STOPPED;
mcs_rwlock_writer_unlock(
&proc->update_lock, &lock);
proc->status = PS_DELAY_STOPPED; do_kill(thread,
thread->status = PS_STOPPED; thread->proc->parent->pid, -1,
mcs_rwlock_writer_unlock(&proc->update_lock, &lock); SIGCHLD, &info, 0);
}
dkprintf("do_signal(): pid: %d, tid: %d SIGSTOP, sleeping\n",
proc->pid, thread->tid);
/* Sleep */ /* Sleep */
schedule(); schedule();
dkprintf("SIGSTOP(): woken up\n"); dkprintf("SIGSTOP(): woken up\n");
@ -884,16 +908,28 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
break; break;
case SIGTRAP: case SIGTRAP:
dkprintf("do_signal,SIGTRAP\n"); dkprintf("do_signal,SIGTRAP\n");
if(!(proc->ptrace & PT_TRACED)) { if (!(thread->ptrace & PT_TRACED)) {
goto core; goto core;
} }
/* Update thread state in fork tree */ /* Update thread state in fork tree */
mcs_rwlock_writer_lock(&proc->update_lock, &lock);
thread->exit_status = SIGTRAP; thread->exit_status = SIGTRAP;
proc->status = PS_DELAY_TRACED;
thread->status = PS_TRACED; thread->status = PS_TRACED;
mcs_rwlock_writer_unlock(&proc->update_lock, &lock); if (thread == proc->main_thread) {
mcs_rwlock_writer_lock(&proc->update_lock,
&lock);
proc->group_exit_status = SIGTRAP;
proc->status = PS_DELAY_TRACED;
mcs_rwlock_writer_unlock(&proc->update_lock,
&lock);
do_kill(thread, thread->proc->parent->pid, -1,
SIGCHLD, &info, 0);
}
else {
do_kill(thread, thread->report_proc->pid, -1,
SIGCHLD, &info, 0);
waitq_wakeup(&thread->report_proc->waitpid_q);
}
/* Sleep */ /* Sleep */
dkprintf("do_signal,SIGTRAP,sleeping\n"); dkprintf("do_signal,SIGTRAP,sleeping\n");
@ -908,7 +944,7 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
info._sifields._sigchld.si_pid = proc->pid; info._sifields._sigchld.si_pid = proc->pid;
info._sifields._sigchld.si_status = 0x0000ffff; info._sifields._sigchld.si_status = 0x0000ffff;
do_kill(cpu_local_var(current), proc->parent->pid, -1, SIGCHLD, &info, 0); do_kill(cpu_local_var(current), proc->parent->pid, -1, SIGCHLD, &info, 0);
proc->signal_flags = SIGNAL_STOP_CONTINUED; proc->main_thread->signal_flags = SIGNAL_STOP_CONTINUED;
proc->status = PS_RUNNING; proc->status = PS_RUNNING;
dkprintf("do_signal,SIGCONT,do nothing\n"); dkprintf("do_signal,SIGCONT,do nothing\n");
break; break;
@ -958,10 +994,12 @@ getsigpending(struct thread *thread, int delflag){
lock = &thread->sigcommon->lock; lock = &thread->sigcommon->lock;
head = &thread->sigcommon->sigpending; head = &thread->sigcommon->sigpending;
for(;;) { for(;;) {
if (delflag) if (delflag) {
mcs_rwlock_writer_lock(lock, &mcs_rw_node); mcs_rwlock_writer_lock(lock, &mcs_rw_node);
else }
else {
mcs_rwlock_reader_lock(lock, &mcs_rw_node); mcs_rwlock_reader_lock(lock, &mcs_rw_node);
}
list_for_each_entry_safe(pending, next, head, list){ list_for_each_entry_safe(pending, next, head, list){
for(x = pending->sigmask.__val[0], sig = 0; x; sig++, x >>= 1); for(x = pending->sigmask.__val[0], sig = 0; x; sig++, x >>= 1);
@ -974,19 +1012,23 @@ getsigpending(struct thread *thread, int delflag){
if(delflag) if(delflag)
list_del(&pending->list); list_del(&pending->list);
if (delflag) if (delflag) {
mcs_rwlock_writer_unlock(lock, &mcs_rw_node); mcs_rwlock_writer_unlock(lock, &mcs_rw_node);
else }
else {
mcs_rwlock_reader_unlock(lock, &mcs_rw_node); mcs_rwlock_reader_unlock(lock, &mcs_rw_node);
}
return pending; return pending;
} }
} }
} }
if (delflag) if (delflag) {
mcs_rwlock_writer_unlock(lock, &mcs_rw_node); mcs_rwlock_writer_unlock(lock, &mcs_rw_node);
else }
else {
mcs_rwlock_reader_unlock(lock, &mcs_rw_node); mcs_rwlock_reader_unlock(lock, &mcs_rw_node);
}
if(lock == &thread->sigpendinglock) if(lock == &thread->sigpendinglock)
return NULL; return NULL;
@ -1177,7 +1219,7 @@ repeat:
continue; continue;
} }
if (thread->proc->exit_status & 0x0000000100000000L) { if (thread->proc->group_exit_status & 0x0000000100000000L) {
continue; continue;
} }
@ -1404,10 +1446,10 @@ done:
in check_signal */ in check_signal */
rc = 0; rc = 0;
k = tthread->sigcommon->action + sig - 1; k = tthread->sigcommon->action + sig - 1;
if((sig != SIGKILL && (tproc->ptrace & PT_TRACED)) || if ((sig != SIGKILL && (tthread->ptrace & PT_TRACED)) ||
(k->sa.sa_handler != (void *)1 && (k->sa.sa_handler != (void *)1 &&
(k->sa.sa_handler != NULL || (k->sa.sa_handler != NULL ||
(sig != SIGCHLD && sig != SIGURG)))){ (sig != SIGCHLD && sig != SIGURG)))) {
struct sig_pending *pending = NULL; struct sig_pending *pending = NULL;
if (sig < 33) { // SIGRTMIN - SIGRTMAX if (sig < 33) { // SIGRTMIN - SIGRTMAX
list_for_each_entry(pending, head, list){ list_for_each_entry(pending, head, list){

View File

@ -576,7 +576,6 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c,
struct ikc_scd_packet pckt; struct ikc_scd_packet pckt;
struct ihk_ikc_channel_desc *resp_channel = cpu_local_var(ikc2linux); struct ihk_ikc_channel_desc *resp_channel = cpu_local_var(ikc2linux);
int rc; int rc;
struct mcs_rwlock_node_irqsave lock;
struct thread *thread; struct thread *thread;
struct process *proc; struct process *proc;
struct mcctrl_signal { struct mcctrl_signal {
@ -637,14 +636,14 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c,
* the waiting thread * the waiting thread
*/ */
case SCD_MSG_WAKE_UP_SYSCALL_THREAD: case SCD_MSG_WAKE_UP_SYSCALL_THREAD:
thread = find_thread(0, packet->ttid, &lock); thread = find_thread(0, packet->ttid);
if (!thread) { if (!thread) {
kprintf("%s: WARNING: no thread for SCD reply? TID: %d\n", kprintf("%s: WARNING: no thread for SCD reply? TID: %d\n",
__FUNCTION__, packet->ttid); __FUNCTION__, packet->ttid);
ret = -EINVAL; ret = -EINVAL;
break; break;
} }
thread_unlock(thread, &lock); thread_unlock(thread);
dkprintf("%s: SCD_MSG_WAKE_UP_SYSCALL_THREAD: waking up tid %d\n", dkprintf("%s: SCD_MSG_WAKE_UP_SYSCALL_THREAD: waking up tid %d\n",
__FUNCTION__, packet->ttid); __FUNCTION__, packet->ttid);

View File

@ -464,6 +464,14 @@ struct process {
// threads and children // threads and children
struct list_head threads_list; struct list_head threads_list;
struct list_head report_threads_list;
/*
* main_thread is used to refer to thread information using process ID.
* 1) signal related state in signal_flags
* 2) status of trace
*/
struct thread *main_thread;
mcs_rwlock_lock_t threads_lock; // lock for threads_list mcs_rwlock_lock_t threads_lock; // lock for threads_list
/* TID set of proxy process */ /* TID set of proxy process */
struct mcexec_tid *tids; struct mcexec_tid *tids;
@ -492,7 +500,6 @@ struct process {
// V +---- | // V +---- |
// PS_STOPPED -----+ // PS_STOPPED -----+
// (PS_TRACED) // (PS_TRACED)
unsigned long exit_status; // only for zombie
/* Store exit_status for a group of threads when stopped by SIGSTOP. /* 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 exit_status can't be used because values of exit_status of threads
@ -524,22 +531,6 @@ struct process {
long saved_cmdline_len; long saved_cmdline_len;
cpu_set_t cpu_set; cpu_set_t cpu_set;
/* Store ptrace flags.
* The lower 8 bits are PTRACE_O_xxx of the PTRACE_SETOPTIONS request.
* Other bits are for inner use of the McKernel.
*/
int ptrace;
/* Store ptrace event message.
* PTRACE_O_xxx will store event message here.
* PTRACE_GETEVENTMSG will get from here.
*/
unsigned long ptrace_eventmsg;
/* Store event related to signal. For example,
it represents that the proceess has been resumed by SIGCONT. */
int signal_flags;
/* Store signal sent to parent when the process terminates. */ /* Store signal sent to parent when the process terminates. */
int termsig; int termsig;
@ -610,7 +601,7 @@ struct thread {
// thread info // thread info
int cpu_id; int cpu_id;
int tid; int tid;
int status; // PS_RUNNING -> PS_EXITED int status; // PS_RUNNING -> PS_EXITED (-> ZOMBIE / ptrace)
// | ^ ^ // | ^ ^
// | | | // | | |
// V | | // V | |
@ -620,6 +611,14 @@ struct thread {
// PS_UNINTERRUPTIBLE // PS_UNINTERRUPTIBLE
int exit_status; int exit_status;
/*
* Store event related to signal. For example,
* it represents that the proceess has been resumed by SIGCONT.
*/
int signal_flags;
int termsig;
// process vm // process vm
struct process_vm *vm; struct process_vm *vm;
@ -639,6 +638,22 @@ struct thread {
ihk_spinlock_t spin_sleep_lock; ihk_spinlock_t spin_sleep_lock;
int spin_sleep; int spin_sleep;
// for ptrace
struct process *report_proc;
struct list_head report_siblings_list; // lock process
/* Store ptrace flags.
* The lower 8 bits are PTRACE_O_xxx of the PTRACE_SETOPTIONS request.
* Other bits are for inner use of the McKernel.
*/
int ptrace;
/* Store ptrace event message.
* PTRACE_O_xxx will store event message here.
* PTRACE_GETEVENTMSG will get from here.
*/
unsigned long ptrace_eventmsg;
ihk_atomic_t refcount; ihk_atomic_t refcount;
int *clear_child_tid; int *clear_child_tid;
@ -830,8 +845,8 @@ void cpu_clear_and_set(int c_cpu, int s_cpu,
void release_cpuid(int cpuid); void release_cpuid(int cpuid);
struct thread *find_thread(int pid, int tid, struct mcs_rwlock_node_irqsave *lock); struct thread *find_thread(int pid, int tid);
void thread_unlock(struct thread *thread, struct mcs_rwlock_node_irqsave *lock); void thread_unlock(struct thread *thread);
struct process *find_process(int pid, struct mcs_rwlock_node_irqsave *lock); struct process *find_process(int pid, struct mcs_rwlock_node_irqsave *lock);
void process_unlock(struct process *proc, struct mcs_rwlock_node_irqsave *lock); void process_unlock(struct process *proc, struct mcs_rwlock_node_irqsave *lock);
void chain_process(struct process *); void chain_process(struct process *);
@ -846,6 +861,7 @@ extern unsigned long do_kill(struct thread *thread, int pid, int tid, int sig,
struct siginfo *info, int ptracecont); struct siginfo *info, int ptracecont);
extern void set_signal(int sig, void *regs, struct siginfo *info); extern void set_signal(int sig, void *regs, struct siginfo *info);
extern void check_sig_pending(void); extern void check_sig_pending(void);
void clear_single_step(struct thread *thread);
void release_fp_regs(struct thread *proc); void release_fp_regs(struct thread *proc);
void save_fp_regs(struct thread *proc); void save_fp_regs(struct thread *proc);

View File

@ -125,6 +125,7 @@ init_process(struct process *proc, struct process *parent)
INIT_LIST_HEAD(&proc->ptraced_siblings_list); INIT_LIST_HEAD(&proc->ptraced_siblings_list);
mcs_rwlock_init(&proc->update_lock); mcs_rwlock_init(&proc->update_lock);
#endif /* POSTK_DEBUG_ARCH_DEP_63 */ #endif /* POSTK_DEBUG_ARCH_DEP_63 */
INIT_LIST_HEAD(&proc->report_threads_list);
INIT_LIST_HEAD(&proc->threads_list); INIT_LIST_HEAD(&proc->threads_list);
INIT_LIST_HEAD(&proc->children_list); INIT_LIST_HEAD(&proc->children_list);
INIT_LIST_HEAD(&proc->ptraced_children_list); INIT_LIST_HEAD(&proc->ptraced_children_list);
@ -349,6 +350,7 @@ struct thread *create_thread(unsigned long user_pc,
thread->vm = vm; thread->vm = vm;
thread->proc = proc; thread->proc = proc;
proc->vm = vm; proc->vm = vm;
proc->main_thread = thread;
if(init_process_vm(proc, asp, vm) != 0){ if(init_process_vm(proc, asp, vm) != 0){
goto err; goto err;
@ -466,6 +468,7 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp,
thread->proc = proc; thread->proc = proc;
thread->vm = proc->vm; thread->vm = proc->vm;
proc->main_thread = thread;
memcpy(&proc->vm->region, &org->vm->region, sizeof(struct vm_regions)); memcpy(&proc->vm->region, &org->vm->region, sizeof(struct vm_regions));
@ -570,29 +573,47 @@ ptrace_traceme(void)
struct thread *thread = cpu_local_var(current); struct thread *thread = cpu_local_var(current);
struct process *proc = thread->proc; struct process *proc = thread->proc;
struct process *parent = proc->parent; struct process *parent = proc->parent;
struct mcs_rwlock_node_irqsave lock;
struct mcs_rwlock_node child_lock; struct mcs_rwlock_node child_lock;
struct resource_set *resource_set = cpu_local_var(resource_set);
struct process *pid1 = resource_set->pid1;
dkprintf("ptrace_traceme,pid=%d,proc->parent=%p\n", proc->pid, proc->parent); dkprintf("ptrace_traceme,pid=%d,proc->parent=%p\n", proc->pid, proc->parent);
if (proc->ptrace & PT_TRACED) { if (thread->ptrace & PT_TRACED) {
return -EPERM;
}
if (parent == pid1) {
return -EPERM; return -EPERM;
} }
dkprintf("ptrace_traceme,parent->pid=%d\n", proc->parent->pid); dkprintf("ptrace_traceme,parent->pid=%d\n", proc->parent->pid);
mcs_rwlock_writer_lock(&proc->update_lock, &lock); if (thread == proc->main_thread) {
mcs_rwlock_writer_lock_noirq(&parent->children_lock, &child_lock); mcs_rwlock_writer_lock_noirq(&parent->children_lock,
list_add_tail(&proc->ptraced_siblings_list, &parent->ptraced_children_list); &child_lock);
mcs_rwlock_writer_unlock_noirq(&parent->children_lock, &child_lock); list_add_tail(&proc->ptraced_siblings_list,
proc->ptrace = PT_TRACED | PT_TRACE_EXEC; &parent->ptraced_children_list);
mcs_rwlock_writer_unlock(&proc->update_lock, &lock); mcs_rwlock_writer_unlock_noirq(&parent->children_lock,
&child_lock);
}
if (!thread->report_proc) {
mcs_rwlock_writer_lock_noirq(&parent->threads_lock,
&child_lock);
list_add_tail(&thread->report_siblings_list,
&parent->report_threads_list);
mcs_rwlock_writer_unlock_noirq(&parent->threads_lock,
&child_lock);
thread->report_proc = parent;
}
thread->ptrace = PT_TRACED | PT_TRACE_EXEC;
if (thread->ptrace_debugreg == NULL) { if (thread->ptrace_debugreg == NULL) {
error = alloc_debugreg(thread); error = alloc_debugreg(thread);
} }
clear_single_step(thread); clear_single_step(thread);
hold_thread(thread);
dkprintf("ptrace_traceme,returning,error=%d\n", error); dkprintf("ptrace_traceme,returning,error=%d\n", error);
return error; return error;
@ -2430,6 +2451,11 @@ void free_process_memory_ranges(struct process_vm *vm)
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock); ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
} }
static void free_thread_pages(struct thread *thread)
{
ihk_mc_free_pages(thread, KERNEL_STACK_NR_PAGES);
}
void void
hold_process(struct process *proc) hold_process(struct process *proc)
{ {
@ -2462,13 +2488,6 @@ release_process(struct process *proc)
list_del(&proc->siblings_list); list_del(&proc->siblings_list);
mcs_rwlock_writer_unlock(&parent->children_lock, &lock); mcs_rwlock_writer_unlock(&parent->children_lock, &lock);
if(proc->ptrace & PT_TRACED){
parent = proc->ppid_parent;
mcs_rwlock_writer_lock(&parent->children_lock, &lock);
list_del(&proc->ptraced_siblings_list);
mcs_rwlock_writer_unlock(&parent->children_lock, &lock);
}
if (proc->tids) kfree(proc->tids); if (proc->tids) kfree(proc->tids);
#ifdef PROFILE_ENABLE #ifdef PROFILE_ENABLE
if (proc->profile) { if (proc->profile) {
@ -2481,6 +2500,7 @@ release_process(struct process *proc)
} }
profile_dealloc_proc_events(proc); profile_dealloc_proc_events(proc);
#endif // PROFILE_ENABLE #endif // PROFILE_ENABLE
free_thread_pages(proc->main_thread);
kfree(proc); kfree(proc);
} }
@ -2574,8 +2594,8 @@ out:
int hold_thread(struct thread *thread) int hold_thread(struct thread *thread)
{ {
if (thread->status == PS_EXITED) { if (thread->status == PS_EXITED) {
kprintf("hold_thread: ERROR: already exited process,tid=%d\n", thread->tid); kprintf("hold_thread: WARNING: already exited process,tid=%d\n",
return -ESRCH; thread->tid);
} }
ihk_atomic_inc(&thread->refcount); ihk_atomic_inc(&thread->refcount);
@ -2657,17 +2677,16 @@ void destroy_thread(struct thread *thread)
ts_add(&thread->proc->stime, &ats); ts_add(&thread->proc->stime, &ats);
tsc_to_ts(thread->user_tsc, &ats); tsc_to_ts(thread->user_tsc, &ats);
ts_add(&thread->proc->utime, &ats); ts_add(&thread->proc->utime, &ats);
mcs_rwlock_writer_unlock(&proc->update_lock, &updatelock);
mcs_rwlock_writer_lock(&proc->threads_lock, &lock); mcs_rwlock_writer_lock(&proc->threads_lock, &lock);
list_del(&thread->siblings_list); list_del(&thread->siblings_list);
if (thread->uti_state == UTI_STATE_EPILOGUE) { if (thread->uti_state == UTI_STATE_EPILOGUE) {
__find_and_replace_tid(proc, thread, thread->uti_refill_tid); __find_and_replace_tid(proc, thread, thread->uti_refill_tid);
} else { }
else if (thread != proc->main_thread) {
__release_tid(proc, thread); __release_tid(proc, thread);
} }
mcs_rwlock_writer_unlock(&proc->threads_lock, &lock);
mcs_rwlock_writer_unlock(&proc->update_lock, &updatelock);
cpu_clear(thread->cpu_id, &thread->vm->address_space->cpu_set, cpu_clear(thread->cpu_id, &thread->vm->address_space->cpu_set,
&thread->vm->address_space->cpu_set_lock); &thread->vm->address_space->cpu_set_lock);
@ -2691,7 +2710,9 @@ void destroy_thread(struct thread *thread)
release_sigcommon(thread->sigcommon); release_sigcommon(thread->sigcommon);
ihk_mc_free_pages(thread, KERNEL_STACK_NR_PAGES); if (thread != proc->main_thread)
free_thread_pages(thread);
mcs_rwlock_writer_unlock(&proc->threads_lock, &lock);
} }
void release_thread(struct thread *thread) void release_thread(struct thread *thread)
@ -2713,20 +2734,6 @@ void release_thread(struct thread *thread)
destroy_thread(thread); destroy_thread(thread);
release_process_vm(vm); release_process_vm(vm);
rusage_num_threads_dec();
#ifdef RUSAGE_DEBUG
if (rusage->num_threads == 0) {
int i;
kprintf("total_memory_usage=%ld\n", rusage->total_memory_usage);
for(i = 0; i < IHK_MAX_NUM_PGSIZES; i++) {
kprintf("memory_stat_rss[%d]=%ld\n", i, rusage->memory_stat_rss[i]);
}
for(i = 0; i < IHK_MAX_NUM_PGSIZES; i++) {
kprintf("memory_stat_mapped_file[%d]=%ld\n", i, rusage->memory_stat_mapped_file[i]);
}
}
#endif
} }
void cpu_set(int cpu, cpu_set_t *cpu_set, ihk_spinlock_t *lock) void cpu_set(int cpu, cpu_set_t *cpu_set, ihk_spinlock_t *lock)
@ -3287,6 +3294,25 @@ void schedule(void)
if ((last != NULL) && (last->status == PS_EXITED)) { if ((last != NULL) && (last->status == PS_EXITED)) {
release_thread(last); release_thread(last);
rusage_num_threads_dec();
#ifdef RUSAGE_DEBUG
if (rusage->num_threads == 0) {
int i;
kprintf("total_memory_usage=%ld\n",
rusage->total_memory_usage);
for (i = 0; i < IHK_MAX_NUM_PGSIZES; i++) {
kprintf("memory_stat_rss[%d]=%ld\n", i,
rusage->memory_stat_rss[i]);
}
for (i = 0; i < IHK_MAX_NUM_PGSIZES; i++) {
kprintf(
"memory_stat_mapped_file[%d]=%ld\n",
i,
rusage->memory_stat_mapped_file[i]);
}
}
#endif
} }
/* Have we migrated to another core meanwhile? */ /* Have we migrated to another core meanwhile? */
@ -3535,22 +3561,26 @@ void runq_del_thread(struct thread *thread, int cpu_id)
} }
struct thread * struct thread *
find_thread(int pid, int tid, struct mcs_rwlock_node_irqsave *lock) find_thread(int pid, int tid)
{ {
struct thread *thread; struct thread *thread;
struct thread_hash *thash = cpu_local_var(resource_set)->thread_hash; struct thread_hash *thash = cpu_local_var(resource_set)->thread_hash;
int hash = thread_hash(tid); int hash = thread_hash(tid);
struct mcs_rwlock_node_irqsave lock;
if(tid <= 0) if(tid <= 0)
return NULL; return NULL;
mcs_rwlock_reader_lock(&thash->lock[hash], lock); mcs_rwlock_reader_lock(&thash->lock[hash], &lock);
retry: retry:
list_for_each_entry(thread, &thash->list[hash], hash_list){ list_for_each_entry(thread, &thash->list[hash], hash_list){
if(thread->tid == tid){ if(thread->tid == tid){
if(pid <= 0) if (pid <= 0 ||
return thread; thread->proc->pid == pid) {
if(thread->proc->pid == pid) hold_thread(thread);
mcs_rwlock_reader_unlock(&thash->lock[hash],
&lock);
return thread; return thread;
}
} }
} }
/* If no thread with pid == tid was found, then we may be looking for a /* If no thread with pid == tid was found, then we may be looking for a
@ -3560,20 +3590,16 @@ retry:
pid = 0; pid = 0;
goto retry; goto retry;
} }
mcs_rwlock_reader_unlock(&thash->lock[hash], lock); mcs_rwlock_reader_unlock(&thash->lock[hash], &lock);
return NULL; return NULL;
} }
void void
thread_unlock(struct thread *thread, struct mcs_rwlock_node_irqsave *lock) thread_unlock(struct thread *thread)
{ {
struct thread_hash *thash = cpu_local_var(resource_set)->thread_hash;
int hash;
if(!thread) if(!thread)
return; return;
hash = thread_hash(thread->tid); release_thread(thread);
mcs_rwlock_reader_unlock(&thash->lock[hash], lock);
} }
struct process * struct process *
@ -3628,8 +3654,9 @@ debug_log(unsigned long arg)
if (p == pid1) if (p == pid1)
continue; continue;
found++; found++;
kprintf("pid=%d ppid=%d status=%d\n", kprintf("pid=%d ppid=%d status=%d ref=%d\n",
p->pid, p->ppid_parent->pid, p->status); p->pid, p->ppid_parent->pid, p->status,
p->refcount.counter);
} }
__mcs_rwlock_reader_unlock(&phash->lock[i], &lock); __mcs_rwlock_reader_unlock(&phash->lock[i], &lock);
} }
@ -3640,9 +3667,11 @@ debug_log(unsigned long arg)
__mcs_rwlock_reader_lock(&thash->lock[i], &lock); __mcs_rwlock_reader_lock(&thash->lock[i], &lock);
list_for_each_entry(t, &thash->list[i], hash_list){ list_for_each_entry(t, &thash->list[i], hash_list){
found++; found++;
kprintf("cpu=%d pid=%d tid=%d status=%d offload=%d\n", kprintf("cpu=%d pid=%d tid=%d status=%d "
t->cpu_id, t->proc->pid, t->tid, "offload=%d ref=%d ptrace=%08x\n",
t->status, t->in_syscall_offload); t->cpu_id, t->proc->pid, t->tid,
t->status, t->in_syscall_offload,
t->refcount.counter, t->ptrace);
} }
__mcs_rwlock_reader_unlock(&thash->lock[i], &lock); __mcs_rwlock_reader_unlock(&thash->lock[i], &lock);
} }

File diff suppressed because it is too large Load Diff

117
test/issues/771+1179+1143/C771.sh Executable file
View File

@ -0,0 +1,117 @@
#!/bin/sh
USELTP=1
USEOSTEST=1
GDBBUILDDIR="$HOME/rpmbuild/BUILD/gdb-7.6.1/build-x86_64-redhat-linux-gnu"
. ../../common.sh
#===============================================================================
expect -c "
set timeout 60
spawn "$MCEXEC" gdb ./C771T001
expect \"(gdb)\"
send -- \"b thr\n\"
expect \"(gdb)\"
send -- \"r\n\"
expect \"(gdb)\"
send -- \"info threads\n\"
expect \"(gdb)\"
send -- \"bt\n\"
expect \"(gdb)\"
send -- \"n\n\"
expect \"(gdb)\"
send -- \"thread 1\n\"
expect \"(gdb)\"
send -- \"bt\n\"
expect \"(gdb)\"
send -- \"thread 2\n\"
expect \"(gdb)\"
send -- \"c\n\"
expect \"(gdb)\"
send -- \"q\n\"
expect eof
" | tee C771T001.txt
echo checking result...
awk -f C771T001.awk C771T001.txt
rm -f C771T001.txt
sleep 5
"$SBIN"/ihkosctl 0 clear_kmsg
"$SBIN"/ihkosctl 0 ioctl 40000000 1
"$SBIN"/ihkosctl 0 ioctl 40000000 2
"$SBIN"/ihkosctl 0 kmsg | tee C771T012.txt
if grep ' 0 processes are found' C771T012.txt > /dev/null 2>&1 && \
grep ' 0 threads are found' C771T012.txt > /dev/null 2>&1; then
echo "*** C771T012 no processes and threads found OK"
else
echo "*** C771T012 processes and threads are exists NG"
fi
rm -f C771T012.txt
#===============================================================================
if [ -x "$GDBBUILDDIR/gdb/testsuite/gdb.threads/bp_in_thread" ] ;then
if [ -d gdb-result ]; then
rm -rf gdb-result
fi
mkdir -p gdb-result/raw/linux gdb-result/raw/mck
mkdir -p gdb-result/linux gdb-result/mck
export gdb_builddir="$GDBBUILDDIR"
export MCEXEC
id=13
while read line; do
cat=`echo $line | awk '{print $1}'`
exp=`echo $line | awk '{print $2}'`
./gdb_test.sh $cat $exp 2>&1 | tee $cat-$exp.txt
if grep "【PASS】" $cat-$exp.txt > /dev/null 2>&1; then
echo "*** C771T0$id: $cat-$exp OK"
else
echo "*** C771T0$id: $cat-$exp NG"
fi
rm -f $cat-$exp.txt
id=`expr $id + 1`
done < gdblist
else
echo '***' No GDB build dir. skip GDB tests >&2
fi
#===============================================================================
$MCEXEC ./C771T033
#===============================================================================
$MCEXEC "$TESTMCK" -s ptrace -n 19 | tee C771T036.txt
if grep "RESULT: ok" C771T036.txt > /dev/null 2>&1; then
echo "*** C771T036: ostest-ptrace-19 OK"
else
echo "*** C771T036: ostest-ptrace-19 NG"
fi
rm -f C771T036.txt
#===============================================================================
$MCEXEC ./C771T037
#===============================================================================
id=43
while read tp; do
sudo $MCEXEC $LTPBIN/$tp 2>&1 | tee $tp.txt
ok=`grep TPASS $tp.txt | wc -l`
ng=`grep TFAIL $tp.txt | wc -l`
if [ $ng = 0 ]; then
echo "*** C771T0$id: $tp OK ($ok)"
else
echo "*** C771T0$id: $tp NG (ok=$ok ng=$ng)"
fi
rm -f $tp.txt
id=`expr $id + 1`
done < ltplist

View File

@ -0,0 +1,627 @@
Script started on Mon Sep 24 08:49:43 2018
bash-4.2$ make test
gcc -g -Wall -o C771T001 C771T001.c -pthread
gcc -g -Wall -o C771T033 C771T033.c -pthread
gcc -g -Wall -o C771T037 C771T037.c -pthread
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
spawn /home/shirasawa/wallaby11-smp-x86/issue771/mic/bin/mcexec gdb ./C771T001
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-94.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/shirasawa/wallaby11-smp-x86/issue771/mckernel/test/issues/771+1179+1143/C771T001...done.
(gdb) b thr
Breakpoint 1 at 0x400989: file C771T001.c, line 20.
(gdb) r
Starting program: /home/shirasawa/wallaby11-smp-x86/issue771/mckernel/test/issues/771+1179+1143/./C771T001
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
process start pid=5721
[New Thread 0x2aaaad000700 (LWP 5750)]
pthread_create: 0
[Switching to Thread 0x2aaaad000700 (LWP 5750)]
Breakpoint 1, thr (arg=0x0) at C771T001.c:20
20 fprintf(stderr, "thread start tid=%d\n", (int)syscall(SYS_gettid));
Missing separate debuginfos, use: debuginfo-install glibc-2.17-222.el7.x86_64 libgcc-4.8.5-28.el7_5.1.x86_64 libgfortran-4.8.5-28.el7_5.1.x86_64 libquadmath-4.8.5-28.el7_5.1.x86_64 mpich-3.2-3.2-2.el7.x86_64
(gdb) info threads
Id Target Id Frame
* 2 Thread 0x2aaaad000700 (LWP 5750) "exe" thr (arg=0x0) at C771T001.c:20
1 Thread 0x2aaaac735e80 (LWP 5721) "exe" 0x0000000000400b61 in main (
argc=1, argv=0x547ffffffd08) at C771T001.c:52
(gdb) bt
#0 thr (arg=0x0) at C771T001.c:20
#1 0x00002aaaaae49e25 in start_thread () from /lib64/libpthread.so.0
#2 0x00002aaaab15cbad in clone () from /lib64/libc.so.6
(gdb) n
thread start tid=5750
21 fflush(stderr);
(gdb) thread 1
[Switching to thread 1 (Thread 0x2aaaac735e80 (LWP 5721))]
#0 0x0000000000400b61 in main (argc=1, argv=0x547ffffffd08) at C771T001.c:52
52 while (!m);
(gdb) bt
#0 0x0000000000400b61 in main (argc=1, argv=0x547ffffffd08) at C771T001.c:52
(gdb) thread 2
[Switching to thread 2 (Thread 0x2aaaad000700 (LWP 5750))]
#0 thr (arg=0x0) at C771T001.c:21
21 fflush(stderr);
(gdb) c
Continuing.
mmap m=0x2aaaad001000 errno=0
update m=0x2aaaad001000
update *m=1
munmap rc=0, errno=0
main done
[Thread 0x2aaaad000700 (LWP 5750) exited]
[Inferior 1 (process 5721) exited normally]
(gdb) q
checking result...
*** C771T001 gdb start OK
*** C771T002 breakpoint command OK
*** C771T003 run command OK
*** C771T004 info threads command OK
*** C771T005 backtrace command OK
*** C771T006 next command OK
*** C771T007 thread command OK
*** C771T008 thread command OK
*** C771T009 thread command OK
*** C771T010 continue command OK
*** C771T011 quit command OK
OK=11 NG=0
[ 0]: 0 processes are found.
[ 0]: 0 threads are found.
*** C771T012 no processes and threads found OK
======== a2-run ========
【SAME】a2-run: Summary.
【SAME】a2-run : Log.
【PASS】a2-run
*** C771T013: base-a2-run OK
======== foll-fork ========
【SAME】foll-fork: Summary.
【SAME】foll-fork : Log.
【PASS】foll-fork
*** C771T014: base-foll-fork OK
======== fork-detach ========
【SAME】fork-detach: Summary.
【SAME】fork-detach : Log.
【PASS】fork-detach
*** C771T015: base-fork-detach OK
======== atomic-seq-threaded ========
【DIFF】atomic-seq-threaded : Summary Difference ---
--- /home/shirasawa/wallaby11-smp-x86/issue771/mckernel/test/issues/771+1179+1143/gdb-result/linux/atomic-seq-threaded.sum 2018-09-24 08:52:39.889889082 +0900
+++ /home/shirasawa/wallaby11-smp-x86/issue771/mckernel/test/issues/771+1179+1143/gdb-result/mck/atomic-seq-threaded.sum 2018-09-24 08:52:39.899889116 +0900
@@ -11,5 +11,5 @@
=== gdb Summary ===
# of unsupported tests 2
-/home/shirasawa/rpmbuild/BUILD/gdb-7.6.1/build-x86_64-redhat-linux-gnu/gdb/testsuite/../../gdb/gdb version 7.6.1-110.el7.centos -nw -nx -data-directory /home/shirasawa/rpmbuild/BUILD/gdb-7.6.1/build-x86_64-redhat-linux-gnu/gdb/testsuite/../data-directory
+/home/shirasawa/wallaby11-smp-x86/issue771/mckernel/test/issues/771+1179+1143/mcexec_gdb.sh version 7.6.1-94.el7 -nw -nx -data-directory /home/shirasawa/rpmbuild/BUILD/gdb-7.6.1/build-x86_64-redhat-linux-gnu/gdb/testsuite/../data-directory
【SAME】atomic-seq-threaded : Log.
【PASS】atomic-seq-threaded
*** C771T016: threads-atomic-seq-threaded OK
======== bp_in_thread ========
【SAME】bp_in_thread: Summary.
【SAME】bp_in_thread : Log.
【PASS】bp_in_thread
*** C771T017: threads-bp_in_thread OK
======== bt-clone-stop ========
【SAME】bt-clone-stop: Summary.
【SAME】bt-clone-stop : Log.
【PASS】bt-clone-stop
*** C771T018: threads-bt-clone-stop OK
======== corethreads ========
【SAME】corethreads: Summary.
【SAME】corethreads : Log.
【PASS】corethreads
*** C771T019: threads-corethreads OK
======== dlopen-libpthread ========
【SAME】dlopen-libpthread: Summary.
【SAME】dlopen-libpthread : Log.
【PASS】dlopen-libpthread
*** C771T020: threads-dlopen-libpthread OK
======== fork-child-threads ========
【SAME】fork-child-threads: Summary.
【SAME】fork-child-threads : Log.
【PASS】fork-child-threads
*** C771T021: threads-fork-child-threads OK
======== killed ========
【SAME】killed: Summary.
【SAME】killed : Log.
【PASS】killed
*** C771T022: threads-killed OK
======== pthread_cond_wait ========
【SAME】pthread_cond_wait: Summary.
【SAME】pthread_cond_wait : Log.
【PASS】pthread_cond_wait
*** C771T023: threads-pthread_cond_wait OK
======== switch-threads ========
【SAME】switch-threads: Summary.
【SAME】switch-threads : Log.
【PASS】switch-threads
*** C771T024: threads-switch-threads OK
======== thread-specific ========
【SAME】thread-specific: Summary.
【SAME】thread-specific : Log.
【PASS】thread-specific
*** C771T025: threads-thread-specific OK
======== thread_check ========
【SAME】thread_check: Summary.
【DIFF】thread_check : Log Difference ---
--- /home/shirasawa/wallaby11-smp-x86/issue771/mckernel/test/issues/771+1179+1143/gdb-result/linux/thread_check.log 2018-09-24 09:00:11.257427754 +0900
+++ /home/shirasawa/wallaby11-smp-x86/issue771/mckernel/test/issues/771+1179+1143/gdb-result/mck/thread_check.log 2018-09-24 09:00:11.270427798 +0900
@@ -13,4 +13,4 @@
(gdb) PASS: gdb.threads/thread_check.exp: continue to tf
(gdb) PASS: gdb.threads/thread_check.exp: backtrace from thread function
(gdb) info breakpoints
-(gdb) Quitting /home/shirasawa/rpmbuild/BUILD/gdb-7.6.1/build-x86_64-redhat-linux-gnu/gdb/testsuite/../../gdb/gdb -nw -nx -data-directory /home/shirasawa/rpmbuild/BUILD/gdb-7.6.1/build-x86_64-redhat-linux-gnu/gdb/testsuite/../data-directory
+(gdb) Quitting mcexec_gdb.sh -nw -nx -data-directory /home/shirasawa/rpmbuild/BUILD/gdb-7.6.1/build-x86_64-redhat-linux-gnu/gdb/testsuite/../data-directory
【PASS】thread_check
*** C771T026: threads-thread_check OK
======== thread_events ========
【SAME】thread_events: Summary.
【DIFF】thread_events : Log Difference ---
--- /home/shirasawa/wallaby11-smp-x86/issue771/mckernel/test/issues/771+1179+1143/gdb-result/linux/thread_events.log 2018-09-24 09:01:01.132598675 +0900
+++ /home/shirasawa/wallaby11-smp-x86/issue771/mckernel/test/issues/771+1179+1143/gdb-result/mck/thread_events.log 2018-09-24 09:01:01.141598706 +0900
@@ -15,7 +15,7 @@
(gdb) PASS: gdb.threads/thread_events.exp: continue to threadfunc with messages disabled
(gdb) PASS: gdb.threads/thread_events.exp: continue to after_join_func with messages disabled
(gdb) info breakpoints
-(gdb) Quitting /home/shirasawa/rpmbuild/BUILD/gdb-7.6.1/build-x86_64-redhat-linux-gnu/gdb/testsuite/../../gdb/gdb -nw -nx -data-directory /home/shirasawa/rpmbuild/BUILD/gdb-7.6.1/build-x86_64-redhat-linux-gnu/gdb/testsuite/../data-directory
+(gdb) Quitting mcexec_gdb.sh -nw -nx -data-directory /home/shirasawa/rpmbuild/BUILD/gdb-7.6.1/build-x86_64-redhat-linux-gnu/gdb/testsuite/../data-directory
(gdb) GDB initialized.
(gdb) set width 0
(gdb) set build-id-verbose 0
@@ -33,4 +33,4 @@
(gdb) PASS: gdb.threads/thread_events.exp: continue to threadfunc with messages enabled
(gdb) PASS: gdb.threads/thread_events.exp: continue to after_join_func with messages enabled
(gdb) info breakpoints
-(gdb) Quitting /home/shirasawa/rpmbuild/BUILD/gdb-7.6.1/build-x86_64-redhat-linux-gnu/gdb/testsuite/../../gdb/gdb -nw -nx -data-directory /home/shirasawa/rpmbuild/BUILD/gdb-7.6.1/build-x86_64-redhat-linux-gnu/gdb/testsuite/../data-directory
+(gdb) Quitting mcexec_gdb.sh -nw -nx -data-directory /home/shirasawa/rpmbuild/BUILD/gdb-7.6.1/build-x86_64-redhat-linux-gnu/gdb/testsuite/../data-directory
【PASS】thread_events
*** C771T027: threads-thread_events OK
======== threaded-exec ========
【SAME】threaded-exec: Summary.
【SAME】threaded-exec : Log.
【PASS】threaded-exec
*** C771T028: threads-threaded-exec OK
======== threxit-hop-specific ========
【SAME】threxit-hop-specific: Summary.
【SAME】threxit-hop-specific : Log.
【PASS】threxit-hop-specific
*** C771T029: threads-threxit-hop-specific OK
======== tls-nodebug ========
【SAME】tls-nodebug: Summary.
【SAME】tls-nodebug : Log.
【PASS】tls-nodebug
*** C771T030: threads-tls-nodebug OK
======== tls-sepdebug ========
【SAME】tls-sepdebug: Summary.
【SAME】tls-sepdebug : Log.
【PASS】tls-sepdebug
*** C771T031: threads-tls-sepdebug OK
======== tls-var ========
【SAME】tls-var: Summary.
【SAME】tls-var : Log.
【PASS】tls-var
*** C771T032: threads-tls-var OK
tid=23026
*** C771T033 *** ATTACH OK
*** C771T034 *** SYSCALL OK
syscall enter n=9
*** C771T034 *** SYSCALL OK
syscall return n=9 r=46912535269376
*** C771T035 DETACH OK
mmap m=0x2aaaad001000 errno=0
update m=0x2aaaad001000
update *m=1
munmap rc=0, errno=0
main done
TEST_SUITE: ptrace
TEST_NUMBER: 19
ARGS:
TEST_SUITE: ptrace
TEST_NUMBER: 19
ARGS:
child is stopped.
RESULT: ok
*** C771T036: ostest-ptrace-19 OK
pid=23121
tid=23151
*** C771T037 wait4(pid) OK
*** C771T038 wait4(tid) OK
*** C771T039 wait4(pid, __WCLONE) OK
*** C771T040 wait4(tid, __WCLONE) OK
*** C771T041 wait4(pid, __WALL) OK
*** C771T042 wait4(tid, __WALL) OK
clone01 1 TPASS : clone returned 23215
*** C771T043: clone01 OK (1)
clone03 1 TPASS : Test passed
*** C771T044: clone03 OK (1)
clone04 1 TPASS : expected failure; Got EINVAL
*** C771T045: clone04 OK (1)
clone06 1 TPASS : Test Passed
*** C771T046: clone06 OK (1)
clone07 1 TPASS : Use of return() in child did not cause SIGSEGV
*** C771T047: clone07 OK (1)
exit01 1 TPASS : exit() test PASSED
*** C771T048: exit01 OK (1)
exit02 1 TPASS : exit() test PASSED
*** C771T049: exit02 OK (1)
exit_group01 1 TPASS : exit_group() succeeded
*** C771T050: exit_group01 OK (1)
fork01 1 TPASS : fork() returned 23754
fork01 2 TPASS : child pid and fork() return agree: 23754
*** C771T051: fork01 OK (2)
fork02 0 TINFO : Inside parent
fork02 0 TINFO : Inside child
fork02 0 TINFO : exit status of wait 0
fork02 1 TPASS : test 1 PASSED
*** C771T052: fork02 OK (1)
fork03 0 TINFO : process id in parent of child from fork : 23896
fork03 1 TPASS : test 1 PASSED
*** C771T053: fork03 OK (1)
fork04 1 TPASS : Env var TERM unchanged after fork(): xterm
fork04 2 TPASS : Env var NoTSetzWq unchanged after fork(): getenv() does not find variable set
fork04 3 TPASS : Env var TESTPROG unchanged after fork(): FRKTCS04
*** C771T054: fork04 OK (3)
fork07 0 TINFO : Forking 100 children
fork07 0 TINFO : Forked all 100 children, now collecting
fork07 0 TINFO : Collected all 100 children
fork07 1 TPASS : 100/100 children read correctly from an inheritted fd
*** C771T055: fork07 OK (1)
fork08 0 TINFO : parent forksval: 1
fork08 0 TINFO : parent forksval: 2
fork08 0 TINFO : second child got char: b
fork08 1 TPASS : Test passed in childnumber 2
fork08 0 TINFO : exit status of wait expected 0 got 0
fork08 1 TPASS : parent test PASSED
fork08 0 TINFO : exit status of wait expected 0 got 0
fork08 2 TPASS : parent test PASSED
fork08 0 TINFO : exit status of wait expected 0 got 0
fork08 3 TPASS : parent test PASSED
fork08 0 TINFO : Number of processes forked is 2
*** C771T056: fork08 OK (4)
fork09 0 TINFO : OPEN_MAX is 1024
fork09 0 TINFO : first file descriptor is 12
fork09 0 TINFO : Parent reporting 1023 files open
fork09 0 TINFO : Child opened new file #1023
fork09 1 TPASS : test 1 PASSED
*** C771T057: fork09 OK (1)
fork10 0 TINFO : fork child A
fork10 1 TPASS : test 1 PASSED
*** C771T058: fork10 OK (1)
fork11 1 TPASS : fork test passed, 100 processes
*** C771T059: fork11 OK (1)
kill01 1 TPASS : received expected signal 9
*** C771T060: kill01 OK (1)
kill02 1 TPASS : The signal was sent to all processes in the process group.
kill02 2 TPASS : The signal was not sent to selective processes that were not in the process group.
*** C771T061: kill02 OK (2)
kill03 1 TPASS : errno set to 22 : Invalid argument, as expected
*** C771T062: kill03 OK (1)
kill04 1 TPASS : errno set to 3 : No such process, as expected
*** C771T063: kill04 OK (1)
kill failed with EPERM
kill05 1 TPASS : received expected errno(EPERM)
*** C771T064: kill05 OK (1)
kill06 1 TPASS : received expected signal 9
*** C771T065: kill06 OK (1)
kill07 0 TINFO : received expected signal 9
kill07 1 TPASS : Did not catch signal as expected
*** C771T066: kill07 OK (1)
kill08 1 TPASS : received expected signal 9
*** C771T067: kill08 OK (1)
kill09 1 TPASS : kill(31358, SIGKILL) returned 0
*** C771T068: kill09 OK (1)
kill10 1 TPASS : All 2 pgrps received their signals
31429: All 10 children reported in
31460: All 10 children reported in
*** C771T069: kill10 OK (1)
kill11 1 TPASS : signal SIGHUP
kill11 2 TPASS : signal SIGINT
kill11 3 TPASS : signal SIGQUIT dumped core
kill11 4 TPASS : signal SIGILL dumped core
kill11 5 TPASS : signal SIGTRAP dumped core
kill11 6 TPASS : signal SIGIOT/SIGABRT dumped core
kill11 7 TPASS : signal SIGIOT/SIGABRT dumped core
kill11 8 TPASS : signal SIGBUS dumped core
kill11 9 TPASS : signal SIGFPE dumped core
kill11 10 TPASS : signal SIGKILL
kill11 11 TPASS : signal SIGUSR1
kill11 12 TPASS : signal SIGSEGV dumped core
kill11 13 TPASS : signal SIGUSR2
kill11 14 TPASS : signal SIGPIPE
kill11 15 TPASS : signal SIGALRM
kill11 16 TPASS : signal SIGTERM
kill11 17 TPASS : signal SIGXCPU dumped core
kill11 18 TPASS : signal SIGXFSZ dumped core
kill11 19 TPASS : signal SIGVTALRM
kill11 20 TPASS : signal SIGPROF
kill11 21 TPASS : signal SIGIO/SIGPOLL
kill11 22 TPASS : signal SIGPWR
kill11 23 TPASS : signal SIGSYS/SIGUNUSED dumped core
*** C771T070: kill11 OK (23)
kill12 1 TPASS : Test passed
*** C771T071: kill12 OK (1)
ptrace01 1 TPASS : Test Passed
ptrace01 2 TPASS : Test Passed
*** C771T072: ptrace01 OK (2)
ptrace02 1 TPASS : Test Passed
ptrace02 2 TPASS : Test Passed
*** C771T073: ptrace02 OK (2)
ptrace03 1 TCONF : ptrace03.c:137: this kernel allows to trace init
ptrace03 2 TPASS : Test Passed
ptrace03 3 TPASS : Test Passed
*** C771T074: ptrace03 OK (2)
ptrace05 0 TINFO : [child] Sending kill(.., 0)
ptrace05 1 TPASS : kill(.., 0) exited with 0, as expected.
ptrace05 0 TINFO : [child] Sending kill(.., 1)
ptrace05 2 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 2)
ptrace05 3 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 3)
ptrace05 4 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 4)
ptrace05 5 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 5)
ptrace05 6 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 6)
ptrace05 7 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 7)
ptrace05 8 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 8)
ptrace05 9 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 9)
ptrace05 10 TPASS : Killed with SIGKILL, as expected.
ptrace05 0 TINFO : [child] Sending kill(.., 10)
ptrace05 11 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 11)
ptrace05 12 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 12)
ptrace05 13 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 13)
ptrace05 14 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 14)
ptrace05 15 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 15)
ptrace05 16 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 16)
ptrace05 17 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 17)
ptrace05 18 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 18)
ptrace05 19 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 19)
ptrace05 20 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 20)
ptrace05 21 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 21)
ptrace05 22 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 22)
ptrace05 23 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 23)
ptrace05 24 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 24)
ptrace05 25 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 25)
ptrace05 26 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 26)
ptrace05 27 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 27)
ptrace05 28 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 28)
ptrace05 29 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 29)
ptrace05 30 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 30)
ptrace05 31 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 31)
ptrace05 32 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 32)
ptrace05 33 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 33)
ptrace05 34 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 34)
ptrace05 35 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 35)
ptrace05 36 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 36)
ptrace05 37 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 37)
ptrace05 38 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 38)
ptrace05 39 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 39)
ptrace05 40 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 40)
ptrace05 41 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 41)
ptrace05 42 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 42)
ptrace05 43 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 43)
ptrace05 44 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 44)
ptrace05 45 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 45)
ptrace05 46 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 46)
ptrace05 47 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 47)
ptrace05 48 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 48)
ptrace05 49 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 49)
ptrace05 50 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 50)
ptrace05 51 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 51)
ptrace05 52 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 52)
ptrace05 53 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 53)
ptrace05 54 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 54)
ptrace05 55 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 55)
ptrace05 56 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 56)
ptrace05 57 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 57)
ptrace05 58 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 58)
ptrace05 59 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 59)
ptrace05 60 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 60)
ptrace05 61 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 61)
ptrace05 62 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 62)
ptrace05 63 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 63)
ptrace05 64 TPASS : Stopped as expected
ptrace05 0 TINFO : [child] Sending kill(.., 64)
ptrace05 65 TPASS : Stopped as expected
*** C771T075: ptrace05 OK (65)
wait02 1 TPASS : wait(&status) returned 3201
*** C771T076: wait02 OK (1)
wait401 1 TPASS : Received child pid as expected.
wait401 2 TPASS : wait401 call succeeded
*** C771T077: wait401 OK (2)
wait402 1 TPASS : received expected failure - errno = 10 - No child processes
*** C771T078: wait402 OK (1)
waitid01 0 TINFO : Process 3384 terminated:
waitid01 0 TINFO : code = 1
waitid01 0 TINFO : exit value = 31488
waitid01 0 TINFO : Process 3414 terminated:
waitid01 0 TINFO : code = 1
waitid01 0 TINFO : exit value = 0
waitid01 0 TINFO : Process 3444 terminated:
waitid01 0 TINFO : code = 2
waitid01 0 TINFO : signal = 1
waitid01 0 TINFO : Process 3474 terminated:
waitid01 0 TINFO : code = 1
waitid01 0 TINFO : exit value = 31488
waitid01 0 TINFO : Process 3504 terminated:
waitid01 0 TINFO : code = 1
waitid01 0 TINFO : exit value = 0
waitid01 0 TINFO : Process 3534 terminated:
waitid01 0 TINFO : code = 2
waitid01 0 TINFO : signal = 1
waitid01 0 TINFO : Process 3564 terminated:
waitid01 0 TINFO : code = 1
waitid01 0 TINFO : exit value = 31488
waitid01 0 TINFO : Process 3594 terminated:
waitid01 0 TINFO : code = 1
waitid01 0 TINFO : exit value = 0
waitid01 0 TINFO : Process 3624 terminated:
waitid01 0 TINFO : code = 2
waitid01 0 TINFO : signal = 1
waitid01 1 TPASS : waitid(): system call passed
*** C771T079: waitid01 OK (1)
waitid02 0 TINFO : WNOHANG
waitid02 0 TINFO : (3664) waitid(0, 0, 0x547ffffffcf0, 1)
waitid02 1 TPASS : exp_errno=22
waitid02 0 TINFO : si_pid = 0 ; si_code = 0 ; si_status = 0
waitid02 0 TINFO : WNOHANG | WEXITED no child
waitid02 0 TINFO : (3664) waitid(0, 0, 0x547ffffffcf0, 5)
waitid02 2 TPASS : exp_errno=10
waitid02 0 TINFO : si_pid = 0 ; si_code = 0 ; si_status = 0
waitid02 0 TINFO : WNOHANG | WEXITED with child
waitid02 0 TINFO : (3664) waitid(0, 0, 0x547ffffffcf0, 5)
waitid02 3 TPASS : ret: 0
waitid02 0 TINFO : si_pid = 0 ; si_code = 0 ; si_status = 0
waitid02 0 TINFO : P_PGID, WEXITED wait for child
waitid02 0 TINFO : (3664) waitid(2, 5365, 0x547ffffffcf0, 4)
waitid02 4 TPASS : ret: 0
waitid02 0 TINFO : si_pid = 3725 ; si_code = 1 ; si_status = 0
waitid02 0 TINFO : P_PID, WEXITED wait for child
waitid02 0 TINFO : (3664) waitid(1, 3755, 0x547ffffffcf0, 4)
waitid02 5 TPASS : ret: 0
waitid02 0 TINFO : si_pid = 3755 ; si_code = 1 ; si_status = 0
waitid02 0 TINFO : P_PID, WSTOPPED | WNOWAIT
waitid02 0 TINFO : (3664) waitid(1, 3785, 0x547ffffffcf0, 16777218)
waitid02 6 TPASS : ret: 0
waitid02 0 TINFO : si_pid = 3785 ; si_code = 5 ; si_status = 4991
waitid02 0 TINFO : P_PID, WCONTINUED
waitid02 0 TINFO : (3664) waitid(1, 3815, 0x547ffffffcf0, 8)
waitid02 7 TPASS : ret: 0
waitid02 0 TINFO : si_pid = 3815 ; si_code = 6 ; si_status = 65535
waitid02 0 TINFO : P_PID, WEXITED not a child of the calling process
waitid02 0 TINFO : (3664) waitid(1, 1, 0x547ffffffcf0, 4)
waitid02 8 TPASS : exp_errno=10
waitid02 0 TINFO : si_pid = 0 ; si_code = 0 ; si_status = 0
*** C771T080: waitid02 OK (8)
waitpid01 1 TPASS : recieved expected pid
waitpid01 2 TPASS : recieved expected signal
*** C771T081: waitpid01 OK (2)
waitpid02 1 TPASS : recieved expected pid
waitpid02 2 TPASS : recieved expected signal
waitpid02 3 TPASS : recieved expected exit value
*** C771T082: waitpid02 OK (3)
waitpid03 1 TPASS : Got correct child PID
waitpid03 2 TPASS : Condition 2 test passed
*** C771T083: waitpid03 OK (2)
waitpid04 1 TPASS : condition 1 test passed
waitpid04 2 TPASS : condition 2 test passed
waitpid04 3 TPASS : condition 3 test passed
*** C771T084: waitpid04 OK (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.
*** C771T085: waitpid05 OK (24)
waitpid06 1 TPASS : waitpid06 PASSED
*** C771T086: waitpid06 OK (1)
waitpid07 1 TPASS : waitpid07 PASSED
*** C771T087: waitpid07 OK (1)
waitpid08 1 TPASS : waitpid08 PASSED
*** C771T088: waitpid08 OK (1)
waitpid09 1 TPASS : case 1 PASSED
waitpid09 2 TPASS : case 2 PASSED
*** C771T089: waitpid09 OK (2)
waitpid10 1 TPASS : Test PASSED
*** C771T090: waitpid10 OK (1)
waitpid11 1 TPASS : Test PASSED
waitpid11 1 TPASS : waitpid11 PASSED
*** C771T091: waitpid11 OK (2)
waitpid12 1 TPASS : Test PASSED
waitpid12 1 TPASS : waitpid12 PASSED
*** C771T092: waitpid12 OK (2)
waitpid13 1 TPASS : Test PASSED
waitpid13 1 TPASS : waitpid13 PASSED
*** C771T093: waitpid13 OK (2)
bash-4.2$ exit
exit
Script done on Mon Sep 24 09:07:34 2018

View File

@ -0,0 +1,176 @@
#! /usr/bin/awk -f
BEGIN{
ok = 0
ng = 0
}
/^\(gdb\) b thr/{
print "*** C771T001 gdb start OK"
ok++
st = 2
next
}
/^\(gdb\) r/{
st = 3
next
}
/^\(gdb\) info threads/{
st = 4
next
}
/^\(gdb\) bt/{
st = (bt == 0) ? 5 : 8
bt++
next
}
/^\(gdb\) n/{
st = 6
next
}
/^\(gdb\) thread 1/{
st = 7
next
}
/^\(gdb\) thread 2/{
if (st != 0) {
printf("*** C771T%03d backtrace command NG\n", st)
ng++
}
st = 9
next
}
/^\(gdb\) c/{
st = 10
next
}
/^\(gdb\) q/{
st = 11
next
}
/^\(gdb\)/ {
printf("*** C771T%03d NG\n", st)
ng++
exit(1)
}
st == 2 {
if ($0 ~/^Breakpoint 1 at/) {
print "*** C771T002 breakpoint command OK"
ok++
}
else {
print "*** C771T002 breakpoint command NG"
ng++
}
st = 0
}
st == 3 {
if ($0 ~/^Starting program/) {
print "*** C771T003 run command OK"
ok++
}
else {
print "*** C771T003 run command NG"
ng++
}
st = 0
}
st == 4 {
if ($0 ~/^ Id /) {
print "*** C771T004 info threads command OK"
ok++
}
else {
print "*** C771T004 info threadsrun command NG"
ng++
}
st = 0
}
st == 5 {
if ($0 ~/^#0 thr/) {
print "*** C771T005 backtrace command OK"
ok++
}
else {
print "*** C771T005 backtrace command NG"
ng++
}
st = 0
}
st == 6 {
if ($0 ~/^thread start tid=/) {
print "*** C771T006 next command OK"
ok++
}
else {
print "*** C771T006 next command NG"
ng++
}
st = 0
}
st == 7 {
if ($0 ~/^\[Switching to thread 1/) {
print "*** C771T007 thread command OK"
ok++
}
else {
print "*** C771T007 thread command NG"
ng++
}
st = 0
}
st == 8 {
if ($0 ~/ in main /) {
print "*** C771T008 thread command OK"
ok++
st = 0
}
}
st == 9 {
if ($0 ~/^\[Switching to thread 2/) {
print "*** C771T009 thread command OK"
ok++
}
else {
print "*** C771T009 thread command NG"
ng++
}
st = 0
}
st == 10 {
if ($0 ~/^Continuing/) {
print "*** C771T010 continue command OK"
ok++
}
else {
print "*** C771T010 continue command NG"
ng++
}
st = 0
}
END{
if (st == 11) {
print "*** C771T011 quit command OK"
ok++
}
print "OK=" ok " NG=" ng
exit(ng > 0 ? 1: 0)
}

View File

@ -0,0 +1,63 @@
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <sys/syscall.h>
#include <sys/mman.h>
volatile char *m;
void *
thr(void *arg)
{
int rc;
char *mm;
fprintf(stderr, "thread start tid=%d\n", (int)syscall(SYS_gettid));
fflush(stderr);
errno = 0;
mm = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
-1, 0);
fprintf(stderr, "mmap m=%p errno=%d\n", mm, errno);
fflush(stderr);
memset(mm, '\0', 4096);
m = mm;
*mm = '1';
while (*m);
rc = munmap(mm, 4096);
fprintf(stderr, "munmap rc=%d, errno=%d\n", rc, errno);
fflush(stderr);
return NULL;
}
int
main(int argc, char **argv)
{
pthread_t th;
int rc;
fprintf(stderr, "process start pid=%d\n", getpid());
fflush(stderr);
rc = pthread_create(&th, NULL, thr, NULL);
if (rc) {
fprintf(stderr, "pthread_create: %d\n", rc);
exit(1);
}
fprintf(stderr, "pthread_create: %d\n", rc);
fflush(stderr);
while (!m);
fprintf(stderr, "update m=%p\n", m);
fflush(stderr);
while (!*m);
fprintf(stderr, "update *m=%c\n", *m);
fflush(stderr);
*m = '\0';
pthread_join(th, NULL);
fprintf(stderr, "main done\n");
fflush(stderr);
exit(0);
}

View File

@ -0,0 +1,175 @@
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <sys/syscall.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/wait.h>
volatile char *m;
volatile int *x;
void *
thr(void *arg)
{
int rc;
pid_t tid;
char *mm;
tid = syscall(SYS_gettid);
*x = tid;
while (*x == tid);
errno = 0;
mm = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
-1, 0);
fprintf(stderr, "mmap m=%p errno=%d\n", mm, errno);
fflush(stderr);
memset(mm, '\0', 4096);
m = mm;
*mm = '1';
while (*m);
rc = munmap(mm, 4096);
fprintf(stderr, "munmap rc=%d, errno=%d\n", rc, errno);
fflush(stderr);
return NULL;
}
int
main(int argc, char **argv)
{
pthread_t th;
int rc;
pid_t tid;
pid_t pid;
int sig;
int st;
x = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS,
-1, 0);
if (x == (void *)-1) {
perror("mmap");
exit(1);
}
*x = 0;
rc = pthread_create(&th, NULL, thr, NULL);
if (rc) {
fprintf(stderr, "pthread_create: %d\n", rc);
exit(1);
}
while (*x == 0);
tid = *x;
fprintf(stderr, "tid=%d\n", tid);
if ((pid = fork()) == 0) {
if (ptrace(PTRACE_ATTACH, tid, 0, 0) == -1) {
fprintf(stderr, "*** C771T033 *** ATTACH NG err=%d\n",
errno);
exit(1);
}
rc = waitpid(-1, &st, __WALL);
if (rc == tid) {
fprintf(stderr, "*** C771T033 *** ATTACH OK\n");
}
else {
fprintf(stderr, "*** C771T033 *** ATTACH NG rc=%d\n",
rc);
exit(1);
}
if (ptrace(PTRACE_SETOPTIONS, tid, 0, PTRACE_O_TRACESYSGOOD) ==
-1) {
fprintf(stderr, "PTRACE_SETOPTIONS errno=%d\n", errno);
exit(1);
}
*x = 0;
sig = 0;
for (;;) {
rc = ptrace(PTRACE_SYSCALL, tid, 0, sig);
if (rc == -1) {
fprintf(stderr,
"*** C771T034 *** SYSCALL NG err=%d\n",
errno);
exit(1);
}
rc = waitpid(-1, &st, __WALL);
if (rc == tid) {
fprintf(stderr,
"*** C771T034 *** SYSCALL OK\n");
}
else {
fprintf(stderr,
"*** C771T034 *** SYSCALL NG rc=%d\n",
rc);
exit(1);
}
if (WIFEXITED(st) || WIFSIGNALED(st)) {
fprintf(stderr, "thread terminated %08x\n", st);
exit(1);
}
if (!WIFSTOPPED(st)) {
fprintf(stderr, "warning: st=%08x\n", st);
continue;
}
if (WSTOPSIG(st) & 0x80) { // syscall
struct user_regs_struct arg;
int num;
long ret;
if (ptrace(PTRACE_GETREGS, tid, NULL, &arg) ==
-1) {
}
num = arg.orig_rax;
ret = arg.rax;
if (ret == -ENOSYS) {
fprintf(stderr,
"syscall enter n=%d\n", num);
}
else {
fprintf(stderr,
"syscall return n=%d r=%ld\n",
num, ret);
if (ptrace(PTRACE_DETACH, tid, NULL,
NULL) == -1) {
fprintf(stderr,
"*** C771T035 DETACH NG"
"err=%d\n", errno);
exit(1);
}
else {
fprintf(stderr,
"*** C771T035 DETACH OK"
"\n");
exit(0);
}
}
}
else { // signal
sig = WSTOPSIG(st) & 0x7f;
}
}
}
while (!m);
fprintf(stderr, "update m=%p\n", m);
fflush(stderr);
while (!*m);
fprintf(stderr, "update *m=%c\n", *m);
fflush(stderr);
*m = '\0';
waitpid(pid, &st, 0);
pthread_join(th, NULL);
fprintf(stderr, "main done\n");
fflush(stderr);
exit(0);
}

View File

@ -0,0 +1,150 @@
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <sys/syscall.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/wait.h>
volatile char *m;
volatile int *x;
void *
thr(void *arg)
{
pid_t tid;
tid = syscall(SYS_gettid);
*x = tid;
while (*x == tid);
return NULL;
}
int
main(int argc, char **argv)
{
pthread_t th;
pid_t tid;
pid_t pid;
int st;
int rc;
x = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS,
-1, 0);
if (x == (void *)-1) {
perror("mmap");
exit(1);
}
*x = 0;
rc = pthread_create(&th, NULL, thr, NULL);
if (rc) {
fprintf(stderr, "pthread_create: %d\n", rc);
exit(1);
}
while (*x == 0);
tid = *x;
fprintf(stderr, "pid=%d\n", getpid());
fprintf(stderr, "tid=%d\n", tid);
if ((pid = fork()) == 0) {
pid = getppid();
if (ptrace(PTRACE_ATTACH, tid, 0, 0) == -1) {
fprintf(stderr, "*** C771T037 ATTACH NG err=%d\n",
errno);
exit(1);
}
if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) {
fprintf(stderr, "*** C771T037 ATTACH NG err=%d\n",
errno);
exit(1);
}
rc = wait4(pid, &st, WNOHANG, NULL);
if (rc == -1) {
fprintf(stderr, "*** C771T037 wait4(pid) NG err=%d\n",
errno);
}
else {
fprintf(stderr, "*** C771T037 wait4(pid) OK\n");
}
rc = wait4(tid, &st, WNOHANG, NULL);
if (rc == -1 && errno == ECHILD) {
fprintf(stderr, "*** C771T038 wait4(tid) OK\n");
}
else {
fprintf(stderr, "*** C771T038 wait4(tid) NG err=%d\n",
errno);
}
rc = wait4(pid, &st, WNOHANG|__WCLONE, NULL);
if (rc == -1 && errno == ECHILD) {
fprintf(stderr,
"*** C771T039 wait4(pid, __WCLONE) OK\n");
}
else {
fprintf(stderr,
"*** C771T039 wait4(pid, __WCLONE) NG err=%d\n",
errno);
}
rc = wait4(tid, &st, WNOHANG|__WCLONE, NULL);
if (rc == -1) {
fprintf(stderr,
"*** C771T040 wait4(tid, __WCLONE) NG err=%d\n",
errno);
}
else {
fprintf(stderr,
"*** C771T040 wait4(tid, __WCLONE) OK\n");
}
rc = wait4(pid, &st, WNOHANG|__WALL, NULL);
if (rc == -1) {
fprintf(stderr,
"*** C771T041 wait4(pid, __WALL) NG err=%d\n",
errno);
}
else {
fprintf(stderr,
"*** C771T041 wait4(pid, __WALL) OK\n");
}
rc = wait4(tid, &st, WNOHANG|__WALL, NULL);
if (rc == -1) {
fprintf(stderr,
"*** C771T042 wait4(tid, __WALL) NG err=%d\n",
errno);
}
else {
fprintf(stderr,
"*** C771T042 wait4(tid, __WALL) OK\n");
}
if (ptrace(PTRACE_DETACH, tid, NULL, NULL) == -1) {
fprintf(stderr, "*** C771T042 DETACH NG err=%d\n",
errno);
exit(1);
}
if (ptrace(PTRACE_DETACH, pid, NULL, NULL) == -1) {
fprintf(stderr, "*** C771T042 DETACH NG err=%d\n",
errno);
exit(1);
}
*x = 0;
exit(0);
}
while (*x == tid);
exit(0);
}

View File

@ -0,0 +1,23 @@
CC = gcc
TARGET= C771T001 C771T033 C771T037
CPPFLAGS =
LDFLAGS =
all: $(TARGET)
C771T001: C771T001.c
$(CC) -g -Wall -o $@ $^ -pthread
C771T033: C771T033.c
$(CC) -g -Wall -o $@ $^ -pthread
C771T037: C771T037.c
$(CC) -g -Wall -o $@ $^ -pthread
test: all
@sh ./C771.sh
clean:
rm -f $(TARGET) *.o
rm -rf gdb-result

View File

@ -0,0 +1,144 @@
【Issue#771 Issue#1179 Issue#1143 動作確認】
□ テスト内容
各 Issue は以下の理由により、一括して対応した。
・ Issue#771 は ptrace のスレッドサポートである。
・ Issue#1179 は PTRACE_ATTACH の不具合対応であるが、スレッドの PTRACE_ATTACH
対応が Issue#771 に含まれるため、一括して対応することにした。
・ Issue#1143 は wait4 の __WALL フラグサポートであるが、スレッドの wait4 対応
(__WCLONEフラグサポート) が Issue#771 に含まれるため、一括して対応すること
にした。
テスト内容は以下の通りである。
1. gdb を用いてスレッドを使用するプログラムのデバッグが行えることを確認する。
C771T001 mcexec gdb C771T001 を実行すると、McKernelでgdbの実行を開始し、
(gdb) のプロンプトが表示されること
C771T002 b thr を実行し、スレッドにブレークポイントを設定できること
C771T003 r コマンド実行後、スレッドに設定したブレークポイントで停止できること
C771T004 info threads コマンドで、スレッド一覧が表示できること
C771T005 bt コマンドでスレッドのバックトレースが表示できること
C771T006 n コマンドでスレッドのステップ実行ができること
C771T007 thread 1 コマンドでメインスレッドに切り替えできること
C771T008 bt コマンドでメインスレッドのバックトレースが表示できること
C771T009 thread 2 コマンドで再びスレッドに切り替えできること
C771T010 c コマンドでスレッドとメインスレッドの実行が再開されること
C771T011 q コマンドで gdb を正しく終了できること
C771T012 McKernel にスレッドとプロセスの残留が無いこと
2. gdb のテストケースを実行し、gdb が使用する ptrace の機能が動作することを
確認する。thread を使用するテストを中心に、以下のテストケースを選定した。
C771T013 a2-run が PASS すること
C771T014 foll-fork が PASS すること
C771T015 fork-detach が PASS すること
C771T016 atomic-seq-threaded が PASS すること
C771T017 bp_in_thread が PASS すること
C771T018 bt-clone-stop が PASS すること
C771T019 corethreads が PASS すること
C771T020 dlopen-libpthread が PASS すること
C771T021 fork-child-threads が PASS すること
C771T022 killed が PASS すること
C771T023 pthread_cond_wait が PASS すること
C771T024 switch-threads が PASS すること
C771T025 thread-specific が PASS すること
C771T026 thread_check が PASS すること
C771T027 thread_events が PASS すること
C771T028 threaded-exec が PASS すること
C771T029 threxit-hop-specific が PASS すること
C771T030 tls-nodebug が PASS すること
C771T031 tls-sepdebug が PASS すること
C771T032 tls-var が PASS すること
3. ptrace のスレッドサポートの基本機能を確認する。
C771T033 スレッドに PTRACE_ATTACH できること
C771T034 PTRACE_SYSCALL により、スレッドのシステムコールを補足できること
C771T035 PTRACE_DETACH により、スレッドのトレースを中止できること
4. Issue#1179 の指摘プログラムが正常動作することを確認する。
CT771T036 test_mck -s ptrace -n 19 が PASS すること
5. wait4 で __WALL フラグ、__WCLONE フラグが正しく機能することを確認する。
CT771T037 wait4 のフラグに __WALL, __WCLONE 共に指定しないとき、pid に
子プロセスを指定してエラーにならないこと
CT771T038 wait4 のフラグに __WALL, __WCLONE 共に指定しないとき、pid に
スレッドをを指定してエラー(ECHILD)になること
CT771T039 wait4 のフラグに __WCLONE を指定し、pid に子プロセスを指定して
エラー(ECHILD)になること
CT771T040 wait4 のフラグに __WCLONE を指定し、pid にスレッドをを指定して
エラーにならないこと
CT771T041 wait4 のフラグに __WALL を指定し、pid に子プロセスを指定して
エラーにならないこと
CT771T042 wait4 のフラグに __WALL を指定し、pid にスレッドをを指定して
エラーにならないこと
6. LTP を用いて変更が既存処理に影響しないことを確認する。
プロセス関連のシステムコール(clone, exit, fork, kill, ptrace, waitなど)
を中心に以下のテストプログラムを選定した。
CT771T043 clone01 が PASS すること
CT771T044 clone03 が PASS すること
CT771T045 clone04 が PASS すること
CT771T046 clone06 が PASS すること
CT771T047 clone07 が PASS すること
CT771T048 exit01 が PASS すること
CT771T049 exit02 が PASS すること
CT771T050 exit_group01 が PASS すること
CT771T051 fork01 が PASS すること
CT771T052 fork02 が PASS すること
CT771T053 fork03 が PASS すること
CT771T054 fork04 が PASS すること
CT771T055 fork07 が PASS すること
CT771T056 fork08 が PASS すること
CT771T057 fork09 が PASS すること
CT771T058 fork10 が PASS すること
CT771T059 fork11 が PASS すること
CT771T060 kill01 が PASS すること
CT771T061 kill02 が PASS すること
CT771T062 kill03 が PASS すること
CT771T063 kill04 が PASS すること
CT771T064 kill05 が PASS すること
CT771T065 kill06 が PASS すること
CT771T066 kill07 が PASS すること
CT771T067 kill08 が PASS すること
CT771T068 kill09 が PASS すること
CT771T069 kill11 が PASS すること
CT771T070 kill12 が PASS すること
CT771T071 ptrace01 が PASS すること
CT771T072 ptrace02 が PASS すること
CT771T073 ptrace03 が PASS すること
CT771T074 ptrace04 が PASS すること
CT771T075 ptrace05 が PASS すること
CT771T076 wait02 が PASS すること
CT771T077 wait401 が PASS すること
CT771T078 wait402 が PASS すること
CT771T079 waitid01 が PASS すること
CT771T080 waitid02 が PASS すること
CT771T081 waitpid01 が PASS すること
CT771T082 waitpid02 が PASS すること
CT771T083 waitpid03 が PASS すること
CT771T084 waitpid04 が PASS すること
CT771T085 waitpid05 が PASS すること
CT771T086 waitpid06 が PASS すること
CT771T087 waitpid07 が PASS すること
CT771T088 waitpid08 が PASS すること
CT771T089 waitpid09 が PASS すること
CT771T090 waitpid10 が PASS すること
CT771T091 waitpid11 が PASS すること
CT771T092 waitpid12 が PASS すること
CT771T093 waitpid13 が PASS すること
□ 実行手順
$ make test
McKernelのインストール先や、OSTEST, LTPの配置場所は、 $HOME/.mck_test_config
を参照する。.mck_test_config は、McKernel をビルドした際に生成される
mck_test_config.sample ファイルを $HOME にコピーし、適宜編集すること。
また、C771.sh の以下の指定を適宜変更すること。
GDBBUILDDIR= GDB 構築したパス ($HOME にて gdb を src.rpm から構築している
場合は変更不要)
gdb のテストケースでは、dejagnu パッケージに含まれる runtest コマンドを使用
する。システムにインストールされていない場合は、予めインストールすること。
□ 実行結果
C771.txt 参照。
すべての項目をPASSしていることを確認。

View File

@ -0,0 +1,75 @@
#!/bin/bash
if [ $# -lt 2 ]; then
echo "$0 option error" >&2
echo "Usage: $0 category test_exp" >&2
exit 1
fi
cat=$1
test_exp=$2
gdb_installdir=/usr
if [ "X$gdb_builddir" = X ];then
echo gdb_builddir was not set >&2
exit 1
fi
if [ "X$MCEXEC" = X ];then
echo MCEXEC was not set >&2
exit 1
fi
log_dir="$gdb_builddir/gdb/testsuite"
if ! which runtest > /dev/null 2>&1; then
echo no runtest found >&2
exit 1
fi
result=`pwd`/gdb-result
result_raw=`pwd`/gdb-result/raw
export PATH=`pwd`:$PATH
cd ${gdb_builddir}
echo "======== ${test_exp} ========"
# exec by linux
make check RUNTESTFLAGS="--verbose gdb.${cat}/${test_exp}.exp" &> /dev/null
mv ${log_dir}/gdb.log ${result_raw}/linux/${test_exp}.log
mv ${log_dir}/gdb.sum ${result_raw}/linux/${test_exp}.sum
# exec by mcexec
make check RUNTESTFLAGS="--verbose GDB=mcexec_gdb.sh gdb.${cat}/${test_exp}.exp" &> /dev/null
mv ${log_dir}/gdb.log ${result_raw}/mck/${test_exp}.log
mv ${log_dir}/gdb.sum ${result_raw}/mck/${test_exp}.sum
# extract important part
sed -n '/gdb tests/,/expected passes/p' ${result_raw}/linux/${test_exp}.sum > ${result}/linux/${test_exp}.sum
sed -n '/gdb tests/,/expected passes/p' ${result_raw}/mck/${test_exp}.sum > ${result}/mck/${test_exp}.sum
grep -e '^(gdb) [a-zA-Z0-9]' ${result_raw}/linux/${test_exp}.log > ${result}/linux/${test_exp}.log
grep -e '^(gdb) [a-zA-Z0-9]' ${result_raw}/mck/${test_exp}.log > ${result}/mck/${test_exp}.log
diff -u ${result}/linux/${test_exp}.sum ${result}/mck/${test_exp}.sum > /dev/null
if [ $? -eq 0 ]; then
echo "【SAME】${test_exp}: Summary."
else
echo "【DIFF】${test_exp} : Summary Difference ---"
diff -u ${result}/linux/${test_exp}.sum ${result}/mck/${test_exp}.sum
fi
diff -u ${result}/linux/${test_exp}.log ${result}/mck/${test_exp}.log > /dev/null
if [ $? -eq 0 ]; then
echo "【SAME】${test_exp} : Log."
else
echo "【DIFF】${test_exp} : Log Difference ---"
diff -u ${result}/linux/${test_exp}.log ${result}/mck/${test_exp}.log
fi
diff -u <(grep 'of expected passes' ${result}/linux/${test_exp}.sum) <(grep 'of expected passes' ${result}/mck/${test_exp}.sum) > /dev/null
if [ $? -eq 0 ]; then
echo "【PASS】${test_exp}"
else
echo "【FAIL】${test_exp}"
diff -u <(grep 'of expected passes' ${result}/linux/${test_exp}.sum) <(grep 'of expected passes' ${result}/mck/${test_exp}.sum) > /dev/null
fi

View File

@ -0,0 +1,20 @@
base a2-run
base foll-fork
base fork-detach
threads atomic-seq-threaded
threads bp_in_thread
threads bt-clone-stop
threads corethreads
threads dlopen-libpthread
threads fork-child-threads
threads killed
threads pthread_cond_wait
threads switch-threads
threads thread-specific
threads thread_check
threads thread_events
threads threaded-exec
threads threxit-hop-specific
threads tls-nodebug
threads tls-sepdebug
threads tls-var

View File

@ -0,0 +1,51 @@
clone01
clone03
clone04
clone06
clone07
exit01
exit02
exit_group01
fork01
fork02
fork03
fork04
fork07
fork08
fork09
fork10
fork11
kill01
kill02
kill03
kill04
kill05
kill06
kill07
kill08
kill09
kill10
kill11
kill12
ptrace01
ptrace02
ptrace03
ptrace05
wait02
wait401
wait402
waitid01
waitid02
waitpid01
waitpid02
waitpid03
waitpid04
waitpid05
waitpid06
waitpid07
waitpid08
waitpid09
waitpid10
waitpid11
waitpid12
waitpid13

View File

@ -0,0 +1,8 @@
#!/bin/sh -x
if [ x$MCEXEC = x ]; then
echo MCEXEC was not set >&2
exit 1
fi
exec $MCEXEC gdb "$@"