/* * This creates a new process as a copy of the old one, * but does not actually start it yet. * * It copies the registers, and all the appropriate * parts of the process environment (as per the clone * flags). The actual kick-off is left to the caller. */ struct task_struct *copy_process(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size, int __user *parent_tidptr, int __user *child_tidptr) { int retval; struct task_struct *p = NULL; if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) return ERR_PTR(-EINVAL); /* * Thread groups must share signals as well, and detached threads * can only be started up within the thread group. */ if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND)) return ERR_PTR(-EINVAL); /* * Shared signal handlers imply shared VM. By way of the above, * thread groups also imply shared VM. Blocking this case allows * for various simplifications in other code. */ if ((clone_flags & CLONE_SIGHAND) && !(clone_flags & CLONE_VM)) return ERR_PTR(-EINVAL); retval = security_task_create(clone_flags); if (retval) goto fork_out; retval = -ENOMEM; p = dup_task_struct(current); if (!p) goto fork_out; retval = -EAGAIN; if (atomic_read(&p->user->processes) >= p->rlim[RLIMIT_NPROC].rlim_cur) { if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) && p->user != &root_user) goto bad_fork_free; } atomic_inc(&p->user->__count); atomic_inc(&p->user->processes); get_group_info(p->group_info); /* * If multiple threads are within copy_process(), then this check * triggers too late. This doesn't hurt, the check is only there * to stop root fork bombs. */ if (nr_threads >= max_threads) goto bad_fork_cleanup_count; if (!try_module_get(p->thread_info->exec_domain->module)) goto bad_fork_cleanup_count; if (p->binfmt && !try_module_get(p->binfmt->module)) goto bad_fork_cleanup_put_domain; p->did_exec = 0; copy_flags(clone_flags, p); if (clone_flags & CLONE_IDLETASK) p->pid = 0; else { p->pid = alloc_pidmap(); if (p->pid == -1) goto bad_fork_cleanup; } retval = -EFAULT; if (clone_flags & CLONE_PARENT_SETTID) if (put_user(p->pid, parent_tidptr)) goto bad_fork_cleanup; p->proc_dentry = NULL; INIT_LIST_HEAD(&p->children); INIT_LIST_HEAD(&p->sibling); init_waitqueue_head(&p->wait_chldexit); p->vfork_done = NULL; spin_lock_init(&p->alloc_lock); spin_lock_init(&p->proc_lock); clear_tsk_thread_flag(p, TIF_SIGPENDING); init_sigpending(&p->pending); p->it_real_value = p->it_virt_value = p->it_prof_value = 0; p->it_real_incr = p->it_virt_incr = p->it_prof_incr = 0; init_timer(&p->real_timer); p->real_timer.data = (unsigned long) p; p->utime = p->stime = 0; p->cutime = p->cstime = 0; p->lock_depth = -1; /* -1 = no lock */ p->start_time = get_jiffies_64(); p->security = NULL; p->io_context = NULL; p->audit_context = NULL; #ifdef CONFIG_NUMA p->mempolicy = mpol_copy(p->mempolicy); if (IS_ERR(p->mempolicy)) { retval = PTR_ERR(p->mempolicy); p->mempolicy = NULL; goto bad_fork_cleanup; } #endif retval = -ENOMEM; if ((retval = security_task_alloc(p))) goto bad_fork_cleanup_policy; if ((retval = audit_alloc(p))) goto bad_fork_cleanup_security; /* copy all the process information */ if ((retval = copy_semundo(clone_flags, p))) goto bad_fork_cleanup_audit; if ((retval = copy_files(clone_flags, p))) goto bad_fork_cleanup_semundo; if ((retval = copy_fs(clone_flags, p))) goto bad_fork_cleanup_files; if ((retval = copy_sighand(clone_flags, p))) goto bad_fork_cleanup_fs; if ((retval = copy_signal(clone_flags, p))) goto bad_fork_cleanup_sighand; if ((retval = copy_mm(clone_flags, p))) goto bad_fork_cleanup_signal; if ((retval = copy_namespace(clone_flags, p))) goto bad_fork_cleanup_mm; retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs); if (retval) goto bad_fork_cleanup_namespace; p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; /* * Clear TID on mm_release()? */ p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL; /* * Syscall tracing should be turned off in the child regardless * of CLONE_PTRACE. */ clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); /* Our parent execution domain becomes current domain These must match for thread signalling to apply */ p->parent_exec_id = p->self_exec_id; /* ok, now we should be set up.. */ p->exit_signal = (clone_flags & CLONE_THREAD) ? -1 : (clone_flags & CSIGNAL); p->pdeath_signal = 0; /* Perform scheduler related setup */ sched_fork(p); /* * Ok, make it visible to the rest of the system. * We dont wake it up yet. */ p->tgid = p->pid; p->group_leader = p; INIT_LIST_HEAD(&p->ptrace_children); INIT_LIST_HEAD(&p->ptrace_list); /* Need tasklist lock for parent etc handling! */ write_lock_irq(&tasklist_lock); /* * Check for pending SIGKILL! The new thread should not be allowed * to slip out of an OOM kill. (or normal SIGKILL.) */ if (sigismember(¤t->pending.signal, SIGKILL)) { write_unlock_irq(&tasklist_lock); retval = -EINTR; goto bad_fork_cleanup_namespace; } /* CLONE_PARENT re-uses the old parent */ if (clone_flags & CLONE_PARENT) p->real_parent = current->real_parent; else p->real_parent = current; p->parent = p->real_parent; if (clone_flags & CLONE_THREAD) { spin_lock(¤t->sighand->siglock); /* * Important: if an exit-all has been started then * do not create this new thread - the whole thread * group is supposed to exit anyway. */ if (current->signal->group_exit) { spin_unlock(¤t->sighand->siglock); write_unlock_irq(&tasklist_lock); retval = -EAGAIN; goto bad_fork_cleanup_namespace; } p->tgid = current->tgid; p->group_leader = current->group_leader; if (current->signal->group_stop_count > 0) { /* * There is an all-stop in progress for the group. * We ourselves will stop as soon as we check signals. * Make the new thread part of that group stop too. */ current->signal->group_stop_count++; set_tsk_thread_flag(p, TIF_SIGPENDING); } spin_unlock(¤t->sighand->siglock); } SET_LINKS(p); if (p->ptrace & PT_PTRACED) __ptrace_link(p, current->parent); attach_pid(p, PIDTYPE_PID, p->pid); if (thread_group_leader(p)) { attach_pid(p, PIDTYPE_TGID, p->tgid); attach_pid(p, PIDTYPE_PGID, process_group(p)); attach_pid(p, PIDTYPE_SID, p->signal->session); if (p->pid) __get_cpu_var(process_counts)++; } else link_pid(p, p->pids + PIDTYPE_TGID, &p->group_leader->pids[PIDTYPE_TGID].pid); nr_threads++; write_unlock_irq(&tasklist_lock); retval = 0; fork_out: if (retval) return ERR_PTR(retval); return p; bad_fork_cleanup_namespace: exit_namespace(p); bad_fork_cleanup_mm: exit_mm(p); if (p->active_mm) mmdrop(p->active_mm); bad_fork_cleanup_signal: exit_signal(p); bad_fork_cleanup_sighand: exit_sighand(p); bad_fork_cleanup_fs: exit_fs(p); /* blocking */ bad_fork_cleanup_files: exit_files(p); /* blocking */ bad_fork_cleanup_semundo: exit_sem(p); bad_fork_cleanup_audit: audit_free(p); bad_fork_cleanup_security: security_task_free(p); bad_fork_cleanup_policy: #ifdef CONFIG_NUMA mpol_free(p->mempolicy); #endif bad_fork_cleanup: if (p->pid > 0) free_pidmap(p->pid); if (p->binfmt) module_put(p->binfmt->module); bad_fork_cleanup_put_domain: module_put(p->thread_info->exec_domain->module); bad_fork_cleanup_count: put_group_info(p->group_info); atomic_dec(&p->user->processes); free_uid(p->user); bad_fork_free: free_task(p); goto fork_out; }
int main(void) { // Relocate interrupt vectors // extern void *g_pfnVectors; SCB->VTOR = (uint32_t)&g_pfnVectors; float period = 0.0; int last_start = 0; int start = 0; int end = 0; setup(); init_hal(); set_comp_type("foo"); // default pin for mem errors HAL_PIN(bar) = 0.0; //feedback comps #include "comps/adc.comp" #include "comps/res.comp" #include "comps/enc_fb.comp" #include "comps/encm.comp" #include "comps/encs.comp" #include "comps/yaskawa.comp" //TODO: hyperface //command comps #include "comps/sserial.comp" #include "comps/sim.comp" #include "comps/enc_cmd.comp" #include "comps/en.comp" //PID #include "comps/stp.comp" #include "comps/rev.comp" #include "comps/rev.comp" #include "comps/vel.comp" #include "comps/vel.comp" #include "comps/cauto.comp" #include "comps/pid.comp" #include "comps/pmsm_t2c.comp" #include "comps/curpid.comp" #include "comps/pmsm.comp" #include "comps/pmsm_limits.comp" #include "comps/idq.comp" #include "comps/dq.comp" #include "comps/hv.comp" //other comps #include "comps/fault.comp" #include "comps/term.comp" #include "comps/io.comp" set_comp_type("net"); HAL_PIN(enable) = 0.0; HAL_PIN(cmd) = 0.0; HAL_PIN(fb) = 0.0; HAL_PIN(fb_error) = 0.0; HAL_PIN(cmd_d) = 0.0; HAL_PIN(fb_d) = 0.0; HAL_PIN(core_temp0) = 0.0; HAL_PIN(core_temp1) = 0.0; HAL_PIN(motor_temp) = 0.0; HAL_PIN(rt_calc_time) = 0.0; HAL_PIN(frt_calc_time) = 0.0; HAL_PIN(nrt_calc_time) = 0.0; HAL_PIN(rt_period) = 0.0; HAL_PIN(frt_period) = 0.0; HAL_PIN(nrt_period) = 0.0; set_comp_type("conf"); HAL_PIN(r) = 1.0; HAL_PIN(l) = 0.01; HAL_PIN(j) = KGCM2(0.26); HAL_PIN(psi) = 0.05; HAL_PIN(polecount) = 4.0; HAL_PIN(mot_type) = 0.0;//ac sync,async/dc,2phase HAL_PIN(out_rev) = 0.0; HAL_PIN(high_motor_temp) = 80.0; HAL_PIN(max_motor_temp) = 100.0; HAL_PIN(phase_time) = 0.5; HAL_PIN(phase_cur) = 1.0; HAL_PIN(max_vel) = RPM(1000.0); HAL_PIN(max_acc) = RPM(1000.0)/0.01; HAL_PIN(max_force) = 1.0; HAL_PIN(max_dc_cur) = 1.0; HAL_PIN(max_ac_cur) = 2.0; HAL_PIN(fb_type) = RES; HAL_PIN(fb_polecount) = 1.0; HAL_PIN(fb_offset) = 0.0; HAL_PIN(fb_rev) = 0.0; HAL_PIN(fb_res) = 1000.0; HAL_PIN(autophase) = 1.0;//constant,cauto,hfi HAL_PIN(cmd_type) = ENC; HAL_PIN(cmd_unit) = 0.0;//pos,vel,torque HAL_PIN(cmd_rev) = 0.0; HAL_PIN(cmd_res) = 2000.0; HAL_PIN(en_condition) = 0.0; HAL_PIN(error_out) = 0.0; HAL_PIN(pos_static) = 0.0;//track pos in disabled and error condition HAL_PIN(sin_offset) = 0.0; HAL_PIN(cos_offset) = 0.0; HAL_PIN(sin_gain) = 1.0; HAL_PIN(cos_gain) = 1.0; HAL_PIN(max_dc_volt) = 370.0; HAL_PIN(max_hv_temp) = 90.0; HAL_PIN(max_core_temp) = 55.0; HAL_PIN(max_pos_error) = M_PI / 2.0; HAL_PIN(high_dc_volt) = 350.0; HAL_PIN(low_dc_volt) = 12.0; HAL_PIN(high_hv_temp) = 70.0; HAL_PIN(fan_hv_temp) = 60.0; HAL_PIN(fan_core_temp) = 450.0; HAL_PIN(fan_motor_temp) = 60.0; HAL_PIN(p) = 0.99; HAL_PIN(pos_p) = 100.0; HAL_PIN(vel_p) = 1.0; HAL_PIN(acc_p) = 0.3; HAL_PIN(acc_pi) = 50.0; HAL_PIN(cur_p) = 0.0; HAL_PIN(cur_i) = 0.0; HAL_PIN(cur_ff) = 1.0; HAL_PIN(cur_ind) = 0.0; HAL_PIN(max_sat) = 0.2; rt_time_hal_pin = map_hal_pin("net0.rt_calc_time"); frt_time_hal_pin = map_hal_pin("net0.frt_calc_time"); rt_period_time_hal_pin = map_hal_pin("net0.rt_period"); frt_period_time_hal_pin = map_hal_pin("net0.frt_period"); for(int i = 0; i < hal.nrt_init_func_count; i++){ // run nrt init hal.nrt_init[i](); } link_pid(); if(hal.pin_errors + hal.comp_errors == 0){ start_hal(); } else{ hal.hal_state = MEM_ERROR; } while(1)//run non realtime stuff { start = SysTick->VAL; if(last_start < start){ last_start += SysTick->LOAD; } period = ((float)(last_start - start)) / RCC_Clocks.HCLK_Frequency; last_start = start; for(hal.active_nrt_func = 0; hal.active_nrt_func < hal.nrt_func_count; hal.active_nrt_func++){//run all non realtime hal functions hal.nrt[hal.active_nrt_func](period); } hal.active_nrt_func = -1; end = SysTick->VAL; if(start < end){ start += SysTick->LOAD; } PIN(nrt_calc_time) = ((float)(start - end)) / RCC_Clocks.HCLK_Frequency; PIN(nrt_period) = period; Wait(2); } }
int main(void) { float period = 0.0; float lasttime = 0.0; setup(); #include "comps/frt.comp" #include "comps/rt.comp" #include "comps/nrt.comp" #include "comps/pos_minus.comp" #include "comps/pwm2uvw.comp" #include "comps/pwmout.comp" #include "comps/pwm2uart.comp" #include "comps/enc.comp" #include "comps/res.comp" //#include "comps/pid.comp" #include "comps/term.comp" #include "comps/sim.comp" #include "comps/pderiv.comp" #include "comps/pderiv.comp" #include "comps/autophase.comp" #include "comps/vel_observer.comp" set_comp_type("net"); HAL_PIN(enable) = 0.0; HAL_PIN(cmd) = 0.0; HAL_PIN(fb) = 0.0; HAL_PIN(cmd_d) = 0.0; HAL_PIN(fb_d) = 0.0; HAL_PIN(u) = 0.0; HAL_PIN(v) = 0.0; HAL_PIN(w) = 0.0; for(int i = 0; i < hal.init_func_count; i++){ hal.init[i](); } TIM_Cmd(TIM2, ENABLE);//int TIM_Cmd(TIM4, ENABLE);//PWM TIM_Cmd(TIM5, ENABLE);//PID link_pid(); link_ac_sync_res(); set_hal_pin("ap0.start", 1.0); link_hal_pins("sim0.sin", "net0.cmd"); link_hal_pins("net0.cmd", "vel_ob0.pos_in"); link_hal_pins("net0.cmd", "term0.wave0"); link_hal_pins("net0.cmd_d", "term0.wave1"); link_hal_pins("vel_ob0.pos_out", "term0.wave2"); link_hal_pins("vel_ob0.vel_out", "term0.wave3"); link_hal_pins("vel_ob0.trg", "rt0.trg0"); set_hal_pin("term0.gain0", 10.0); set_hal_pin("term0.gain1", 10.0); set_hal_pin("term0.gain2", 10.0); set_hal_pin("term0.gain3", 10.0); set_hal_pin("sim0.amp", 1.0); set_hal_pin("sim0.freq", 0.5); set_hal_pin("vel_ob0.alpha", 1.0); set_hal_pin("vel_ob0.beta", 0.1); link_hal_pins("pwm2uart0.uout", "net0.u"); link_hal_pins("pwm2uart0.vout", "net0.v"); link_hal_pins("pwm2uart0.wout", "net0.w"); data_t data; while(1) // Do not exit { Wait(1); period = time/1000.0 + (1.0 - SysTick->VAL/RCC_Clocks.HCLK_Frequency)/1000.0 - lasttime; lasttime = time/1000.0 + (1.0 - SysTick->VAL/RCC_Clocks.HCLK_Frequency)/1000.0; for(int i = 0; i < hal.nrt_func_count; i++){ hal.nrt[i](period); } data.data[0] = (uint16_t)PIN(u); data.data[1] = (uint16_t)PIN(v); data.data[2] = (uint16_t)PIN(w); while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET); USART_SendData(USART3, 0x155); for(int i = 0; i < DATALENGTH * 2; i++){ while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET); USART_SendData(USART3, data.byte[i]); } } }
int main(void) { float period = 0.0; float lasttime = 0.0; setup(); #include "comps/adc.comp" #include "comps/fault.comp" #include "comps/enc_cmd.comp" #include "comps/enc_fb.comp" //#include "comps/res.comp" #include "comps/encm.comp" #include "comps/sim.comp" #include "comps/rev.comp" #include "comps/rev.comp" #include "comps/cauto.comp" #include "comps/pderiv.comp" #include "comps/pderiv.comp" #include "comps/pid.comp" #include "comps/rev.comp" #include "comps/cur.comp" #include "comps/pwm2uart.comp" #include "comps/absavg.comp" #include "comps/term.comp" #include "comps/led.comp" #include "comps/fan.comp" #include "comps/brake.comp" set_comp_type("net"); HAL_PIN(enable) = 0.0; HAL_PIN(cmd) = 0.0; HAL_PIN(fb) = 0.0; HAL_PIN(fb_error) = 0.0; HAL_PIN(cmd_d) = 0.0; HAL_PIN(fb_d) = 0.0; HAL_PIN(amp) = 0.0; HAL_PIN(vlt) = 0.0; HAL_PIN(tmp) = 0.0; HAL_PIN(rt_calc_time) = 0.0; set_comp_type("conf"); HAL_PIN(r) = 0.0; HAL_PIN(l) = 0.0; HAL_PIN(j) = 0.0; HAL_PIN(km) = 0.0; HAL_PIN(pole_count) = 0.0; HAL_PIN(fb_pole_count) = 0.0; HAL_PIN(fb_offset) = 0.0; HAL_PIN(pos_p) = 0.0; HAL_PIN(acc_p) = 0.0; HAL_PIN(acc_pi) = 0.0; HAL_PIN(cur_lp) = 0.0; HAL_PIN(max_vel) = 0.0; HAL_PIN(max_acc) = 0.0; HAL_PIN(max_force) = 0.0; HAL_PIN(max_cur) = 0.0; HAL_PIN(fb_type) = 0.0; HAL_PIN(cmd_type) = 0.0; HAL_PIN(fb_rev) = 0.0; HAL_PIN(cmd_rev) = 0.0; HAL_PIN(out_rev) = 0.0; HAL_PIN(fb_res) = 1.0; HAL_PIN(cmd_res) = 2000.0; HAL_PIN(sin_offset) = -17600.0; HAL_PIN(cos_offset) = -17661.0; HAL_PIN(sin_gain) = 0.0001515; HAL_PIN(cos_gain) = 0.00015; HAL_PIN(max_volt) = 370.0; HAL_PIN(max_temp) = 100.0; HAL_PIN(max_pos_error) = M_PI / 2.0; HAL_PIN(high_volt) = 350.0; HAL_PIN(low_volt) = 12.0; HAL_PIN(high_temp) = 80.0; HAL_PIN(fan_temp) = 40.0; HAL_PIN(autophase) = 1.0; HAL_PIN(max_sat) = 0.2; g_amp_hal_pin = map_hal_pin("net0.amp"); g_vlt_hal_pin = map_hal_pin("net0.vlt"); g_tmp_hal_pin = map_hal_pin("net0.tmp"); rt_time_hal_pin = map_hal_pin("net0.rt_calc_time"); for(int i = 0; i < hal.init_func_count; i++){ hal.init[i](); } link_pid(); //set_e240(); //set_bergerlahr();//pid2: ok //set_mitsubishi();//pid2: ok //set_festo(); //set_manutec(); set_rexroth();//pid2: ok //link_hal_pins("enc10.ipos", "rev1.in"); //set_hal_pin("res0.reverse", 0.0); //set_bosch1();//pid2: ok //set_bosch4();//pid2: ok //set_sanyo();//pid2: ok //set_br(); set_cmd_enc(); link_hal_pins("conf0.max_cur", "fault0.max_cur"); link_hal_pins("conf0.max_volt", "fault0.max_volt"); link_hal_pins("conf0.max_temp", "fault0.max_temp"); link_hal_pins("conf0.max_pos_error", "fault0.max_pos_error"); link_hal_pins("conf0.high_volt", "fault0.high_volt"); link_hal_pins("conf0.high_temp", "fault0.high_temp"); link_hal_pins("conf0.low_volt", "fault0.low_volt"); link_hal_pins("conf0.fan_temp", "fault0.fan_temp"); link_hal_pins("conf0.autophase", "fault0.phase_on_start"); link_hal_pins("conf0.max_sat", "fault0.max_sat"); set_hal_pin("fault0.reset", 0.0); link_hal_pins("fault0.phase_start", "cauto0.start"); link_hal_pins("cauto0.ready", "fault0.phase_ready"); link_hal_pins("pid0.pos_error", "fault0.pos_error"); link_hal_pins("pid0.saturated", "fault0.sat"); link_hal_pins("net0.vlt", "fault0.volt"); link_hal_pins("net0.tmp", "fault0.temp"); link_hal_pins("net0.amp", "fault0.amp"); link_hal_pins("net0.fb_error", "fault0.fb_error"); link_hal_pins("net0.cmd", "fault0.cmd"); link_hal_pins("rev1.out", "fault0.fb"); link_hal_pins("fault0.start_offset", "cauto0.start_offset"); link_hal_pins("fault0.cur", "pid0.max_cur"); link_hal_pins("fault0.cur", "cur0.cur_max"); link_hal_pins("fault0.brake", "brake0.brake"); link_hal_pins("fault0.fan", "fan0.fan"); link_hal_pins("fault0.enable_out", "pwm2uart0.enable"); link_hal_pins("fault0.enable_pid", "pid0.enable"); link_hal_pins("net0.enable", "fault0.enable"); link_hal_pins("fault0.led_green", "led0.g"); link_hal_pins("fault0.led_red", "led0.r"); link_hal_pins("pid0.pos_error", "avg0.in"); set_hal_pin("avg0.ac", 0.0001); TIM_Cmd(TIM8, ENABLE);//int UB_USB_CDC_Init(); while(1) // Do not exit { Wait(2); period = systime/1000.0 + (1.0 - SysTick->VAL/RCC_Clocks.HCLK_Frequency)/1000.0 - lasttime; lasttime = systime/1000.0 + (1.0 - SysTick->VAL/RCC_Clocks.HCLK_Frequency)/1000.0; for(int i = 0; i < hal.nrt_func_count; i++){ hal.nrt[i](period); } } }
/* * This creates a new process as a copy of the old one, * but does not actually start it yet. * * It copies the registers, and all the appropriate * parts of the process environment (as per the clone * flags). The actual kick-off is left to the caller. */ struct task_struct *copy_process(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size, int *parent_tidptr, int *child_tidptr) { int retval; struct task_struct *p = NULL; if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) return ERR_PTR(-EINVAL); /* * Thread groups must share signals as well, and detached threads * can only be started up within the thread group. */ if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND)) return ERR_PTR(-EINVAL); if ((clone_flags & CLONE_DETACHED) && !(clone_flags & CLONE_THREAD)) return ERR_PTR(-EINVAL); if (!(clone_flags & CLONE_DETACHED) && (clone_flags & CLONE_THREAD)) return ERR_PTR(-EINVAL); retval = -ENOMEM; p = dup_task_struct(current); if (!p) goto fork_out; p->tux_info = NULL; retval = -EAGAIN; /* * Increment user->__count before the rlimit test so that it would * be correct if we take the bad_fork_free failure path. */ atomic_inc(&p->user->__count); if (atomic_read(&p->user->processes) >= p->rlim[RLIMIT_NPROC].rlim_cur) { if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE)) goto bad_fork_free; } atomic_inc(&p->user->processes); /* * Counter increases are protected by * the kernel lock so nr_threads can't * increase under us (but it may decrease). */ if (nr_threads >= max_threads) goto bad_fork_cleanup_count; get_exec_domain(p->exec_domain); if (p->binfmt && p->binfmt->module) __MOD_INC_USE_COUNT(p->binfmt->module); p->did_exec = 0; p->swappable = 0; p->state = TASK_UNINTERRUPTIBLE; copy_flags(clone_flags, p); if (clone_flags & CLONE_IDLETASK) p->pid = 0; else { p->pid = alloc_pidmap(); if (p->pid == -1) goto bad_fork_cleanup; } retval = -EFAULT; if (clone_flags & CLONE_PARENT_SETTID) if (put_user(p->pid, parent_tidptr)) goto bad_fork_cleanup; INIT_LIST_HEAD(&p->run_list); INIT_LIST_HEAD(&p->children); INIT_LIST_HEAD(&p->sibling); init_waitqueue_head(&p->wait_chldexit); p->vfork_done = NULL; spin_lock_init(&p->alloc_lock); spin_lock_init(&p->switch_lock); p->sigpending = 0; init_sigpending(&p->pending); p->it_real_value = p->it_virt_value = p->it_prof_value = 0; p->it_real_incr = p->it_virt_incr = p->it_prof_incr = 0; init_timer(&p->real_timer); p->real_timer.data = (unsigned long) p; p->leader = 0; /* session leadership doesn't inherit */ p->tty_old_pgrp = 0; memset(&p->utime, 0, sizeof(p->utime)); memset(&p->stime, 0, sizeof(p->stime)); memset(&p->cutime, 0, sizeof(p->cutime)); memset(&p->cstime, 0, sizeof(p->cstime)); memset(&p->group_utime, 0, sizeof(p->group_utime)); memset(&p->group_stime, 0, sizeof(p->group_stime)); memset(&p->group_cutime, 0, sizeof(p->group_cutime)); memset(&p->group_cstime, 0, sizeof(p->group_cstime)); #ifdef CONFIG_SMP memset(&p->per_cpu_utime, 0, sizeof(p->per_cpu_utime)); memset(&p->per_cpu_stime, 0, sizeof(p->per_cpu_stime)); #endif memset(&p->timing_state, 0, sizeof(p->timing_state)); p->timing_state.type = PROCESS_TIMING_USER; p->last_sigxcpu = 0; p->array = NULL; p->lock_depth = -1; /* -1 = no lock */ p->start_time = jiffies; retval = -ENOMEM; /* copy all the process information */ if (copy_files(clone_flags, p)) goto bad_fork_cleanup; if (copy_fs(clone_flags, p)) goto bad_fork_cleanup_files; if (copy_sighand(clone_flags, p)) goto bad_fork_cleanup_fs; if (copy_signal(clone_flags, p)) goto bad_fork_cleanup_sighand; if (copy_mm(clone_flags, p)) goto bad_fork_cleanup_signal; if (copy_namespace(clone_flags, p)) goto bad_fork_cleanup_mm; retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs); if (retval) goto bad_fork_cleanup_namespace; p->semundo = NULL; p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; /* * Clear TID on mm_release()? */ p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr : NULL; /* Our parent execution domain becomes current domain These must match for thread signalling to apply */ p->parent_exec_id = p->self_exec_id; /* ok, now we should be set up.. */ p->swappable = 1; if (clone_flags & CLONE_DETACHED) p->exit_signal = -1; else p->exit_signal = clone_flags & CSIGNAL; p->pdeath_signal = 0; /* * Share the timeslice between parent and child, thus the * total amount of pending timeslices in the system doesnt change, * resulting in more scheduling fairness. */ local_irq_disable(); p->time_slice = (current->time_slice + 1) >> 1; p->first_time_slice = 1; /* * The remainder of the first timeslice might be recovered by * the parent if the child exits early enough. */ current->time_slice >>= 1; p->last_run = jiffies; if (!current->time_slice) { /* * This case is rare, it happens when the parent has only * a single jiffy left from its timeslice. Taking the * runqueue lock is not a problem. */ current->time_slice = 1; scheduler_tick(0 /* don't update the time stats */); } local_irq_enable(); if ((int)current->time_slice <= 0) BUG(); if ((int)p->time_slice <= 0) BUG(); /* * Ok, add it to the run-queues and make it * visible to the rest of the system. * * Let it rip! */ p->tgid = p->pid; p->group_leader = p; INIT_LIST_HEAD(&p->ptrace_children); INIT_LIST_HEAD(&p->ptrace_list); /* Need tasklist lock for parent etc handling! */ write_lock_irq(&tasklist_lock); /* * Check for pending SIGKILL! The new thread should not be allowed * to slip out of an OOM kill. (or normal SIGKILL.) */ if (sigismember(¤t->pending.signal, SIGKILL)) { write_unlock_irq(&tasklist_lock); retval = -EINTR; goto bad_fork_cleanup_namespace; } /* CLONE_PARENT re-uses the old parent */ if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) p->real_parent = current->real_parent; else p->real_parent = current; p->parent = p->real_parent; if (clone_flags & CLONE_THREAD) { spin_lock(¤t->sighand->siglock); /* * Important: if an exit-all has been started then * do not create this new thread - the whole thread * group is supposed to exit anyway. */ if (current->signal->group_exit) { spin_unlock(¤t->sighand->siglock); write_unlock_irq(&tasklist_lock); retval = -EINTR; goto bad_fork_cleanup_namespace; } p->tgid = current->tgid; p->group_leader = current->group_leader; if (current->signal->group_stop_count > 0) { /* * There is an all-stop in progress for the group. * We ourselves will stop as soon as we check signals. * Make the new thread part of that group stop too. */ current->signal->group_stop_count++; p->sigpending = 1; } spin_unlock(¤t->sighand->siglock); } SET_LINKS(p); if (p->ptrace & PT_PTRACED) __ptrace_link(p, current->parent); attach_pid(p, PIDTYPE_PID, p->pid); if (thread_group_leader(p)) { attach_pid(p, PIDTYPE_TGID, p->tgid); attach_pid(p, PIDTYPE_PGID, p->pgrp); attach_pid(p, PIDTYPE_SID, p->session); } else { link_pid(p, p->pids + PIDTYPE_TGID, &p->group_leader->pids[PIDTYPE_TGID].pid); } /* clear controlling tty of new task if parent's was just cleared */ if (!current->tty && p->tty) p->tty = NULL; nr_threads++; write_unlock_irq(&tasklist_lock); retval = 0; fork_out: if (retval) return ERR_PTR(retval); return p; bad_fork_cleanup_namespace: exit_namespace(p); bad_fork_cleanup_mm: exit_mm(p); if (p->active_mm) mmdrop(p->active_mm); bad_fork_cleanup_signal: exit_signal(p); bad_fork_cleanup_sighand: exit_sighand(p); bad_fork_cleanup_fs: exit_fs(p); /* blocking */ bad_fork_cleanup_files: exit_files(p); /* blocking */ bad_fork_cleanup: if (p->pid > 0) free_pidmap(p->pid); put_exec_domain(p->exec_domain); if (p->binfmt && p->binfmt->module) __MOD_DEC_USE_COUNT(p->binfmt->module); bad_fork_cleanup_count: atomic_dec(&p->user->processes); bad_fork_free: p->state = TASK_ZOMBIE; /* debug */ atomic_dec(&p->usage); put_task_struct(p); goto fork_out; }