fork: do_fork: free resources when an error is detected
Change-Id: I0a29bb2cf886228effb088afe97d1b614728f517
This commit is contained in:
committed by
Masamichi Takagi
parent
6ce5c754f3
commit
f2460695c4
@@ -2669,9 +2669,12 @@ unsigned long do_fork(int clone_flags, unsigned long newsp,
|
|||||||
int ptrace_event = 0;
|
int ptrace_event = 0;
|
||||||
int termsig = clone_flags & 0x000000ff;
|
int termsig = clone_flags & 0x000000ff;
|
||||||
const struct ihk_mc_cpu_info *cpu_info = ihk_mc_get_cpu_info();
|
const struct ihk_mc_cpu_info *cpu_info = ihk_mc_get_cpu_info();
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
dkprintf("do_fork,flags=%08x,newsp=%lx,ptidptr=%lx,ctidptr=%lx,tls=%lx,curpc=%lx,cursp=%lx",
|
dkprintf("%s,flags=%08x,newsp=%lx,ptidptr=%lx,"
|
||||||
clone_flags, newsp, parent_tidptr, child_tidptr, tlsblock_base, curpc, cursp);
|
"ctidptr=%lx,tls=%lx,curpc=%lx,cursp=%lx",
|
||||||
|
__func__, clone_flags, newsp, parent_tidptr,
|
||||||
|
child_tidptr, tlsblock_base, curpc, cursp);
|
||||||
|
|
||||||
dkprintf("do_fork(): stack_pointr passed in: 0x%lX, stack pointer of caller: 0x%lx\n",
|
dkprintf("do_fork(): stack_pointr passed in: 0x%lX, stack pointer of caller: 0x%lx\n",
|
||||||
newsp, cursp);
|
newsp, cursp);
|
||||||
@@ -2710,7 +2713,7 @@ unsigned long do_fork(int clone_flags, unsigned long newsp,
|
|||||||
|
|
||||||
if (!allow_oversubscribe && rusage.num_threads >= cpu_info->ncpus) {
|
if (!allow_oversubscribe && rusage.num_threads >= cpu_info->ncpus) {
|
||||||
kprintf("%s: ERROR: CPU oversubscription is not allowed. Specify -O option in mcreboot.sh to allow it.\n", __FUNCTION__);
|
kprintf("%s: ERROR: CPU oversubscription is not allowed. Specify -O option in mcreboot.sh to allow it.\n", __FUNCTION__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldproc->coredump_barrier_count) {
|
if (oldproc->coredump_barrier_count) {
|
||||||
@@ -2730,17 +2733,17 @@ unsigned long do_fork(int clone_flags, unsigned long newsp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
cpuid = obtain_clone_cpuid(&old->cpu_set, old->mod_clone == SPAWN_TO_REMOTE && oldproc->uti_use_last_cpu);
|
cpuid = obtain_clone_cpuid(&old->cpu_set, old->mod_clone == SPAWN_TO_REMOTE && oldproc->uti_use_last_cpu);
|
||||||
if (cpuid == -1) {
|
if (cpuid == -1) {
|
||||||
kprintf("do_fork,core not available\n");
|
kprintf("do_fork,core not available\n");
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
new = clone_thread(old, curpc,
|
new = clone_thread(old, curpc,
|
||||||
newsp ? newsp : cursp, clone_flags);
|
newsp ? newsp : cursp, clone_flags);
|
||||||
|
|
||||||
if (!new) {
|
if (!new) {
|
||||||
release_cpuid(cpuid);
|
err = -ENOMEM;
|
||||||
return -ENOMEM;
|
goto release_cpuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
newproc = new->proc;
|
newproc = new->proc;
|
||||||
@@ -2759,8 +2762,8 @@ unsigned long do_fork(int clone_flags, unsigned long newsp,
|
|||||||
tids = kmalloc(sizeof(int) * NR_TIDS, IHK_MC_AP_NOWAIT);
|
tids = kmalloc(sizeof(int) * NR_TIDS, IHK_MC_AP_NOWAIT);
|
||||||
if (!tids) {
|
if (!tids) {
|
||||||
mcs_rwlock_writer_unlock(&newproc->threads_lock, &lock);
|
mcs_rwlock_writer_unlock(&newproc->threads_lock, &lock);
|
||||||
release_cpuid(cpuid);
|
err = -ENOMEM;
|
||||||
return -ENOMEM;
|
goto destroy_thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
newproc->tids = kmalloc(sizeof(struct mcexec_tid) *
|
newproc->tids = kmalloc(sizeof(struct mcexec_tid) *
|
||||||
@@ -2768,11 +2771,16 @@ unsigned long do_fork(int clone_flags, unsigned long newsp,
|
|||||||
if (!newproc->tids) {
|
if (!newproc->tids) {
|
||||||
mcs_rwlock_writer_unlock(&newproc->threads_lock, &lock);
|
mcs_rwlock_writer_unlock(&newproc->threads_lock, &lock);
|
||||||
kfree(tids);
|
kfree(tids);
|
||||||
release_cpuid(cpuid);
|
err = -ENOMEM;
|
||||||
return -ENOMEM;
|
goto destroy_thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
settid(new, NR_TIDS, tids);
|
if ((err = settid(new, NR_TIDS, tids)) < 0) {
|
||||||
|
mcs_rwlock_writer_unlock(&newproc->threads_lock,
|
||||||
|
&lock);
|
||||||
|
kfree(tids);
|
||||||
|
goto release_ids;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; (i < NR_TIDS) && tids[i]; ++i) {
|
for (i = 0; (i < NR_TIDS) && tids[i]; ++i) {
|
||||||
dkprintf("%s: tids[%d]: %d\n",
|
dkprintf("%s: tids[%d]: %d\n",
|
||||||
@@ -2804,14 +2812,14 @@ retry_tid:
|
|||||||
|
|
||||||
/* TODO: spawn more mcexec threads */
|
/* TODO: spawn more mcexec threads */
|
||||||
if (!new->tid) {
|
if (!new->tid) {
|
||||||
release_cpuid(cpuid);
|
|
||||||
kprintf("%s: no more TIDs available\n", __func__);
|
kprintf("%s: no more TIDs available\n", __func__);
|
||||||
for (i = 0; i < newproc->nr_tids; ++i) {
|
for (i = 0; i < newproc->nr_tids; ++i) {
|
||||||
kprintf("%s: i=%d,tid=%d,thread=%p\n",
|
kprintf("%s: i=%d,tid=%d,thread=%p\n",
|
||||||
__func__, i, newproc->tids[i].tid,
|
__func__, i, newproc->tids[i].tid,
|
||||||
newproc->tids[i].thread);
|
newproc->tids[i].thread);
|
||||||
}
|
}
|
||||||
return -ENOMEM;
|
err = -ENOMEM;
|
||||||
|
goto release_ids;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* fork() a new process on the host */
|
/* fork() a new process on the host */
|
||||||
@@ -2830,10 +2838,8 @@ retry_tid:
|
|||||||
newproc->pid = do_syscall(&request1, ihk_mc_get_processor_id());
|
newproc->pid = do_syscall(&request1, ihk_mc_get_processor_id());
|
||||||
if (newproc->pid < 0) {
|
if (newproc->pid < 0) {
|
||||||
kprintf("ERROR: forking host process\n");
|
kprintf("ERROR: forking host process\n");
|
||||||
|
err = newproc->pid;
|
||||||
/* TODO: clean-up new */
|
goto destroy_thread;
|
||||||
release_cpuid(cpuid);
|
|
||||||
return newproc->pid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In a single threaded process TID equals to PID */
|
/* In a single threaded process TID equals to PID */
|
||||||
@@ -2851,7 +2857,10 @@ retry_tid:
|
|||||||
dkprintf("clone_flags & CLONE_PARENT_SETTID: 0x%lX\n",
|
dkprintf("clone_flags & CLONE_PARENT_SETTID: 0x%lX\n",
|
||||||
parent_tidptr);
|
parent_tidptr);
|
||||||
|
|
||||||
setint_user((int*)parent_tidptr, new->tid);
|
err = setint_user((int *)parent_tidptr, new->tid);
|
||||||
|
if (err) {
|
||||||
|
goto release_ids;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clone_flags & CLONE_CHILD_CLEARTID) {
|
if (clone_flags & CLONE_CHILD_CLEARTID) {
|
||||||
@@ -2869,8 +2878,8 @@ retry_tid:
|
|||||||
if (ihk_mc_pt_virt_to_phys(new->vm->address_space->page_table,
|
if (ihk_mc_pt_virt_to_phys(new->vm->address_space->page_table,
|
||||||
(void *)child_tidptr, &phys)) {
|
(void *)child_tidptr, &phys)) {
|
||||||
kprintf("ERROR: looking up physical addr for child process\n");
|
kprintf("ERROR: looking up physical addr for child process\n");
|
||||||
release_cpuid(cpuid);
|
err = -EFAULT;
|
||||||
return -EFAULT;
|
goto release_ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
*((int*)phys_to_virt(phys)) = new->tid;
|
*((int*)phys_to_virt(phys)) = new->tid;
|
||||||
@@ -2901,7 +2910,8 @@ retry_tid:
|
|||||||
if (!new->mod_clone_arg) {
|
if (!new->mod_clone_arg) {
|
||||||
kprintf("%s: error: allocating mod_clone_arg\n",
|
kprintf("%s: error: allocating mod_clone_arg\n",
|
||||||
__func__);
|
__func__);
|
||||||
return -ENOMEM;
|
err = -ENOMEM;
|
||||||
|
goto release_ids;
|
||||||
}
|
}
|
||||||
memcpy(new->mod_clone_arg, old->mod_clone_arg,
|
memcpy(new->mod_clone_arg, old->mod_clone_arg,
|
||||||
sizeof(struct uti_attr));
|
sizeof(struct uti_attr));
|
||||||
@@ -2950,7 +2960,10 @@ retry_tid:
|
|||||||
request1.number = __NR_clone;
|
request1.number = __NR_clone;
|
||||||
request1.args[0] = 1;
|
request1.args[0] = 1;
|
||||||
request1.args[1] = new->tid;
|
request1.args[1] = new->tid;
|
||||||
do_syscall(&request1, ihk_mc_get_processor_id());
|
err = do_syscall(&request1, ihk_mc_get_processor_id());
|
||||||
|
if (err) {
|
||||||
|
goto free_mod_clone_arg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (termsig && termsig != SIGCHLD) {
|
else if (termsig && termsig != SIGCHLD) {
|
||||||
struct mcs_rwlock_node_irqsave lock;
|
struct mcs_rwlock_node_irqsave lock;
|
||||||
@@ -2971,6 +2984,37 @@ retry_tid:
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new->tid;
|
return new->tid;
|
||||||
|
|
||||||
|
free_mod_clone_arg:
|
||||||
|
kfree(new->mod_clone_arg);
|
||||||
|
new->mod_clone_arg = NULL;
|
||||||
|
|
||||||
|
ihk_atomic_dec(&new->vm->refcount);
|
||||||
|
|
||||||
|
release_ids:
|
||||||
|
if (clone_flags & CLONE_VM) {
|
||||||
|
kfree(newproc->tids);
|
||||||
|
newproc->tids = NULL;
|
||||||
|
} else {
|
||||||
|
request1.number = __NR_kill;
|
||||||
|
request1.args[0] = newproc->pid;
|
||||||
|
request1.args[1] = SIGKILL;
|
||||||
|
do_syscall(&request1, ihk_mc_get_processor_id());
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy_thread:
|
||||||
|
if (!(clone_flags & CLONE_VM)) {
|
||||||
|
/* in case of fork, destroy struct process */
|
||||||
|
ihk_atomic_set(&new->proc->refcount, 1);
|
||||||
|
kfree(newproc->saved_cmdline);
|
||||||
|
newproc->saved_cmdline = NULL;
|
||||||
|
}
|
||||||
|
ihk_atomic_set(&new->refcount, 1);
|
||||||
|
release_thread(new);
|
||||||
|
|
||||||
|
release_cpuid:
|
||||||
|
release_cpuid(cpuid);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DECLARE(set_tid_address)
|
SYSCALL_DECLARE(set_tid_address)
|
||||||
|
|||||||
Reference in New Issue
Block a user