/* * Swap out the memory of a process to make room * for something else. */ int swapout(ptptr p) { uint16_t blk; uint16_t map; if (!p->p_page) panic("process already swapped!\n"); #ifdef DEBUG kprintf("Swapping out %x (%d)\n", p, p->p_page); #endif /* We mever swap the live process so the second page is always page 6 */ if (low_bank == p) panic("swapout"); /* Are we out of swap ? */ map = swapmap_alloc(); if (map == 0) return ENOMEM; blk = map * SWAP_SIZE; /* Write the top page and the included uarea stash to disk */ swapwrite(SWAPDEV, blk, 0x4000, 0xC000, p->p_page); /* Write the alt bank via the top 16K window */ swapwrite(SWAPDEV, blk + 0x20, 0x4000, 0xC000, 6); /* Release the mapping */ pagemap_free(p); p->p_page = 0; p->p_page2 = map; #ifdef DEBUG kprintf("%x: swapout done %d\n", p, p->p_page); #endif return 0; }
/* Called on execve */ int pagemap_realloc(usize_t size) { unsigned int proc = udata.u_page; struct memblk *mb; pagemap_free(udata.u_ptab); store[proc] = mem[proc] = mem_alloc(); mb = &mem[proc]->memblk[0]; mb->start = kmalloc(size); mb->end = mb->start + size; if (mb->start == NULL) return ENOMEM; return 0; }
int swapout(ptptr p) { uint16_t page = p->p_page; uint16_t blk; uint16_t map; uint16_t base = SWAPBASE; uint16_t size = (0x4000 - SWAPBASE) >> 9; uint8_t *pt = (uint8_t *)&p->page; if (page) panic("process already swapped!\n"); #ifdef DEBUG kprintf("Swapping out %x (%d)\n", p, p->p_page); #endif /* Are we out of swap ? */ map = swapmap_alloc(); if (map == 0) return ENOMEM; blk = map * SWAP_SIZE; #ifdef CONFIG_HAS_LOW_PAGE swapwrite(SWAPDEV, blk, 1, 0x0000); blk++; #endif /* Write the app (and possibly the uarea etc..) to disk */ for (i = 0; i < 4; i ++) { swapwrite(SWAPDEV, blk, size, base, *pt++); base += 0x4000; /* Last bank is determined by SWAP SIZE. We do the maths in 512's (0x60 = 0xC000) */ if (i == 3) size = SWAP_SIZE_EXCL_ZP - 0x60; else size = 0x20; } pagemap_free(p); p->p_page = 0; p->p_page2 = map; #ifdef DEBUG kprintf("%x: swapout done %d\n", p, p->p_page); #endif return 0; }
/* * Swap out the memory of a process to make room * for something else */ int swapout(ptptr p) { uint16_t page = p->p_page; uint16_t blk; uint16_t map; #ifdef UDATA_SWAPSIZE uint8_t *ptr; #endif swapproc = p; if (page) { #ifdef DEBUG kprintf("Swapping out %x (%d)\n", p, p->p_page); #endif /* Are we out of swap ? */ if (swapptr == 0) return ENOMEM; swap_flush_cache(p); map = swapmap[--swapptr]; blk = map * SWAP_SIZE; #ifdef UDATA_SWAPSIZE /* Allow the platform to do things like handle the uarea stash */ ptr = swapout_prepare_uarea(p); /* Write to disk if the platform asks us */ if (ptr) swapwrite(SWAPDEV, blk, UDATA_SWAPSIZE, ptr); #endif /* Write the app (and possibly the uarea etc..) to disk */ swapwrite(SWAPDEV, blk + UDATA_BLOCKS, SWAPTOP - SWAPBASE, SWAPBASE); pagemap_free(p); p->p_page = 0; p->p_page2 = map; #ifdef DEBUG kprintf("%x: swapout done %d\n", p, p->p_page); #endif } #ifdef DEBUG else kprintf("%x: process already swapped!\n", p); #endif return 0; }
arg_t _fork(void) { // allocate new process struct p_tab *new_process; arg_t r; irqflags_t irq; if (flags) { /* Brief period of grace... */ // udata.u_error = EINVAL; // return -1; kputs("warning: rebuild libc\n"); } new_process = ptab_alloc(); if (!new_process) return -1; irq = di(); // we're going to run our child process next, so mark this process as being ready to run udata.u_ptab->p_status = P_READY; // kick off the new process (the bifurcation happens inside here, we returns in both // the child and parent contexts) r = dofork(new_process); #ifdef DEBUG kprintf("Dofork %x (n %x)returns %d\n", udata.u_ptab, new_process, r); kprintf("udata.u_page %d p_page %d\n", udata.u_page, udata.u_ptab->p_page); kprintf("parent %x\n", udata.u_ptab->p_pptr); #endif // if we fail this returns -1 if (r == -1) { udata.u_ptab->p_status = P_RUNNING; pagemap_free(new_process); new_process->p_status = P_EMPTY; udata.u_error = ENOMEM; nproc--; nready--; } irqrestore(irq); return r; }
void doexit(int16_t val, int16_t val2) { int16_t j; ptptr p; irqflags_t irq; #ifdef DEBUG kprintf("process %d exiting\n", udata.u_ptab->p_pid); kprintf ("udata.u_page %u, udata.u_ptab %x, udata.u_ptab->p_page %u\n", udata.u_page, udata.u_ptab, udata.u_ptab->p_page); #endif if (udata.u_ptab->p_pid == 1) panic("killed init"); _sync(); /* Not necessary, but a good idea. */ irq = di(); /* Discard our memory before we blow away and reuse the memory */ pagemap_free(udata.u_ptab); for (j = 0; j < UFTSIZE; ++j) { if (udata.u_files[j] != NO_FILE) doclose(j); } udata.u_ptab->p_exitval = (val << 8) | (val2 & 0xff); i_deref(udata.u_cwd); i_deref(udata.u_root); /* Stash away child's execution tick counts in process table, * overlaying some no longer necessary stuff. * * Pedantically POSIX says we should do this at the point of wait() */ udata.u_utime += udata.u_cutime; udata.u_stime += udata.u_cstime; memcpy(&(udata.u_ptab->p_priority), &udata.u_utime, 2 * sizeof(clock_t)); for (p = ptab; p < ptab_end; ++p) { if (p->p_status == P_EMPTY || p == udata.u_ptab) continue; /* Set any child's parents to our parent */ if (p->p_pptr == udata.u_ptab) p->p_pptr = udata.u_ptab->p_pptr; /* Send SIGHUP to any pgrp members and remove them from our pgrp */ if (p->p_pgrp == udata.u_ptab->p_pid) { p->p_pgrp = 0; ssig(p, SIGHUP); } } tty_exit(); irqrestore(irq); #ifdef DEBUG kprintf ("udata.u_page %u, udata.u_ptab %x, udata.u_ptab->p_page %u\n", udata.u_page, udata.u_ptab, udata.u_ptab->p_page); #endif #ifdef CONFIG_ACCT acctexit(p); #endif udata.u_page = 0xFFFFU; udata.u_page2 = 0xFFFFU; /* FIXME: send SIGCLD here */ /* FIXME: POSIX.1 says that SIG_IGN for SIGCLD means don't go zombie, just clean up as we go */ /* Wake up a waiting parent, if any. */ wakeup((char *) udata.u_ptab->p_pptr); udata.u_ptab->p_status = P_ZOMBIE; nready--; nproc--; switchin(getproc()); panic("doexit: won't exit"); }
void doexit(uint16_t val) { int16_t j; ptptr p; irqflags_t irq; #ifdef DEBUG kprintf("process %d exiting\n", udata.u_ptab->p_pid); kprintf ("udata.u_page %u, udata.u_ptab %x, udata.u_ptab->p_page %u\n", udata.u_page, udata.u_ptab, udata.u_ptab->p_page); #endif if (udata.u_ptab->p_pid == 1) panic(PANIC_KILLED_INIT); sync(); /* Not necessary, but a good idea. */ irq = di(); /* Discard our memory before we blow away and reuse the memory */ pagemap_free(udata.u_ptab); for (j = 0; j < UFTSIZE; ++j) { if (udata.u_files[j] != NO_FILE) doclose(j); } udata.u_ptab->p_exitval = val; i_deref(udata.u_cwd); i_deref(udata.u_root); /* Stash away child's execution tick counts in process table, * overlaying some no longer necessary stuff. * * Pedantically POSIX says we should do this at the point of wait() */ udata.u_utime += udata.u_cutime; udata.u_stime += udata.u_cstime; memcpy(&(udata.u_ptab->p_priority), &udata.u_utime, 2 * sizeof(clock_t)); for (p = ptab; p < ptab_end; ++p) { if (p->p_status == P_EMPTY || p == udata.u_ptab) continue; /* Set any child's parents to our parent */ /* FIXME: do we need to wakeup the parent if we do this ? */ if (p->p_pptr == udata.u_ptab) p->p_pptr = udata.u_ptab->p_pptr; /* Send SIGHUP to any pgrp members and remove them from our pgrp */ if (p->p_pgrp == udata.u_ptab->p_pid) { p->p_pgrp = 0; ssig(p, SIGHUP); ssig(p, SIGCONT); } } tty_exit(); irqrestore(irq); #ifdef DEBUG kprintf ("udata.u_page %u, udata.u_ptab %x, udata.u_ptab->p_page %u\n", udata.u_page, udata.u_ptab, udata.u_ptab->p_page); #endif #ifdef CONFIG_ACCT acctexit(p); #endif udata.u_page = 0xFFFFU; udata.u_page2 = 0xFFFFU; signal_parent(udata.u_ptab->p_pptr); nready--; nproc--; switchin(getproc()); panic(PANIC_DOEXIT); }
void doexit(uint16_t val) { int16_t j; ptptr p; irqflags_t irq; #ifdef DEBUG kprintf("process %d exiting %d\n", udata.u_ptab->p_pid, val); kprintf ("udata.u_page %u, udata.u_ptab %p, udata.u_ptab->p_page %u\n", udata.u_page, udata.u_ptab, udata.u_ptab->p_page); #endif if (udata.u_ptab->p_pid == 1) panic(PANIC_KILLED_INIT); sync(); /* Not necessary, but a good idea. */ irq = di(); /* We are exiting, hold all signals (they will never be delivered). If we don't do this we might take a signal while exiting which would be ... unfortunate */ udata.u_ptab->p_held = 0xFFFFFFFFUL; udata.u_cursig = 0; /* Discard our memory before we blow away and reuse the memory */ pagemap_free(udata.u_ptab); for (j = 0; j < UFTSIZE; ++j) { if (udata.u_files[j] != NO_FILE) doclose(j); } udata.u_ptab->p_exitval = val; i_deref(udata.u_cwd); i_deref(udata.u_root); /* Stash away child's execution tick counts in process table, * overlaying some no longer necessary stuff. * * Pedantically POSIX says we should do this at the point of wait() */ udata.u_utime += udata.u_cutime; udata.u_stime += udata.u_cstime; memcpy(&(udata.u_ptab->p_priority), &udata.u_utime, 2 * sizeof(clock_t)); for (p = ptab; p < ptab_end; ++p) { if (p->p_status == P_EMPTY || p == udata.u_ptab) continue; /* Set any child's parents to init */ if (p->p_pptr == udata.u_ptab) { p->p_pptr = ptab; /* ptab is always init */ /* Suppose our child is a zombie and init has SIGCLD blocked */ if (ptab[0].p_ignored & (1UL << SIGCHLD)) { p->p_status = P_EMPTY; } else { ssig(&ptab[0], SIGCHLD); wakeup(&ptab[0]); } } /* Send SIGHUP to any pgrp members and remove them from our pgrp */ if (p->p_pgrp == udata.u_ptab->p_pid) { p->p_pgrp = 0; ssig(p, SIGHUP); ssig(p, SIGCONT); } } tty_exit(); irqrestore(irq); #ifdef DEBUG kprintf ("udata.u_page %u, udata.u_ptab %p, udata.u_ptab->p_page %u\n", udata.u_page, udata.u_ptab, udata.u_ptab->p_page); #endif #ifdef CONFIG_ACCT acctexit(p); #endif udata.u_page = 0xFFFFU; udata.u_page2 = 0xFFFFU; signal_parent(udata.u_ptab->p_pptr); nready--; nproc--; switchin(getproc()); panic(PANIC_DOEXIT); }