/* * Check that we have indeed attached to the thing.. */ int ptrace_check_attach(struct task_struct *child, int kill) { if (!(child->ptrace & PT_PTRACED)) return -ESRCH; if (child->p_pptr != current) return -ESRCH; if (!kill) { if (child->state != TASK_STOPPED) return -ESRCH; #ifdef CONFIG_SMP /* Make sure the child gets off its CPU.. */ for (;;) { task_lock(child); if (!task_has_cpu(child)) break; task_unlock(child); do { if (child->state != TASK_STOPPED) return -ESRCH; barrier(); cpu_relax(); } while (task_has_cpu(child)); } task_unlock(child); #endif } /* All systems go.. */ return 0; }
static void release_task(struct task_struct * p) { if (p != current) { #ifdef CONFIG_SMP /* * Wait to make sure the process isn't on the * runqueue (active on some other CPU still) */ for (;;) { task_lock(p); if (!task_has_cpu(p)) break; task_unlock(p); do { cpu_relax(); barrier(); } while (task_has_cpu(p)); } task_unlock(p); #endif atomic_dec(&p->user->processes); security_task_free(p); free_uid(p->user); unhash_process(p); release_thread(p); current->cmin_flt += p->min_flt + p->cmin_flt; current->cmaj_flt += p->maj_flt + p->cmaj_flt; current->cnswap += p->nswap + p->cnswap; /* * Potentially available timeslices are retrieved * here - this way the parent does not get penalized * for creating too many processes. * * (this cannot be used to artificially 'generate' * timeslices, because any timeslice recovered here * was given away by the parent in the first place.) */ current->counter += p->counter; if (current->counter >= MAX_COUNTER) current->counter = MAX_COUNTER; p->pid = 0; free_task_struct(p); } else { printk("task releasing itself\n"); } }