00001
00019 #include "pm.h"
00020 #include <sys/wait.h>
00021 #include <minix/callnr.h>
00022 #include <minix/com.h>
00023 #include <sys/resource.h>
00024 #include <signal.h>
00025 #include "mproc.h"
00026 #include "param.h"
00027
00028 #define LAST_FEW 2
00029
00030 FORWARD _PROTOTYPE (void cleanup, (register struct mproc *child) );
00031
00032
00033
00034
00035 PUBLIC int do_fork()
00036 {
00037
00038 register struct mproc *rmp;
00039 register struct mproc *rmc;
00040 int child_nr, s;
00041 phys_clicks prog_clicks, child_base;
00042 phys_bytes prog_bytes, parent_abs, child_abs;
00043 pid_t new_pid;
00044 static int next_child;
00045 int n = 0, r;
00046
00047
00048
00049
00050 rmp = mp;
00051 if ((procs_in_use == NR_PROCS) ||
00052 (procs_in_use >= NR_PROCS-LAST_FEW && rmp->mp_effuid != 0))
00053 {
00054 printf("PM: warning, process table is full!\n");
00055 return(EAGAIN);
00056 }
00057
00058
00059
00060
00061 prog_clicks = (phys_clicks) rmp->mp_seg[S].mem_len;
00062 prog_clicks += (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
00063 prog_bytes = (phys_bytes) prog_clicks << CLICK_SHIFT;
00064 if ( (child_base = alloc_mem(prog_clicks)) == NO_MEM) return(ENOMEM);
00065
00066
00067 child_abs = (phys_bytes) child_base << CLICK_SHIFT;
00068 parent_abs = (phys_bytes) rmp->mp_seg[D].mem_phys << CLICK_SHIFT;
00069 s = sys_abscopy(parent_abs, child_abs, prog_bytes);
00070 if (s < 0) panic(__FILE__,"do_fork can't copy", s);
00071
00072
00073 do {
00074 next_child = (next_child+1) % NR_PROCS;
00075 n++;
00076 } while((mproc[next_child].mp_flags & IN_USE) && n <= NR_PROCS);
00077 if(n > NR_PROCS)
00078 panic(__FILE__,"do_fork can't find child slot", NO_NUM);
00079 if(next_child < 0 || next_child >= NR_PROCS
00080 || (mproc[next_child].mp_flags & IN_USE))
00081 panic(__FILE__,"do_fork finds wrong child slot", next_child);
00082
00083 rmc = &mproc[next_child];
00084
00085 child_nr = (int)(rmc - mproc);
00086 procs_in_use++;
00087 *rmc = *rmp;
00088 rmc->mp_parent = who_p;
00089
00090 rmc->mp_flags &= (IN_USE|SEPARATE|PRIV_PROC|DONT_SWAP);
00091 rmc->mp_child_utime = 0;
00092 rmc->mp_child_stime = 0;
00093
00094
00095
00096
00097 if (!(rmc->mp_flags & SEPARATE)) rmc->mp_seg[T].mem_phys = child_base;
00098 rmc->mp_seg[D].mem_phys = child_base;
00099 rmc->mp_seg[S].mem_phys = rmc->mp_seg[D].mem_phys +
00100 (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
00101 rmc->mp_exitstatus = 0;
00102 rmc->mp_sigstatus = 0;
00103
00104
00105 new_pid = get_free_pid();
00106 rmc->mp_pid = new_pid;
00107
00108
00109 if((r=sys_fork(who_e, child_nr, &rmc->mp_endpoint)) != OK) {
00110 panic(__FILE__,"do_fork can't sys_fork", r);
00111 }
00112 tell_fs(FORK, who_e, rmc->mp_endpoint, rmc->mp_pid);
00113
00114
00115 if((r=sys_newmap(rmc->mp_endpoint, rmc->mp_seg)) != OK) {
00116 panic(__FILE__,"do_fork can't sys_newmap", r);
00117 }
00118
00119
00120 setreply(child_nr, 0);
00121 rmp->mp_reply.endpt = rmc->mp_endpoint;
00122
00123 return(new_pid);
00124 }
00125
00126
00127
00128
00129 PUBLIC int do_pm_exit()
00130 {
00131
00132
00133
00134 pm_exit(mp, m_in.status);
00135 return(SUSPEND);
00136 }
00137
00138
00139
00140
00141 PUBLIC void pm_exit(rmp, exit_status)
00142 register struct mproc *rmp;
00143 int exit_status;
00144 {
00145
00146
00147
00148
00149 register int proc_nr, proc_nr_e;
00150 int parent_waiting, right_child, r;
00151 pid_t pidarg, procgrp;
00152 struct mproc *p_mp;
00153 clock_t t[5];
00154
00155 proc_nr = (int) (rmp - mproc);
00156 proc_nr_e = rmp->mp_endpoint;
00157
00158
00159 procgrp = (rmp->mp_pid == mp->mp_procgrp) ? mp->mp_procgrp : 0;
00160
00161
00162 if (rmp->mp_flags & ALARM_ON) set_alarm(proc_nr_e, (unsigned) 0);
00163
00164
00165 if((r=sys_times(proc_nr_e, t)) != OK)
00166 panic(__FILE__,"pm_exit: sys_times failed", r);
00167
00168 p_mp = &mproc[rmp->mp_parent];
00169 p_mp->mp_child_utime += t[0] + rmp->mp_child_utime;
00170 p_mp->mp_child_stime += t[1] + rmp->mp_child_stime;
00171
00172
00173
00174
00175
00176
00177
00178 sys_nice(proc_nr_e, PRIO_STOP);
00179 if(proc_nr_e != FS_PROC_NR)
00180 tell_fs(EXIT, proc_nr_e, 0, 0);
00181 else
00182 printf("PM: FS died\n");
00183 if((r=sys_exit(proc_nr_e)) != OK)
00184 panic(__FILE__,"pm_exit: sys_exit failed", r);
00185
00186
00187 rmp->mp_flags &= ~REPLY;
00188
00189
00190 if (find_share(rmp, rmp->mp_ino, rmp->mp_dev, rmp->mp_ctime) == NULL) {
00191
00192 free_mem(rmp->mp_seg[T].mem_phys, rmp->mp_seg[T].mem_len);
00193 }
00194
00195 free_mem(rmp->mp_seg[D].mem_phys,
00196 rmp->mp_seg[S].mem_vir
00197 + rmp->mp_seg[S].mem_len - rmp->mp_seg[D].mem_vir);
00198
00199
00200 rmp->mp_exitstatus = (char) exit_status;
00201
00202 pidarg = p_mp->mp_wpid;
00203 parent_waiting = p_mp->mp_flags & WAITING;
00204 right_child =
00205 (pidarg == -1 || pidarg == rmp->mp_pid || -pidarg == rmp->mp_procgrp);
00206
00207 if (parent_waiting && right_child) {
00208 cleanup(rmp);
00209 } else {
00210 rmp->mp_flags = IN_USE|ZOMBIE;
00211 sig_proc(p_mp, SIGCHLD);
00212 }
00213
00214
00215 for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
00216 if (rmp->mp_flags & IN_USE && rmp->mp_parent == proc_nr) {
00217
00218 rmp->mp_parent = INIT_PROC_NR;
00219 parent_waiting = mproc[INIT_PROC_NR].mp_flags & WAITING;
00220 if (parent_waiting && (rmp->mp_flags & ZOMBIE)) cleanup(rmp);
00221 }
00222 }
00223
00224
00225 if (procgrp != 0) check_sig(-procgrp, SIGHUP);
00226 }
00227
00228
00229
00230
00231 PUBLIC int do_waitpid()
00232 {
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 register struct mproc *rp;
00243 int pidarg, options, children;
00244
00245
00246 pidarg = (call_nr == WAIT ? -1 : m_in.pid);
00247 options = (call_nr == WAIT ? 0 : m_in.sig_nr);
00248 if (pidarg == 0) pidarg = -mp->mp_procgrp;
00249
00250
00251
00252
00253
00254
00255 children = 0;
00256 for (rp = &mproc[0]; rp < &mproc[NR_PROCS]; rp++) {
00257 if ( (rp->mp_flags & IN_USE) && rp->mp_parent == who_p) {
00258
00259 if (pidarg > 0 && pidarg != rp->mp_pid) continue;
00260 if (pidarg < -1 && -pidarg != rp->mp_procgrp) continue;
00261
00262 children++;
00263 if (rp->mp_flags & ZOMBIE) {
00264
00265 cleanup(rp);
00266 return(SUSPEND);
00267 }
00268 if ((rp->mp_flags & STOPPED) && rp->mp_sigstatus) {
00269
00270 mp->mp_reply.reply_res2 = 0177|(rp->mp_sigstatus << 8);
00271 rp->mp_sigstatus = 0;
00272 return(rp->mp_pid);
00273 }
00274 }
00275 }
00276
00277
00278 if (children > 0) {
00279
00280 if (options & WNOHANG) return(0);
00281 mp->mp_flags |= WAITING;
00282 mp->mp_wpid = (pid_t) pidarg;
00283 return(SUSPEND);
00284 } else {
00285
00286 return(ECHILD);
00287 }
00288 }
00289
00290
00291
00292
00293 PRIVATE void cleanup(child)
00294 register struct mproc *child;
00295 {
00296
00297
00298
00299 struct mproc *parent = &mproc[child->mp_parent];
00300 int exitstatus;
00301
00302
00303 exitstatus = (child->mp_exitstatus << 8) | (child->mp_sigstatus & 0377);
00304 parent->mp_reply.reply_res2 = exitstatus;
00305 setreply(child->mp_parent, child->mp_pid);
00306 parent->mp_flags &= ~WAITING;
00307
00308
00309 child->mp_pid = 0;
00310 child->mp_flags = 0;
00311 child->mp_child_utime = 0;
00312 child->mp_child_stime = 0;
00313 procs_in_use--;
00314 }
00315