static void ps_print_level(int level, proc_p p) { /* pid ppid envid pgrp session xstat stat flag nxch */ #define MAXLEVEL 4 int i; int epilogue_count, yield_count; #if 0 char state[] = "XIRSHZ"; #endif if (level == -1) { printf("PID "); for (i = 0; i < MAXLEVEL; i++) printf(" "); #if 0 printf("PPID PG SES "); printf("sta xst flag nx "); printf("ticks ctxcnt eip name\n"); #else printf (" TICKS\tCTXCNT\tEIP\t\tNAME\t\tEID\n\n"); #endif return; } if (level > MAXLEVEL) level = MAXLEVEL; for (i = 0; i < level; i++) printf(" "); if (p == NULL) {printf(" null proc entry\n");return;} printf("%-3d",p->p_pid); for (i = level; i <= MAXLEVEL; i++) printf(" "); #if 0 printf("%3d ",(p->p_pptr) ? p->p_pptr->p_pid : -1); printf("%3d ",(p->p_pgrp) ? p->p_pgrp->pg_id : -1); printf("%3d ",(p->p_session->s_leader) ? p->p_session->s_leader->p_pid : -1); printf("%c %3d %4s %3d ", state[p->p_stat], p->p_xstat, ps_get_flags(p->p_flag), p->nxchildren); #endif epilogue_count = 0; yield_count = 0; get_counts(p->envid, &epilogue_count, &yield_count); printf("\t%5d\t%6d\t%08x\t%.10s", __envs[envidx(p->envid)].env_ticks, __envs[envidx(p->envid)].env_ctxcnt, /* epilogue_count, */ (p->envid == __envid || p->p_stat == SZOMB) ? 0 : get_eip(p->envid), ps_get_comm(p->envid,1)); if (strlen (ps_get_comm (p->envid,1)) < 8) printf ("\t\t"); else printf ("\t"); printf ("%d\n", p->envid); for (p = p->p_children.lh_first; p != 0; p = p->p_sibling.le_next) { ps_print_level(level+1,p); } }
static unsigned int get_eip (u_int envid) { unsigned int esp; unsigned int eip = 0; struct Env *e = (struct Env *)&__envs[envidx (envid)]; esp = e->env_tf.tf_esp + 44; /* check if pid is saving its fpu state */ { struct Uenv cu; int ret; if ((ret = sys_rdu(CAP_ROOT,e->env_id,&cu)) >= 0) { if (cu.u_fpu) esp += FPU_SAVE_SZ; } /* if this fails, read_write_memory will fail too. */ } eip = read_write_memory (PT_READ_D, envid, esp, 0); return (eip); }
void ae_eth_init() { int i,fid; extern void print_physical(int page); if (envidx(__envid) == 1) { AllocAshShareRegion(); ASN.nfree = 0; for (i = 0; i < NENTRY; i++) { ASN.ae_packets[i].recv.r[0].data = &asn.ash_pkt_data[i * MAXPKT]; ASN.ae_packets[i].recv.r[0].sz = MAXPKT; ASN.ae_packets[i].recv.n = 1; ASN.nfree++; ae_ash_append_pkt(&asn.ash_alloc_pkt, &ASN.ae_packets[i]); } for (fid = 0; fid < DPF_MAXFILT; fid++) { FID_HEAD_QUEUE = 0; FID_TAIL_QUEUE = 0; } } }
/* everything is based on this exec, we have an extra flag (_EXEC_EXECONLY) to differentiate between the exec and fork_exec families. the difference is that the latter forks and then execs the process thereby returning in the parent */ static int fork_execve0(const char *path, char *const argv[], char * const envptr[], int fd, u_int flags) { u_int k = 0; int target_cpu = 0; struct Uenv cu; int NewPid = 0; int envid = 0; /* XXX -- init to supress warning */ char **old_argv = (char **)argv; int r, exec_format; struct Env e; OSCALLENTER(OSCALL_execve); /* verify executable permission */ if (!(flags & _EXEC_USE_FD) && access(path, X_OK) == -1) { /* access will set errno */ r = -errno; goto err; } if (!(envid = sys_env_alloc (0, &r))) { fprintf(stderr,"could not sys_env_alloc\n"); r = -ENOEXEC; goto err; } e = __envs[envidx(envid)]; if ((exec_format = fork_execve0_part2(path, argv, envptr, &e, fd, flags)) < 0) goto err_env_free; /* write environment */ if ((r = sys_wrenv (k, envid, &e)) < 0) { kprintf ("sys_wrenv failed\n"); r = -ENOEXEC; goto err; } if (ExecuteOnExecHandlers(k, envid, flags & _EXEC_EXECONLY) == -1) { fprintf(stderr,"cleanup code not done yet\n"); assert(-1); } #ifdef PROCESS_TABLE if (flags & _EXEC_EXECONLY) { /* because true exec */ NewPid = getpid(); dlockputs(__PROCD_LD,"fork_execve0 get lock "); EXOS_LOCK(PROCINFO_LOCK); dlockputs(__PROCD_LD,"... got lock\n"); EnterCritical (); ProcChangeEnv(NewPid,envid); EXOS_UNLOCK(PROCINFO_LOCK); dlockputs(__PROCD_LD,"fork_execve0 release lock\n"); ExitCritical (); } else { /* because we are forking */ NewPid = AllocateFreePid (envid); } cu = UAREA; if (!execonly) { AddProcEntry (&cu, (char *)path, (char **)argv, NewPid, UAREA.pid); if ((cu.parent_slot = GetChildSlot (NewPid)) < 0) { r = -ENOEXEC; goto err_env_free; } } else { /* TO TOM: what do we do this for? strncpy (UAREA.name, (char*)(((u_int)argv[0]) + ARGV_START_LOCAL - ARGV_START), U_NAMEMAX-1); UAREA.name[U_NAMEMAX-1] = '\0'; */ } /* XXX -- on an exec we'll forget to unref our children's pids */ /* TO TOM: shouldnt this clearchildinfo be at the top */ ClearChildInfo (&cu); #else #ifdef PROCD if (flags & _EXEC_EXECONLY) { NewPid = getpid(); /* only register us if we are of the right format */ if (exec_format == EXEC_EXOS_AOUT) proc_exec(envid); } else { NewPid = proc_fork(envid); } cu = UAREA; //kprintf("NewPid %d envid: %d %s proc_%s: (%d) -> %d\n", //NewPid,__envid,execonly ? "exec" : "fork",path,envid,NewPid); #else NewPid = envid; #endif /* PROCD */ #endif /* PROCESS_TABLE */ strncpy (cu.name, path, U_NAMEMAX-1); cu.name[U_NAMEMAX-1] = '\0'; cu.u_fpu = 0; cu.u_in_critical = 0; cu.u_status = U_RUN; cu.u_entprologue = e.env_tf.tf_eip; cu.u_entepilogue = e.env_tf.tf_eip; cu.u_entfault = 0; cu.u_entipc1 = 0; cu.u_entipc2 = 0; cu.u_ppc = 0; #ifdef PROCESS_TABLE cu.u_chld_state_chng = 0; #endif /* PROCESS_TABLE */ cu.u_next_timeout = 0; cu.u_in_pfault = 0; cu.u_donate = -1; cu.u_yield_count = 0; cu.u_epilogue_count = 0; cu.u_epilogue_abort_count = 0; STOPP(misc,step7); ISTART(misc,step8); cu.u_start_kern_call_counting = 0; if ((r = sys_wru (0, envid, &cu)) < 0) { fprintf (stderr,"sys_wru failed\n"); r = -ENOEXEC; goto err_env_free; } target_cpu = 0; #ifdef __SMP__ if (strncmp(path,"_cpu",4)==0 && strlen(path)>4) { target_cpu = path[4]-'0'; if (target_cpu<0 || target_cpu>sys_get_num_cpus()-1) target_cpu = 0; } #endif /* we can't do this until all the child state is setup */ if ((r = sys_quantum_alloc (k, -1, target_cpu, envid)) < 0) { fprintf (stderr,"could not alloc quantum\n"); r = -ENOEXEC; goto err_env_free; } /* if we're doing a true unix exec and not a combined fork/spawn we need to destroy ourselves since our child should have replaced us. */ if (flags & _EXEC_EXECONLY) { /* if not an exos format, should not expect normal child behaviors, so we * just quit from procd to avoid any hanging... */ if (exec_format == EXEC_SIMPLE) proc_exit(0); /* we die anyways, so free quantum and env */ ProcessFreeQuanta(__envid); sys_env_free (0, __envid); } if (old_argv != argv) __free((char**)argv); OSCALLEXIT(OSCALL_execve); return (NewPid); err_env_free: ProcessFreeQuanta(__envid); sys_env_free (k, envid); err: if (old_argv != argv) __free((char**)argv); errno = -r; OSCALLEXIT(OSCALL_execve); return -1; }
/* could implement tsleep in terms of following tsleep_pred */ int tsleep (void *chan, int pri, char *wmesg, int ticks) { #define PREDSZ 32 struct wk_term t[PREDSZ]; int sz = 0; int sig = 0; int catch = pri & PCATCH; void **wchan; int ret, i, CriticalLevels; unsigned long long dest_ticks = ticks; retry: sz = 0; d0printf("%d tsleep chan: %p, catch: %d, ticks: %d (lbolt? %d)\n", getpid(),chan, catch ?1:0, ticks, chan == &lbolt); global_ftable->counter0++; if (chan == &lbolt) global_ftable->counter2++; wchan = &synch_table->wchan[envidx(__envid)]; *wchan = chan; /* for timeout */ if (dest_ticks) { dest_ticks += __sysinfo.si_system_ticks; sz += wk_mksleep_pred(t, dest_ticks); /* t is fine since it is first */ sz = wk_mkop(sz, t, WK_OR); } /* for channel */ if (chan != &lbolt) { sz = wk_mkvar (sz, t, wk_phys (wchan), 0); sz = wk_mkimm (sz, t, 0); sz = wk_mkop (sz, t, WK_EQ); } else { /* sleep for 0.5 seconds */ sz += wk_mksleep_pred(&t[sz],(500000/__sysinfo.si_rate) + __sysinfo.si_system_ticks); } /* for signals */ if (catch) { //kprintf("%d tsleep interruptible (sigready? %d)\n",getpid(),__issigready()); if ((sig = __issigready())) goto resume; sz = wk_mkop(sz, t, WK_OR); sz += wk_mksig_pred(&t[sz]); } assert(sz <= PREDSZ); /* make sure when sleeping on lbolt => no ticks */ assert(!(chan == &lbolt && dest_ticks != 0)); /* Leave and then Enter Critical Region */ i = CriticalLevels = CriticalNesting(); assert(i >= 0); while (i-- > 0) ExitCritical(); assert(CriticalNesting() == 0); wk_waitfor_pred (t, sz); i = 0; while (i++ < CriticalLevels) EnterCritical(); assert(CriticalLevels == CriticalNesting()); resume: ret = 0; if (catch && (sig != 0 || (sig = __issigready()))) { /* there is a signal ready */ //kprintf("%d tsleep interrupted by a signal: %d (%s)\n",getpid(),sig,sys_signame[sig]); if (__issigstopping(sig)) { __signal_stop_process(sig); goto retry; } if (__issigrestart(sig)) ret = ERESTART; else ret = EINTR; goto done; } if (chan != &lbolt && dest_ticks && __sysinfo.si_system_ticks > dest_ticks) { ret = EWOULDBLOCK; } done: d0printf("%d tsleep ret: %d chan: %p, catch: %d, dest_ticks: %qu (lbolt? %d) -> %d\n", getpid(),ret,chan, catch ?1:0, dest_ticks, chan == &lbolt, ret); /* clear waiting channel */ *wchan = 0; return ret; }