From: Ben Gras Date: Wed, 1 Jun 2005 09:40:42 +0000 (+0000) Subject: Removed mm files (obsolete; it's pm now) X-Git-Tag: v3.1.0~783 X-Git-Url: http://zhaoyanbai.com/repos/Bv9ARM.ch03.html?a=commitdiff_plain;h=25d2f4666c47b6cf3923fa92b11bd630a2ed8a3d;p=minix.git Removed mm files (obsolete; it's pm now) --- diff --git a/servers/mm/Makefile b/servers/mm/Makefile deleted file mode 100644 index 61983bb44..000000000 --- a/servers/mm/Makefile +++ /dev/null @@ -1,134 +0,0 @@ -# Makefile for Memory Manager (MM) -SERVER = mm - -# directories -u = /usr -i = $u/include -s = $i/sys -h = $i/minix -k = $u/src/kernel - -# programs, flags, etc. -CC = exec cc -CFLAGS = -I$i -LDFLAGS = -i - -OBJ = main.o forkexit.o break.o exec.o procutils.o \ - signal.o alloc.o utility.o table.o trace.o getset.o misc.o - -# build local binary -all build: $(SERVER) -$(SERVER): $(OBJ) - $(CC) -o $@ $(LDFLAGS) $(OBJ) -lsys -lutils - install -S 256w $@ - -# install with other servers -install: /usr/sbin/servers/$(SERVER) -/usr/sbin/servers/$(SERVER): $(SERVER) - install -o root -cs $? $@ - -# clean up local files -clean: - rm -f $(SERVER) *.o *.bak - -# dependencies -a = mm.h $h/config.h $s/types.h $h/const.h $h/type.h \ - $i/ansi.h $i/fcntl.h $i/unistd.h $h/syslib.h \ - $i/limits.h $i/errno.h const.h type.h proto.h glo.h - -alloc.o: $a -alloc.o: $i/signal.h -alloc.o: $h/com.h -alloc.o: $h/callnr.h -alloc.o: mproc.h -alloc.o: $k/type.h -alloc.o: $k/const.h - -break.o: $a -break.o: $i/signal.h -break.o: mproc.h -break.o: param.h - -exec.o: $a -exec.o: $s/stat.h -exec.o: $h/callnr.h -exec.o: $h/com.h -exec.o: $i/a.out.h -exec.o: $i/signal.h -exec.o: $i/string.h -exec.o: mproc.h -exec.o: param.h - -forkexit.o: $a -forkexit.o: $s/wait.h -forkexit.o: $h/callnr.h -forkexit.o: $h/com.h -forkexit.o: $h/utils.h -forkexit.o: $i/signal.h -forkexit.o: mproc.h -forkexit.o: param.h - -getset.o: $a -getset.o: $h/callnr.h -getset.o: $i/signal.h -getset.o: mproc.h -getset.o: param.h - -main.o: $a -main.o: $h/callnr.h -main.o: $h/com.h -main.o: $i/signal.h -main.o: $i/fcntl.h -main.o: $h/ioctl.h -main.o: $s/ioc_memory.h -main.o: $h/utils.h -main.o: mproc.h -main.o: param.h - -misc.o: $a -misc.o: $h/callnr.h -misc.o: $h/utils.h -misc.o: $i/signal.h -misc.o: $h/ioctl.h -misc.o: $s/svrctl.h -misc.o: mproc.h -misc.o: param.h - -procutils.o: $a -procutils.o: $i/timers.h -procutils.o: $i/string.h -procutils.o: $k/const.h -procutils.o: $k/type.h -procutils.o: $k/proc.h - -signal.o: $a -signal.o: $s/stat.h -signal.o: $h/callnr.h -signal.o: $h/utils.h -signal.o: $h/com.h -signal.o: $i/signal.h -signal.o: $s/sigcontext.h -signal.o: $i/string.h -signal.o: mproc.h -signal.o: param.h - -table.o: $a -table.o: $h/callnr.h -table.o: $i/signal.h -table.o: mproc.h -table.o: param.h - -trace.o: $a -trace.o: $h/com.h -trace.o: $s/ptrace.h -trace.o: $i/signal.h -trace.o: mproc.h -trace.o: param.h - -utility.o: $a -utility.o: $s/stat.h -utility.o: $h/callnr.h -utility.o: $h/com.h -utility.o: $i/fcntl.h -utility.o: $i/signal.h -utility.o: mproc.h diff --git a/servers/mm/alloc.c b/servers/mm/alloc.c deleted file mode 100644 index 91d0e32f9..000000000 --- a/servers/mm/alloc.c +++ /dev/null @@ -1,428 +0,0 @@ -/* This file is concerned with allocating and freeing arbitrary-size blocks of - * physical memory on behalf of the FORK and EXEC system calls. The key data - * structure used is the hole table, which maintains a list of holes in memory. - * It is kept sorted in order of increasing memory address. The addresses - * it contains refers to physical memory, starting at absolute address 0 - * (i.e., they are not relative to the start of MM). During system - * initialization, that part of memory containing the interrupt vectors, - * kernel, and MM are "allocated" to mark them as not available and to - * remove them from the hole list. - * - * The entry points into this file are: - * alloc_mem: allocate a given sized chunk of memory - * free_mem: release a previously allocated chunk of memory - * mem_init: initialize the tables when MM start up - * max_hole: returns the largest hole currently available - */ - -#include "mm.h" -#include -#include -#include -#include "mproc.h" -#include "../../kernel/const.h" -#include "../../kernel/type.h" - -#define NR_HOLES (2*NR_PROCS) /* max # entries in hole table */ -#define NIL_HOLE (struct hole *) 0 - -PRIVATE struct hole { - struct hole *h_next; /* pointer to next entry on the list */ - phys_clicks h_base; /* where does the hole begin? */ - phys_clicks h_len; /* how big is the hole? */ -} hole[NR_HOLES]; - -PRIVATE struct hole *hole_head; /* pointer to first hole */ -PRIVATE struct hole *free_slots;/* ptr to list of unused table slots */ -#if ENABLE_SWAP -PRIVATE int swap_fd = -1; /* file descriptor of open swap file/device */ -PRIVATE u32_t swap_offset; /* offset to start of swap area on swap file */ -PRIVATE phys_clicks swap_base; /* memory offset chosen as swap base */ -PRIVATE phys_clicks swap_maxsize;/* maximum amount of swap "memory" possible */ -PRIVATE struct mproc *in_queue; /* queue of processes wanting to swap in */ -PRIVATE struct mproc *outswap = &mproc[LOW_USER]; /* outswap candidate? */ -#else /* !SWAP */ -#define swap_base ((phys_clicks) -1) -#endif /* !SWAP */ - -FORWARD _PROTOTYPE( void del_slot, (struct hole *prev_ptr, struct hole *hp) ); -FORWARD _PROTOTYPE( void merge, (struct hole *hp) ); -#if ENABLE_SWAP -FORWARD _PROTOTYPE( int swap_out, (void) ); -#else -#define swap_out() (0) -#endif - -/*===========================================================================* - * alloc_mem * - *===========================================================================*/ -PUBLIC phys_clicks alloc_mem(clicks) -phys_clicks clicks; /* amount of memory requested */ -{ -/* Allocate a block of memory from the free list using first fit. The block - * consists of a sequence of contiguous bytes, whose length in clicks is - * given by 'clicks'. A pointer to the block is returned. The block is - * always on a click boundary. This procedure is called when memory is - * needed for FORK or EXEC. Swap other processes out if needed. - */ - - register struct hole *hp, *prev_ptr; - phys_clicks old_base; - - do { - hp = hole_head; - while (hp != NIL_HOLE && hp->h_base < swap_base) { - if (hp->h_len >= clicks) { - /* We found a hole that is big enough. Use it. */ - old_base = hp->h_base; /* remember where it started */ - hp->h_base += clicks; /* bite a piece off */ - hp->h_len -= clicks; /* ditto */ - - /* Delete the hole if used up completely. */ - if (hp->h_len == 0) del_slot(prev_ptr, hp); - - /* Return the start address of the acquired block. */ - return(old_base); - } - - prev_ptr = hp; - hp = hp->h_next; - } - } while (swap_out()); /* try to swap some other process out */ - return(NO_MEM); -} - -/*===========================================================================* - * free_mem * - *===========================================================================*/ -PUBLIC void free_mem(base, clicks) -phys_clicks base; /* base address of block to free */ -phys_clicks clicks; /* number of clicks to free */ -{ -/* Return a block of free memory to the hole list. The parameters tell where - * the block starts in physical memory and how big it is. The block is added - * to the hole list. If it is contiguous with an existing hole on either end, - * it is merged with the hole or holes. - */ - - register struct hole *hp, *new_ptr, *prev_ptr; - - if (clicks == 0) return; - if ( (new_ptr = free_slots) == NIL_HOLE) panic("Hole table full", NO_NUM); - new_ptr->h_base = base; - new_ptr->h_len = clicks; - free_slots = new_ptr->h_next; - hp = hole_head; - - /* If this block's address is numerically less than the lowest hole currently - * available, or if no holes are currently available, put this hole on the - * front of the hole list. - */ - if (hp == NIL_HOLE || base <= hp->h_base) { - /* Block to be freed goes on front of the hole list. */ - new_ptr->h_next = hp; - hole_head = new_ptr; - merge(new_ptr); - return; - } - - /* Block to be returned does not go on front of hole list. */ - while (hp != NIL_HOLE && base > hp->h_base) { - prev_ptr = hp; - hp = hp->h_next; - } - - /* We found where it goes. Insert block after 'prev_ptr'. */ - new_ptr->h_next = prev_ptr->h_next; - prev_ptr->h_next = new_ptr; - merge(prev_ptr); /* sequence is 'prev_ptr', 'new_ptr', 'hp' */ -} - -/*===========================================================================* - * del_slot * - *===========================================================================*/ -PRIVATE void del_slot(prev_ptr, hp) -register struct hole *prev_ptr; /* pointer to hole entry just ahead of 'hp' */ -register struct hole *hp; /* pointer to hole entry to be removed */ -{ -/* Remove an entry from the hole list. This procedure is called when a - * request to allocate memory removes a hole in its entirety, thus reducing - * the numbers of holes in memory, and requiring the elimination of one - * entry in the hole list. - */ - - if (hp == hole_head) - hole_head = hp->h_next; - else - prev_ptr->h_next = hp->h_next; - - hp->h_next = free_slots; - free_slots = hp; -} - -/*===========================================================================* - * merge * - *===========================================================================*/ -PRIVATE void merge(hp) -register struct hole *hp; /* ptr to hole to merge with its successors */ -{ -/* Check for contiguous holes and merge any found. Contiguous holes can occur - * when a block of memory is freed, and it happens to abut another hole on - * either or both ends. The pointer 'hp' points to the first of a series of - * three holes that can potentially all be merged together. - */ - - register struct hole *next_ptr; - - /* If 'hp' points to the last hole, no merging is possible. If it does not, - * try to absorb its successor into it and free the successor's table entry. - */ - if ( (next_ptr = hp->h_next) == NIL_HOLE) return; - if (hp->h_base + hp->h_len == next_ptr->h_base) { - hp->h_len += next_ptr->h_len; /* first one gets second one's mem */ - del_slot(hp, next_ptr); - } else { - hp = next_ptr; - } - - /* If 'hp' now points to the last hole, return; otherwise, try to absorb its - * successor into it. - */ - if ( (next_ptr = hp->h_next) == NIL_HOLE) return; - if (hp->h_base + hp->h_len == next_ptr->h_base) { - hp->h_len += next_ptr->h_len; - del_slot(hp, next_ptr); - } -} - -/*===========================================================================* - * mem_init * - *===========================================================================*/ -PUBLIC void mem_init(free) -phys_clicks *free; /* memory size summaries */ -{ -/* Initialize hole lists. There are two lists: 'hole_head' points to a linked - * list of all the holes (unused memory) in the system; 'free_slots' points to - * a linked list of table entries that are not in use. Initially, the former - * list has one entry for each chunk of physical memory, and the second - * list links together the remaining table slots. As memory becomes more - * fragmented in the course of time (i.e., the initial big holes break up into - * smaller holes), new table slots are needed to represent them. These slots - * are taken from the list headed by 'free_slots'. - */ - struct memory mem[NR_MEMS]; /* chunks of physical memory */ - int i; - register struct hole *hp; - phys_clicks base; /* base address of chunk */ - phys_clicks size; /* size of chunk */ - message mess; - - /* Get a copy of the physical memory chunks found at the kernel. */ - if ((i=sys_getmemchunks(mem)) != OK) - panic("MM couldn't get mem chunks",i); - - /* Put all holes on the free list. */ - for (hp = &hole[0]; hp < &hole[NR_HOLES]; hp++) hp->h_next = hp + 1; - hole[NR_HOLES-1].h_next = NIL_HOLE; - hole_head = NIL_HOLE; - free_slots = &hole[0]; - - /* Ask the kernel for chunks of physical memory and allocate holes. */ - *free = 0; - for (i=0; i 0) { - free_mem(mem[i].base, mem[i].size); - *free += mem[i].size; -#if ENABLE_SWAP - if (swap_base < mem[i].base + mem[i].size) - swap_base = mem[i].base+mem[i].size; -#endif - } - } - -#if ENABLE_SWAP - /* The swap area is represented as a hole above and separate of regular - * memory. A hole at the size of the swap file is allocated on "swapon". - */ - swap_base++; /* make separate */ - swap_maxsize = 0 - swap_base; /* maximum we can possibly use */ -#endif -} - -#if ENABLE_SWAP -/*===========================================================================* - * swap_on * - *===========================================================================*/ -PUBLIC int swap_on(file, offset, size) -char *file; /* file to swap on */ -u32_t offset, size; /* area on swap file to use */ -{ -/* Turn swapping on. */ - - if (swap_fd != -1) return(EBUSY); /* already have swap? */ - - tell_fs(CHDIR, who, FALSE, 0); /* be like the caller for open() */ - if ((swap_fd = open(file, O_RDWR)) < 0) return(-errno); - swap_offset = offset; - size >>= CLICK_SHIFT; - if (size > swap_maxsize) size = swap_maxsize; - if (size > 0) free_mem(swap_base, (phys_clicks) size); -} - -/*===========================================================================* - * swap_off * - *===========================================================================*/ -PUBLIC int swap_off() -{ -/* Turn swapping off. */ - struct mproc *rmp; - struct hole *hp, *prev_ptr; - - if (swap_fd == -1) return(OK); /* can't turn off what isn't on */ - - /* Put all swapped out processes on the inswap queue and swap in. */ - for (rmp = &mproc[LOW_USER]; rmp < &mproc[NR_PROCS]; rmp++) { - if (rmp->mp_flags & ONSWAP) swap_inqueue(rmp); - } - swap_in(); - - /* All in memory? */ - for (rmp = &mproc[LOW_USER]; rmp < &mproc[NR_PROCS]; rmp++) { - if (rmp->mp_flags & ONSWAP) return(ENOMEM); - } - - /* Yes. Remove the swap hole and close the swap file descriptor. */ - for (hp = hole_head; hp != NIL_HOLE; prev_ptr = hp, hp = hp->h_next) { - if (hp->h_base >= swap_base) { - del_slot(prev_ptr, hp); - hp = hole_head; - } - } - close(swap_fd); - swap_fd = -1; - return(OK); -} - -/*===========================================================================* - * swap_inqueue * - *===========================================================================*/ -PUBLIC void swap_inqueue(rmp) -register struct mproc *rmp; /* process to add to the queue */ -{ -/* Put a swapped out process on the queue of processes to be swapped in. This - * happens when such a process gets a signal, or if a reply message must be - * sent, like when a process doing a wait() has a child that exits. - */ - struct mproc **pmp; - - if (rmp->mp_flags & SWAPIN) return; /* already queued */ - - - for (pmp = &in_queue; *pmp != NULL; pmp = &(*pmp)->mp_swapq) {} - *pmp = rmp; - rmp->mp_swapq = NULL; - rmp->mp_flags |= SWAPIN; -} - -/*===========================================================================* - * swap_in * - *===========================================================================*/ -PUBLIC void swap_in() -{ -/* Try to swap in a process on the inswap queue. We want to send it a message, - * interrupt it, or something. - */ - struct mproc **pmp, *rmp; - phys_clicks old_base, new_base, size; - off_t off; - int proc_nr; - - pmp = &in_queue; - while ((rmp = *pmp) != NULL) { - proc_nr = (rmp - mproc); - size = rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len - - rmp->mp_seg[D].mem_vir; - - if (!(rmp->mp_flags & SWAPIN)) { - /* Guess it got killed. (Queue is cleaned here.) */ - *pmp = rmp->mp_swapq; - continue; - } else - if ((new_base = alloc_mem(size)) == NO_MEM) { - /* No memory for this one, try the next. */ - pmp = &rmp->mp_swapq; - } else { - /* We've found memory. Update map and swap in. */ - old_base = rmp->mp_seg[D].mem_phys; - rmp->mp_seg[D].mem_phys = new_base; - rmp->mp_seg[S].mem_phys = rmp->mp_seg[D].mem_phys + - (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir); - sys_newmap(proc_nr, rmp->mp_seg); - off = swap_offset + ((off_t) (old_base-swap_base)<mp_flags &= ~(ONSWAP|SWAPIN); - *pmp = rmp->mp_swapq; - check_pending(rmp); /* a signal may have waked this one */ - } - } -} - -/*===========================================================================* - * swap_out * - *===========================================================================*/ -PRIVATE int swap_out() -{ -/* Try to find a process that can be swapped out. Candidates are those blocked - * on a system call that MM handles, like wait(), pause() or sigsuspend(). - */ - struct mproc *rmp; - struct hole *hp, *prev_ptr; - phys_clicks old_base, new_base, size; - off_t off; - int proc_nr; - - rmp = outswap; - do { - if (++rmp == &mproc[NR_PROCS]) rmp = &mproc[LOW_USER]; - - /* A candidate? */ - if (!(rmp->mp_flags & (PAUSED | WAITING | SIGSUSPENDED))) continue; - - /* Already on swap or otherwise to be avoided? */ - if (rmp->mp_flags & (TRACED | REPLY | ONSWAP)) continue; - - /* Got one, find a swap hole and swap it out. */ - proc_nr = (rmp - mproc); - size = rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len - - rmp->mp_seg[D].mem_vir; - - prev_ptr = NIL_HOLE; - for (hp = hole_head; hp != NIL_HOLE; prev_ptr = hp, hp = hp->h_next) { - if (hp->h_base >= swap_base && hp->h_len >= size) break; - } - if (hp == NIL_HOLE) continue; /* oops, not enough swapspace */ - new_base = hp->h_base; - hp->h_base += size; - hp->h_len -= size; - if (hp->h_len == 0) del_slot(prev_ptr, hp); - - off = swap_offset + ((off_t) (new_base - swap_base) << CLICK_SHIFT); - lseek(swap_fd, off, SEEK_SET); - rw_seg(1, swap_fd, proc_nr, D, (phys_bytes)size << CLICK_SHIFT); - old_base = rmp->mp_seg[D].mem_phys; - rmp->mp_seg[D].mem_phys = new_base; - rmp->mp_seg[S].mem_phys = rmp->mp_seg[D].mem_phys + - (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir); - sys_newmap(proc_nr, rmp->mp_seg); - free_mem(old_base, size); - rmp->mp_flags |= ONSWAP; - - outswap = rmp; /* next time start here */ - return(TRUE); - } while (rmp != outswap); - - return(FALSE); /* no candidate found */ -} -#endif /* SWAP */ diff --git a/servers/mm/break.c b/servers/mm/break.c deleted file mode 100644 index fbbf27d24..000000000 --- a/servers/mm/break.c +++ /dev/null @@ -1,170 +0,0 @@ -/* The MINIX model of memory allocation reserves a fixed amount of memory for - * the combined text, data, and stack segments. The amount used for a child - * process created by FORK is the same as the parent had. If the child does - * an EXEC later, the new size is taken from the header of the file EXEC'ed. - * - * The layout in memory consists of the text segment, followed by the data - * segment, followed by a gap (unused memory), followed by the stack segment. - * The data segment grows upward and the stack grows downward, so each can - * take memory from the gap. If they meet, the process must be killed. The - * procedures in this file deal with the growth of the data and stack segments. - * - * The entry points into this file are: - * do_brk: BRK/SBRK system calls to grow or shrink the data segment - * adjust: see if a proposed segment adjustment is allowed - * size_ok: see if the segment sizes are feasible - */ - -#include "mm.h" -#include -#include "mproc.h" -#include "param.h" - -#define DATA_CHANGED 1 /* flag value when data segment size changed */ -#define STACK_CHANGED 2 /* flag value when stack size changed */ - -/*===========================================================================* - * do_brk * - *===========================================================================*/ -PUBLIC int do_brk() -{ -/* Perform the brk(addr) system call. - * - * The call is complicated by the fact that on some machines (e.g., 8088), - * the stack pointer can grow beyond the base of the stack segment without - * anybody noticing it. - * The parameter, 'addr' is the new virtual address in D space. - */ - - register struct mproc *rmp; - int r; - vir_bytes v, new_sp; - vir_clicks new_clicks; - - rmp = mp; - v = (vir_bytes) m_in.addr; - new_clicks = (vir_clicks) ( ((long) v + CLICK_SIZE - 1) >> CLICK_SHIFT); - if (new_clicks < rmp->mp_seg[D].mem_vir) { - rmp->mp_reply.reply_ptr = (char *) -1; - return(ENOMEM); - } - new_clicks -= rmp->mp_seg[D].mem_vir; - if ((r=p_getsp(who, &new_sp)) != OK) /* ask kernel for current sp value */ - panic("MM couldn't get stack pointer", r); - r = adjust(rmp, new_clicks, new_sp); - rmp->mp_reply.reply_ptr = (r == OK ? m_in.addr : (char *) -1); - return(r); /* return new address or -1 */ -} - - -/*===========================================================================* - * adjust * - *===========================================================================*/ -PUBLIC int adjust(rmp, data_clicks, sp) -register struct mproc *rmp; /* whose memory is being adjusted? */ -vir_clicks data_clicks; /* how big is data segment to become? */ -vir_bytes sp; /* new value of sp */ -{ -/* See if data and stack segments can coexist, adjusting them if need be. - * Memory is never allocated or freed. Instead it is added or removed from the - * gap between data segment and stack segment. If the gap size becomes - * negative, the adjustment of data or stack fails and ENOMEM is returned. - */ - - register struct mem_map *mem_sp, *mem_dp; - vir_clicks sp_click, gap_base, lower, old_clicks; - int changed, r, ft; - long base_of_stack, delta; /* longs avoid certain problems */ - - mem_dp = &rmp->mp_seg[D]; /* pointer to data segment map */ - mem_sp = &rmp->mp_seg[S]; /* pointer to stack segment map */ - changed = 0; /* set when either segment changed */ - - if (mem_sp->mem_len == 0) return(OK); /* don't bother init */ - - /* See if stack size has gone negative (i.e., sp too close to 0xFFFF...) */ - base_of_stack = (long) mem_sp->mem_vir + (long) mem_sp->mem_len; - sp_click = sp >> CLICK_SHIFT; /* click containing sp */ - if (sp_click >= base_of_stack) return(ENOMEM); /* sp too high */ - - /* Compute size of gap between stack and data segments. */ - delta = (long) mem_sp->mem_vir - (long) sp_click; - lower = (delta > 0 ? sp_click : mem_sp->mem_vir); - - /* Add a safety margin for future stack growth. Impossible to do right. */ -#define SAFETY_BYTES (384 * sizeof(char *)) -#define SAFETY_CLICKS ((SAFETY_BYTES + CLICK_SIZE - 1) / CLICK_SIZE) - gap_base = mem_dp->mem_vir + data_clicks + SAFETY_CLICKS; - if (lower < gap_base) return(ENOMEM); /* data and stack collided */ - - /* Update data length (but not data orgin) on behalf of brk() system call. */ - old_clicks = mem_dp->mem_len; - if (data_clicks != mem_dp->mem_len) { - mem_dp->mem_len = data_clicks; - changed |= DATA_CHANGED; - } - - /* Update stack length and origin due to change in stack pointer. */ - if (delta > 0) { - mem_sp->mem_vir -= delta; - mem_sp->mem_phys -= delta; - mem_sp->mem_len += delta; - changed |= STACK_CHANGED; - } - - /* Do the new data and stack segment sizes fit in the address space? */ - ft = (rmp->mp_flags & SEPARATE); - r = size_ok(ft, rmp->mp_seg[T].mem_len, rmp->mp_seg[D].mem_len, - rmp->mp_seg[S].mem_len, rmp->mp_seg[D].mem_vir, rmp->mp_seg[S].mem_vir); - if (r == OK) { - if (changed) sys_newmap((int)(rmp - mproc), rmp->mp_seg); - return(OK); - } - - /* New sizes don't fit or require too many page/segment registers. Restore.*/ - if (changed & DATA_CHANGED) mem_dp->mem_len = old_clicks; - if (changed & STACK_CHANGED) { - mem_sp->mem_vir += delta; - mem_sp->mem_phys += delta; - mem_sp->mem_len -= delta; - } - return(ENOMEM); -} - - -/*===========================================================================* - * size_ok * - *===========================================================================*/ -PUBLIC int size_ok(file_type, tc, dc, sc, dvir, s_vir) -int file_type; /* SEPARATE or 0 */ -vir_clicks tc; /* text size in clicks */ -vir_clicks dc; /* data size in clicks */ -vir_clicks sc; /* stack size in clicks */ -vir_clicks dvir; /* virtual address for start of data seg */ -vir_clicks s_vir; /* virtual address for start of stack seg */ -{ -/* Check to see if the sizes are feasible and enough segmentation registers - * exist. On a machine with eight 8K pages, text, data, stack sizes of - * (32K, 16K, 16K) will fit, but (33K, 17K, 13K) will not, even though the - * former is bigger (64K) than the latter (63K). Even on the 8088 this test - * is needed, since the data and stack may not exceed 4096 clicks. - */ - -#if (CHIP == INTEL && _WORD_SIZE == 2) - int pt, pd, ps; /* segment sizes in pages */ - - pt = ( (tc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE; - pd = ( (dc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE; - ps = ( (sc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE; - - if (file_type == SEPARATE) { - if (pt > MAX_PAGES || pd + ps > MAX_PAGES) return(ENOMEM); - } else { - if (pt + pd + ps > MAX_PAGES) return(ENOMEM); - } -#endif - - if (dvir + dc > s_vir) return(ENOMEM); - - return(OK); -} diff --git a/servers/mm/const.h b/servers/mm/const.h deleted file mode 100644 index fa4d1c885..000000000 --- a/servers/mm/const.h +++ /dev/null @@ -1,14 +0,0 @@ -/* Constants used by the Memory Manager. */ - -#define NO_MEM ((phys_clicks) 0) /* returned by alloc_mem() with mem is up */ - -#if (CHIP == INTEL && _WORD_SIZE == 2) -/* These definitions are used in size_ok and are not needed for 386. - * The 386 segment granularity is 1 for segments smaller than 1M and 4096 - * above that. - */ -#define PAGE_SIZE 16 /* how many bytes in a page (s.b.HCLICK_SIZE)*/ -#define MAX_PAGES 4096 /* how many pages in the virtual addr space */ -#endif - -#define INIT_PID 1 /* init's process id number */ diff --git a/servers/mm/exec.c b/servers/mm/exec.c deleted file mode 100644 index 9bda417eb..000000000 --- a/servers/mm/exec.c +++ /dev/null @@ -1,598 +0,0 @@ -/* This file handles the EXEC system call. It performs the work as follows: - * - see if the permissions allow the file to be executed - * - read the header and extract the sizes - * - fetch the initial args and environment from the user space - * - allocate the memory for the new process - * - copy the initial stack from MM to the process - * - read in the text and data segments and copy to the process - * - take care of setuid and setgid bits - * - fix up 'mproc' table - * - tell kernel about EXEC - * - save offset to initial argc (for ps) - * - * The entry points into this file are: - * do_exec: perform the EXEC system call - * rw_seg: read or write a segment from or to a file - * find_share: find a process whose text segment can be shared - */ - -#include "mm.h" -#include -#include -#include -#include -#include -#include -#include "mproc.h" -#include "param.h" - -FORWARD _PROTOTYPE( int new_mem, (struct mproc *sh_mp, vir_bytes text_bytes, - vir_bytes data_bytes, vir_bytes bss_bytes, - vir_bytes stk_bytes, phys_bytes tot_bytes) ); -FORWARD _PROTOTYPE( void patch_ptr, (char stack[ARG_MAX], vir_bytes base) ); -FORWARD _PROTOTYPE( int insert_arg, (char stack[ARG_MAX], - vir_bytes *stk_bytes, char *arg, int replace) ); -FORWARD _PROTOTYPE( char *patch_stack, (int fd, char stack[ARG_MAX], - vir_bytes *stk_bytes, char *script) ); -FORWARD _PROTOTYPE( int read_header, (int fd, int *ft, vir_bytes *text_bytes, - vir_bytes *data_bytes, vir_bytes *bss_bytes, - phys_bytes *tot_bytes, long *sym_bytes, vir_clicks sc, - vir_bytes *pc) ); - -#define ESCRIPT (-2000) /* Returned by read_header for a #! script. */ -#define PTRSIZE sizeof(char *) /* Size of pointers in argv[] and envp[]. */ - -/*===========================================================================* - * do_exec * - *===========================================================================*/ -PUBLIC int do_exec() -{ -/* Perform the execve(name, argv, envp) call. The user library builds a - * complete stack image, including pointers, args, environ, etc. The stack - * is copied to a buffer inside MM, and then to the new core image. - */ - - register struct mproc *rmp; - struct mproc *sh_mp; - int m, r, fd, ft, sn; - static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */ - static char name_buf[PATH_MAX]; /* the name of the file to exec */ - char *new_sp, *name, *basename; - vir_bytes src, dst, text_bytes, data_bytes, bss_bytes, stk_bytes, vsp; - phys_bytes tot_bytes; /* total space for program, including gap */ - long sym_bytes; - vir_clicks sc; - struct stat s_buf[2], *s_p; - vir_bytes pc; - - /* Do some validity checks. */ - rmp = mp; - stk_bytes = (vir_bytes) m_in.stack_bytes; - if (stk_bytes > ARG_MAX) return(ENOMEM); /* stack too big */ - if (m_in.exec_len <= 0 || m_in.exec_len > PATH_MAX) return(EINVAL); - - /* Get the exec file name and see if the file is executable. */ - src = (vir_bytes) m_in.exec_name; - dst = (vir_bytes) name_buf; - r = sys_datacopy(who, (vir_bytes) src, - PM_PROC_NR, (vir_bytes) dst, (phys_bytes) m_in.exec_len); - if (r != OK) return(r); /* file name not in user data segment */ - - /* Fetch the stack from the user before destroying the old core image. */ - src = (vir_bytes) m_in.stack_ptr; - dst = (vir_bytes) mbuf; - r = sys_datacopy(who, (vir_bytes) src, - PM_PROC_NR, (vir_bytes) dst, (phys_bytes)stk_bytes); - - if (r != OK) return(EACCES); /* can't fetch stack (e.g. bad virtual addr) */ - - r = 0; /* r = 0 (first attempt), or 1 (interpreted script) */ - name = name_buf; /* name of file to exec. */ - do { - s_p = &s_buf[r]; - tell_fs(CHDIR, who, FALSE, 0); /* switch to the user's FS environ */ - fd = allowed(name, s_p, X_BIT); /* is file executable? */ - if (fd < 0) return(fd); /* file was not executable */ - - /* Read the file header and extract the segment sizes. */ - sc = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT; - - m = read_header(fd, &ft, &text_bytes, &data_bytes, &bss_bytes, - &tot_bytes, &sym_bytes, sc, &pc); - if (m != ESCRIPT || ++r > 1) break; - } while ((name = patch_stack(fd, mbuf, &stk_bytes, name_buf)) != NULL); - - if (m < 0) { - close(fd); /* something wrong with header */ - return(stk_bytes > ARG_MAX ? ENOMEM : ENOEXEC); - } - - /* Can the process' text be shared with that of one already running? */ - sh_mp = find_share(rmp, s_p->st_ino, s_p->st_dev, s_p->st_ctime); - - /* Allocate new memory and release old memory. Fix map and tell kernel. */ - r = new_mem(sh_mp, text_bytes, data_bytes, bss_bytes, stk_bytes, tot_bytes); - if (r != OK) { - close(fd); /* insufficient core or program too big */ - return(r); - } - - /* Save file identification to allow it to be shared. */ - rmp->mp_ino = s_p->st_ino; - rmp->mp_dev = s_p->st_dev; - rmp->mp_ctime = s_p->st_ctime; - - /* Patch up stack and copy it from MM to new core image. */ - vsp = (vir_bytes) rmp->mp_seg[S].mem_vir << CLICK_SHIFT; - vsp += (vir_bytes) rmp->mp_seg[S].mem_len << CLICK_SHIFT; - vsp -= stk_bytes; - patch_ptr(mbuf, vsp); - src = (vir_bytes) mbuf; - r = sys_datacopy(PM_PROC_NR, (vir_bytes) src, - who, (vir_bytes) vsp, (phys_bytes)stk_bytes); - if (r != OK) panic("do_exec stack copy err on", who); - - /* Read in text and data segments. */ - if (sh_mp != NULL) { - lseek(fd, (off_t) text_bytes, SEEK_CUR); /* shared: skip text */ - } else { - rw_seg(0, fd, who, T, text_bytes); - } - rw_seg(0, fd, who, D, data_bytes); - - close(fd); /* don't need exec file any more */ - - /* Take care of setuid/setgid bits. */ - if ((rmp->mp_flags & TRACED) == 0) { /* suppress if tracing */ - if (s_buf[0].st_mode & I_SET_UID_BIT) { - rmp->mp_effuid = s_buf[0].st_uid; - tell_fs(SETUID,who, (int)rmp->mp_realuid, (int)rmp->mp_effuid); - } - if (s_buf[0].st_mode & I_SET_GID_BIT) { - rmp->mp_effgid = s_buf[0].st_gid; - tell_fs(SETGID,who, (int)rmp->mp_realgid, (int)rmp->mp_effgid); - } - } - - /* Save offset to initial argc (for ps) */ - rmp->mp_procargs = vsp; - - /* Fix 'mproc' fields, tell kernel that exec is done, reset caught sigs. */ - for (sn = 1; sn <= _NSIG; sn++) { - if (sigismember(&rmp->mp_catch, sn)) { - sigdelset(&rmp->mp_catch, sn); - rmp->mp_sigact[sn].sa_handler = SIG_DFL; - sigemptyset(&rmp->mp_sigact[sn].sa_mask); - } - } - - rmp->mp_flags &= ~SEPARATE; /* turn off SEPARATE bit */ - rmp->mp_flags |= ft; /* turn it on for separate I & D files */ - new_sp = (char *) vsp; - - tell_fs(EXEC, who, 0, 0); /* allow FS to handle FD_CLOEXEC files */ - - /* System will save command line for debugging, ps(1) output, etc. */ - basename = strrchr(name, '/'); - if (basename == NULL) basename = name; else basename++; - strncpy(rmp->mp_name, basename, PROC_NAME_LEN-1); - rmp->mp_name[PROC_NAME_LEN] = '\0'; - sys_exec(who, new_sp, rmp->mp_flags & TRACED, basename, pc); - - return(SUSPEND); /* no reply, new program just runs */ -} - - -/*===========================================================================* - * read_header * - *===========================================================================*/ -PRIVATE int read_header(fd, ft, text_bytes, data_bytes, bss_bytes, - tot_bytes, sym_bytes, sc, pc) -int fd; /* file descriptor for reading exec file */ -int *ft; /* place to return ft number */ -vir_bytes *text_bytes; /* place to return text size */ -vir_bytes *data_bytes; /* place to return initialized data size */ -vir_bytes *bss_bytes; /* place to return bss size */ -phys_bytes *tot_bytes; /* place to return total size */ -long *sym_bytes; /* place to return symbol table size */ -vir_clicks sc; /* stack size in clicks */ -vir_bytes *pc; /* program entry point (initial PC) */ -{ -/* Read the header and extract the text, data, bss and total sizes from it. */ - - int m, ct; - vir_clicks tc, dc, s_vir, dvir; - phys_clicks totc; - struct exec hdr; /* a.out header is read in here */ - - /* Read the header and check the magic number. The standard MINIX header - * is defined in . It consists of 8 chars followed by 6 longs. - * Then come 4 more longs that are not used here. - * Byte 0: magic number 0x01 - * Byte 1: magic number 0x03 - * Byte 2: normal = 0x10 (not checked, 0 is OK), separate I/D = 0x20 - * Byte 3: CPU type, Intel 16 bit = 0x04, Intel 32 bit = 0x10, - * Motorola = 0x0B, Sun SPARC = 0x17 - * Byte 4: Header length = 0x20 - * Bytes 5-7 are not used. - * - * Now come the 6 longs - * Bytes 8-11: size of text segments in bytes - * Bytes 12-15: size of initialized data segment in bytes - * Bytes 16-19: size of bss in bytes - * Bytes 20-23: program entry point - * Bytes 24-27: total memory allocated to program (text, data + stack) - * Bytes 28-31: size of symbol table in bytes - * The longs are represented in a machine dependent order, - * little-endian on the 8088, big-endian on the 68000. - * The header is followed directly by the text and data segments, and the - * symbol table (if any). The sizes are given in the header. Only the - * text and data segments are copied into memory by exec. The header is - * used here only. The symbol table is for the benefit of a debugger and - * is ignored here. - */ - - if ((m= read(fd, &hdr, A_MINHDR)) < 2) return(ENOEXEC); - - /* Interpreted script? */ - if (((char *) &hdr)[0] == '#' && ((char *) &hdr)[1] == '!') return(ESCRIPT); - - if (m != A_MINHDR) return(ENOEXEC); - - /* Check magic number, cpu type, and flags. */ - if (BADMAG(hdr)) return(ENOEXEC); -#if (CHIP == INTEL && _WORD_SIZE == 2) - if (hdr.a_cpu != A_I8086) return(ENOEXEC); -#endif -#if (CHIP == INTEL && _WORD_SIZE == 4) - if (hdr.a_cpu != A_I80386) return(ENOEXEC); -#endif - if ((hdr.a_flags & ~(A_NSYM | A_EXEC | A_SEP)) != 0) return(ENOEXEC); - - *ft = ( (hdr.a_flags & A_SEP) ? SEPARATE : 0); /* separate I & D or not */ - - /* Get text and data sizes. */ - *text_bytes = (vir_bytes) hdr.a_text; /* text size in bytes */ - *data_bytes = (vir_bytes) hdr.a_data; /* data size in bytes */ - *bss_bytes = (vir_bytes) hdr.a_bss; /* bss size in bytes */ - *tot_bytes = hdr.a_total; /* total bytes to allocate for prog */ - *sym_bytes = hdr.a_syms; /* symbol table size in bytes */ - if (*tot_bytes == 0) return(ENOEXEC); - - if (*ft != SEPARATE) { - /* If I & D space is not separated, it is all considered data. Text=0*/ - *data_bytes += *text_bytes; - *text_bytes = 0; - } - *pc = hdr.a_entry; /* initial address to start execution */ - - /* Check to see if segment sizes are feasible. */ - tc = ((unsigned long) *text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT; - dc = (*data_bytes + *bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT; - totc = (*tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT; - if (dc >= totc) return(ENOEXEC); /* stack must be at least 1 click */ - dvir = (*ft == SEPARATE ? 0 : tc); - s_vir = dvir + (totc - sc); - m = size_ok(*ft, tc, dc, sc, dvir, s_vir); - ct = hdr.a_hdrlen & BYTE; /* header length */ - if (ct > A_MINHDR) lseek(fd, (off_t) ct, SEEK_SET); /* skip unused hdr */ - return(m); -} - - -/*===========================================================================* - * new_mem * - *===========================================================================*/ -PRIVATE int new_mem(sh_mp, text_bytes, data_bytes,bss_bytes,stk_bytes,tot_bytes) -struct mproc *sh_mp; /* text can be shared with this process */ -vir_bytes text_bytes; /* text segment size in bytes */ -vir_bytes data_bytes; /* size of initialized data in bytes */ -vir_bytes bss_bytes; /* size of bss in bytes */ -vir_bytes stk_bytes; /* size of initial stack segment in bytes */ -phys_bytes tot_bytes; /* total memory to allocate, including gap */ -{ -/* Allocate new memory and release the old memory. Change the map and report - * the new map to the kernel. Zero the new core image's bss, gap and stack. - */ - - register struct mproc *rmp; - vir_clicks text_clicks, data_clicks, gap_clicks, stack_clicks, tot_clicks; - phys_clicks new_base; - static char zero[1024]; /* used to zero bss */ - phys_bytes bytes, base, count, bss_offset; - - /* No need to allocate text if it can be shared. */ - if (sh_mp != NULL) text_bytes = 0; - - /* Allow the old data to be swapped out to make room. (Which is really a - * waste of time, because we are going to throw it away anyway.) - */ - rmp->mp_flags |= WAITING; - - /* Acquire the new memory. Each of the 4 parts: text, (data+bss), gap, - * and stack occupies an integral number of clicks, starting at click - * boundary. The data and bss parts are run together with no space. - */ - text_clicks = ((unsigned long) text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT; - data_clicks = (data_bytes + bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT; - stack_clicks = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT; - tot_clicks = (tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT; - gap_clicks = tot_clicks - data_clicks - stack_clicks; - if ( (int) gap_clicks < 0) return(ENOMEM); - - /* Try to allocate memory for the new process. */ - new_base = alloc_mem(text_clicks + tot_clicks); - if (new_base == NO_MEM) return(ENOMEM); - - /* We've got memory for the new core image. Release the old one. */ - rmp = mp; - - if (find_share(rmp, rmp->mp_ino, rmp->mp_dev, rmp->mp_ctime) == NULL) { - /* No other process shares the text segment, so free it. */ - free_mem(rmp->mp_seg[T].mem_phys, rmp->mp_seg[T].mem_len); - } - /* Free the data and stack segments. */ - free_mem(rmp->mp_seg[D].mem_phys, - rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len - rmp->mp_seg[D].mem_vir); - - /* We have now passed the point of no return. The old core image has been - * forever lost, memory for a new core image has been allocated. Set up - * and report new map. - */ - if (sh_mp != NULL) { - /* Share the text segment. */ - rmp->mp_seg[T] = sh_mp->mp_seg[T]; - } else { - rmp->mp_seg[T].mem_phys = new_base; - rmp->mp_seg[T].mem_vir = 0; - rmp->mp_seg[T].mem_len = text_clicks; - } - rmp->mp_seg[D].mem_phys = new_base + text_clicks; - rmp->mp_seg[D].mem_vir = 0; - rmp->mp_seg[D].mem_len = data_clicks; - rmp->mp_seg[S].mem_phys = rmp->mp_seg[D].mem_phys + data_clicks + gap_clicks; - rmp->mp_seg[S].mem_vir = rmp->mp_seg[D].mem_vir + data_clicks + gap_clicks; - rmp->mp_seg[S].mem_len = stack_clicks; - -#if (CHIP == M68000) - rmp->mp_seg[T].mem_vir = 0; - rmp->mp_seg[D].mem_vir = rmp->mp_seg[T].mem_len; - rmp->mp_seg[S].mem_vir = rmp->mp_seg[D].mem_vir + rmp->mp_seg[D].mem_len + gap_clicks; -#endif - - sys_newmap(who, rmp->mp_seg); /* report new map to the kernel */ - - /* The old memory may have been swapped out, but the new memory is real. */ - rmp->mp_flags &= ~(WAITING|ONSWAP|SWAPIN); - - /* Zero the bss, gap, and stack segment. */ - bytes = (phys_bytes)(data_clicks + gap_clicks + stack_clicks) << CLICK_SHIFT; - base = (phys_bytes) rmp->mp_seg[D].mem_phys << CLICK_SHIFT; - bss_offset = (data_bytes >> CLICK_SHIFT) << CLICK_SHIFT; - base += bss_offset; - bytes -= bss_offset; - - while (bytes > 0) { - count = MIN(bytes, (phys_bytes) sizeof(zero)); - if (sys_physcopy(PM_PROC_NR, D, (phys_bytes) zero, - NONE, PHYS_SEG, base, count) != OK) { - panic("new_mem can't zero", NO_NUM); - } - base += count; - bytes -= count; - } - return(OK); -} - - -/*===========================================================================* - * patch_ptr * - *===========================================================================*/ -PRIVATE void patch_ptr(stack, base) -char stack[ARG_MAX]; /* pointer to stack image within MM */ -vir_bytes base; /* virtual address of stack base inside user */ -{ -/* When doing an exec(name, argv, envp) call, the user builds up a stack - * image with arg and env pointers relative to the start of the stack. Now - * these pointers must be relocated, since the stack is not positioned at - * address 0 in the user's address space. - */ - - char **ap, flag; - vir_bytes v; - - flag = 0; /* counts number of 0-pointers seen */ - ap = (char **) stack; /* points initially to 'nargs' */ - ap++; /* now points to argv[0] */ - while (flag < 2) { - if (ap >= (char **) &stack[ARG_MAX]) return; /* too bad */ - if (*ap != NULL) { - v = (vir_bytes) *ap; /* v is relative pointer */ - v += base; /* relocate it */ - *ap = (char *) v; /* put it back */ - } else { - flag++; - } - ap++; - } -} - - -/*===========================================================================* - * insert_arg * - *===========================================================================*/ -PRIVATE int insert_arg(stack, stk_bytes, arg, replace) -char stack[ARG_MAX]; /* pointer to stack image within MM */ -vir_bytes *stk_bytes; /* size of initial stack */ -char *arg; /* argument to prepend/replace as new argv[0] */ -int replace; -{ -/* Patch the stack so that arg will become argv[0]. Be careful, the stack may - * be filled with garbage, although it normally looks like this: - * nargs argv[0] ... argv[nargs-1] NULL envp[0] ... NULL - * followed by the strings "pointed" to by the argv[i] and the envp[i]. The - * pointers are really offsets from the start of stack. - * Return true iff the operation succeeded. - */ - int offset, a0, a1, old_bytes = *stk_bytes; - - /* Prepending arg adds at least one string and a zero byte. */ - offset = strlen(arg) + 1; - - a0 = (int) ((char **) stack)[1]; /* argv[0] */ - if (a0 < 4 * PTRSIZE || a0 >= old_bytes) return(FALSE); - - a1 = a0; /* a1 will point to the strings to be moved */ - if (replace) { - /* Move a1 to the end of argv[0][] (argv[1] if nargs > 1). */ - do { - if (a1 == old_bytes) return(FALSE); - --offset; - } while (stack[a1++] != 0); - } else { - offset += PTRSIZE; /* new argv[0] needs new pointer in argv[] */ - a0 += PTRSIZE; /* location of new argv[0][]. */ - } - - /* stack will grow by offset bytes (or shrink by -offset bytes) */ - if ((*stk_bytes += offset) > ARG_MAX) return(FALSE); - - /* Reposition the strings by offset bytes */ - memmove(stack + a1 + offset, stack + a1, old_bytes - a1); - - strcpy(stack + a0, arg); /* Put arg in the new space. */ - - if (!replace) { - /* Make space for a new argv[0]. */ - memmove(stack + 2 * PTRSIZE, stack + 1 * PTRSIZE, a0 - 2 * PTRSIZE); - - ((char **) stack)[0]++; /* nargs++; */ - } - /* Now patch up argv[] and envp[] by offset. */ - patch_ptr(stack, (vir_bytes) offset); - ((char **) stack)[1] = (char *) a0; /* set argv[0] correctly */ - return(TRUE); -} - - -/*===========================================================================* - * patch_stack * - *===========================================================================*/ -PRIVATE char *patch_stack(fd, stack, stk_bytes, script) -int fd; /* file descriptor to open script file */ -char stack[ARG_MAX]; /* pointer to stack image within MM */ -vir_bytes *stk_bytes; /* size of initial stack */ -char *script; /* name of script to interpret */ -{ -/* Patch the argument vector to include the path name of the script to be - * interpreted, and all strings on the #! line. Returns the path name of - * the interpreter. - */ - char *sp, *interp = NULL; - int n; - enum { INSERT=FALSE, REPLACE=TRUE }; - - /* Make script[] the new argv[0]. */ - if (!insert_arg(stack, stk_bytes, script, REPLACE)) return(NULL); - - if (lseek(fd, 2L, 0) == -1 /* just behind the #! */ - || (n= read(fd, script, PATH_MAX)) < 0 /* read line one */ - || (sp= memchr(script, '\n', n)) == NULL) /* must be a proper line */ - return(NULL); - - /* Move sp backwards through script[], prepending each string to stack. */ - for (;;) { - /* skip spaces behind argument. */ - while (sp > script && (*--sp == ' ' || *sp == '\t')) {} - if (sp == script) break; - - sp[1] = 0; - /* Move to the start of the argument. */ - while (sp > script && sp[-1] != ' ' && sp[-1] != '\t') --sp; - - interp = sp; - if (!insert_arg(stack, stk_bytes, sp, INSERT)) return(NULL); - } - - /* Round *stk_bytes up to the size of a pointer for alignment contraints. */ - *stk_bytes= ((*stk_bytes + PTRSIZE - 1) / PTRSIZE) * PTRSIZE; - - close(fd); - return(interp); -} - - -/*===========================================================================* - * rw_seg * - *===========================================================================*/ -PUBLIC void rw_seg(rw, fd, proc, seg, seg_bytes0) -int rw; /* 0 = read, 1 = write */ -int fd; /* file descriptor to read from / write to */ -int proc; /* process number */ -int seg; /* T, D, or S */ -phys_bytes seg_bytes0; /* how much is to be transferred? */ -{ -/* Transfer text or data from/to a file and copy to/from a process segment. - * This procedure is a little bit tricky. The logical way to transfer a - * segment would be block by block and copying each block to/from the user - * space one at a time. This is too slow, so we do something dirty here, - * namely send the user space and virtual address to the file system in the - * upper 10 bits of the file descriptor, and pass it the user virtual address - * instead of a MM address. The file system extracts these parameters when - * gets a read or write call from the memory manager, which is the only process - * that is permitted to use this trick. The file system then copies the whole - * segment directly to/from user space, bypassing MM completely. - * - * The byte count on read is usually smaller than the segment count, because - * a segment is padded out to a click multiple, and the data segment is only - * partially initialized. - */ - - int new_fd, bytes, r; - char *ubuf_ptr; - struct mem_map *sp = &mproc[proc].mp_seg[seg]; - phys_bytes seg_bytes = seg_bytes0; - - new_fd = (proc << 7) | (seg << 5) | fd; - ubuf_ptr = (char *) ((vir_bytes) sp->mem_vir << CLICK_SHIFT); - - while (seg_bytes != 0) { -#define MM_CHUNK_SIZE 8192 - bytes = MIN((INT_MAX / MM_CHUNK_SIZE) * MM_CHUNK_SIZE, seg_bytes); - if (rw == 0) { - r = read(new_fd, ubuf_ptr, bytes); - } else { - r = write(new_fd, ubuf_ptr, bytes); - } - if (r != bytes) break; - ubuf_ptr += bytes; - seg_bytes -= bytes; - } -} - - -/*===========================================================================* - * find_share * - *===========================================================================*/ -PUBLIC struct mproc *find_share(mp_ign, ino, dev, ctime) -struct mproc *mp_ign; /* process that should not be looked at */ -ino_t ino; /* parameters that uniquely identify a file */ -dev_t dev; -time_t ctime; -{ -/* Look for a process that is the file in execution. Don't - * accidentally "find" mp_ign, because it is the process on whose behalf this - * call is made. - */ - struct mproc *sh_mp; - - for (sh_mp = &mproc[INIT_PROC_NR]; sh_mp < &mproc[NR_PROCS]; sh_mp++) { - if (!(sh_mp->mp_flags & SEPARATE)) continue; - if (sh_mp == mp_ign) continue; - if (sh_mp->mp_ino != ino) continue; - if (sh_mp->mp_dev != dev) continue; - if (sh_mp->mp_ctime != ctime) continue; - return sh_mp; - } - return(NULL); -} diff --git a/servers/mm/forkexit.c b/servers/mm/forkexit.c deleted file mode 100644 index 3de71280d..000000000 --- a/servers/mm/forkexit.c +++ /dev/null @@ -1,288 +0,0 @@ -/* This file deals with creating processes (via FORK) and deleting them (via - * EXIT/WAIT). When a process forks, a new slot in the 'mproc' table is - * allocated for it, and a copy of the parent's core image is made for the - * child. Then the kernel and file system are informed. A process is removed - * from the 'mproc' table when two events have occurred: (1) it has exited or - * been killed by a signal, and (2) the parent has done a WAIT. If the process - * exits first, it continues to occupy a slot until the parent does a WAIT. - * - * The entry points into this file are: - * do_fork: perform the FORK system call - * do_mm_exit: perform the EXIT system call (by calling mm_exit()) - * mm_exit: actually do the exiting - * do_wait: perform the WAITPID or WAIT system call - */ - - -#include "mm.h" -#include -#include -#include -#include -#include -#include "mproc.h" -#include "param.h" - -#define LAST_FEW 2 /* last few slots reserved for superuser */ - -PRIVATE pid_t next_pid = INIT_PID+1; /* next pid to be assigned */ - -FORWARD _PROTOTYPE (void cleanup, (register struct mproc *child) ); - -/*===========================================================================* - * do_fork * - *===========================================================================*/ -PUBLIC int do_fork() -{ -/* The process pointed to by 'mp' has forked. Create a child process. */ - - register struct mproc *rmp; /* pointer to parent */ - register struct mproc *rmc; /* pointer to child */ - int i, child_nr, t; - phys_clicks prog_clicks, child_base; - phys_bytes prog_bytes, parent_abs, child_abs; /* Intel only */ - - /* If tables might fill up during FORK, don't even start since recovery half - * way through is such a nuisance. - */ - rmp = mp; - if ((procs_in_use == NR_PROCS) || - (procs_in_use >= NR_PROCS-LAST_FEW && rmp->mp_effuid != 0)) - { - printf("MM: proc table full!\n"); - return(EAGAIN); - } - - /* Determine how much memory to allocate. Only the data and stack need to - * be copied, because the text segment is either shared or of zero length. - */ - prog_clicks = (phys_clicks) rmp->mp_seg[S].mem_len; - prog_clicks += (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir); - prog_bytes = (phys_bytes) prog_clicks << CLICK_SHIFT; - if ( (child_base = alloc_mem(prog_clicks)) == NO_MEM) return(ENOMEM); - - /* Create a copy of the parent's core image for the child. */ - child_abs = (phys_bytes) child_base << CLICK_SHIFT; - parent_abs = (phys_bytes) rmp->mp_seg[D].mem_phys << CLICK_SHIFT; - i = sys_abscopy(parent_abs, child_abs, prog_bytes); - if (i < 0) panic("do_fork can't copy", i); - - /* Find a slot in 'mproc' for the child process. A slot must exist. */ - for (rmc = &mproc[0]; rmc < &mproc[NR_PROCS]; rmc++) - if ( (rmc->mp_flags & IN_USE) == 0) break; - - /* Set up the child and its memory map; copy its 'mproc' slot from parent. */ - child_nr = (int)(rmc - mproc); /* slot number of the child */ - procs_in_use++; - *rmc = *rmp; /* copy parent's process slot to child's */ - - rmc->mp_parent = who; /* record child's parent */ - rmc->mp_flags &= (IN_USE|SEPARATE); /* inherit only these flags */ - - /* A separate I&D child keeps the parents text segment. The data and stack - * segments must refer to the new copy. - */ - if (!(rmc->mp_flags & SEPARATE)) rmc->mp_seg[T].mem_phys = child_base; - rmc->mp_seg[D].mem_phys = child_base; - rmc->mp_seg[S].mem_phys = rmc->mp_seg[D].mem_phys + - (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir); - rmc->mp_exitstatus = 0; - rmc->mp_sigstatus = 0; - - /* Find a free pid for the child and put it in the table. */ - do { - t = 0; /* 't' = 0 means pid still free */ - next_pid = (next_pid < 30000 ? next_pid + 1 : INIT_PID + 1); - for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) - if (rmp->mp_pid == next_pid || rmp->mp_procgrp == next_pid) { - t = 1; - break; - } - rmc->mp_pid = next_pid; /* assign pid to child */ - } while (t); - - /* Tell kernel and file system about the (now successful) FORK. */ - sys_fork(who, child_nr, rmc->mp_pid); - tell_fs(FORK, who, child_nr, rmc->mp_pid); - - /* Report child's memory map to kernel. */ - sys_newmap(child_nr, rmc->mp_seg); - - /* Reply to child to wake it up. */ - setreply(child_nr, 0); - return(next_pid); /* child's pid */ -} - - -/*===========================================================================* - * do_mm_exit * - *===========================================================================*/ -PUBLIC int do_mm_exit() -{ -/* Perform the exit(status) system call. The real work is done by mm_exit(), - * which is also called when a process is killed by a signal. - */ - - mm_exit(mp, m_in.status); - return(SUSPEND); /* can't communicate from beyond the grave */ -} - - -/*===========================================================================* - * mm_exit * - *===========================================================================*/ -PUBLIC void mm_exit(rmp, exit_status) -register struct mproc *rmp; /* pointer to the process to be terminated */ -int exit_status; /* the process' exit status (for parent) */ -{ -/* A process is done. Release most of the process' possessions. If its - * parent is waiting, release the rest, else keep the process slot and - * become a zombie. - */ - - register int proc_nr; - int parent_waiting, right_child; - pid_t pidarg, procgrp; - struct mproc *p_mp; - - proc_nr = (int) (rmp - mproc); /* get process slot number */ - - /* Remember a session leader's process group. */ - procgrp = (rmp->mp_pid == mp->mp_procgrp) ? mp->mp_procgrp : 0; - - /* If the exited process has a timer pending, kill it. */ - if (rmp->mp_flags & ALARM_ON) set_alarm(proc_nr, (unsigned) 0); - - /* Tell the kernel and FS that the process is no longer runnable. */ - tell_fs(EXIT, proc_nr, 0, 0); /* file system can free the proc slot */ - sys_xit(rmp->mp_parent, proc_nr); - - /* Release the memory occupied by the child. */ - if (find_share(rmp, rmp->mp_ino, rmp->mp_dev, rmp->mp_ctime) == NULL) { - /* No other process shares the text segment, so free it. */ - free_mem(rmp->mp_seg[T].mem_phys, rmp->mp_seg[T].mem_len); - } - /* Free the data and stack segments. */ - free_mem(rmp->mp_seg[D].mem_phys, - rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len - rmp->mp_seg[D].mem_vir); - - /* The process slot can only be freed if the parent has done a WAIT. */ - rmp->mp_exitstatus = (char) exit_status; - - p_mp = &mproc[rmp->mp_parent]; /* process' parent */ - pidarg = p_mp->mp_wpid; /* who's being waited for? */ - parent_waiting = p_mp->mp_flags & WAITING; - - right_child = /* child meets one of the 3 tests? */ - (pidarg == -1 || pidarg == rmp->mp_pid || -pidarg == rmp->mp_procgrp); - - if (parent_waiting && right_child) { - cleanup(rmp); /* tell parent and release child slot */ - } else { - rmp->mp_flags = IN_USE|ZOMBIE; /* parent not waiting, zombify child */ - sig_proc(p_mp, SIGCHLD); /* send parent a "child died" signal */ - } - - /* If the process has children, disinherit them. INIT is the new parent. */ - for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) { - if (rmp->mp_flags & IN_USE && rmp->mp_parent == proc_nr) { - /* 'rmp' now points to a child to be disinherited. */ - rmp->mp_parent = INIT_PROC_NR; - parent_waiting = mproc[INIT_PROC_NR].mp_flags & WAITING; - if (parent_waiting && (rmp->mp_flags & ZOMBIE)) cleanup(rmp); - } - } - - /* Send a hangup to the process' process group if it was a session leader. */ - if (procgrp != 0) check_sig(-procgrp, SIGHUP); -} - - -/*===========================================================================* - * do_waitpid * - *===========================================================================*/ -PUBLIC int do_waitpid() -{ -/* A process wants to wait for a child to terminate. If one is already waiting, - * go clean it up and let this WAIT call terminate. Otherwise, really wait. - * Both WAIT and WAITPID are handled by this code. - */ - - register struct mproc *rp; - int pidarg, options, children; - - /* A process calling WAIT never gets a reply in the usual way at the end - * of the main loop (unless WNOHANG is set or no qualifying child exists). - * If a child has already exited, the routine cleanup() sends the reply - * to awaken the caller. - */ - - /* Set internal variables, depending on whether this is WAIT or WAITPID. */ - pidarg = (call_nr == WAIT ? -1 : m_in.pid); /* 1st param of waitpid */ - options = (call_nr == WAIT ? 0 : m_in.sig_nr); /* 3rd param of waitpid */ - if (pidarg == 0) pidarg = -mp->mp_procgrp; /* pidarg < 0 ==> proc grp */ - - /* Is there a child waiting to be collected? At this point, pidarg != 0: - * pidarg > 0 means pidarg is pid of a specific process to wait for - * pidarg == -1 means wait for any child - * pidarg < -1 means wait for any child whose process group = -pidarg - */ - children = 0; - for (rp = &mproc[0]; rp < &mproc[NR_PROCS]; rp++) { - if ( (rp->mp_flags & IN_USE) && rp->mp_parent == who) { - /* The value of pidarg determines which children qualify. */ - if (pidarg > 0 && pidarg != rp->mp_pid) continue; - if (pidarg < -1 && -pidarg != rp->mp_procgrp) continue; - - children++; /* this child is acceptable */ - if (rp->mp_flags & ZOMBIE) { - /* This child meets the pid test and has exited. */ - cleanup(rp); /* this child has already exited */ - return(SUSPEND); - } - if ((rp->mp_flags & STOPPED) && rp->mp_sigstatus) { - /* This child meets the pid test and is being traced.*/ - mp->mp_reply.reply_res2 = 0177|(rp->mp_sigstatus << 8); - rp->mp_sigstatus = 0; - return(rp->mp_pid); - } - } - } - - /* No qualifying child has exited. Wait for one, unless none exists. */ - if (children > 0) { - /* At least 1 child meets the pid test exists, but has not exited. */ - if (options & WNOHANG) return(0); /* parent does not want to wait */ - mp->mp_flags |= WAITING; /* parent wants to wait */ - mp->mp_wpid = (pid_t) pidarg; /* save pid for later */ - return(SUSPEND); /* do not reply, let it wait */ - } else { - /* No child even meets the pid test. Return error immediately. */ - return(ECHILD); /* no - parent has no children */ - } -} - - -/*===========================================================================* - * cleanup * - *===========================================================================*/ -PRIVATE void cleanup(child) -register struct mproc *child; /* tells which process is exiting */ -{ -/* Finish off the exit of a process. The process has exited or been killed - * by a signal, and its parent is waiting. - */ - - struct mproc *parent = &mproc[child->mp_parent]; - int exitstatus; - - /* Wake up the parent. */ - exitstatus = (child->mp_exitstatus << 8) | (child->mp_sigstatus & 0377); - parent->mp_reply.reply_res2 = exitstatus; - setreply(child->mp_parent, child->mp_pid); - parent->mp_flags &= ~WAITING; /* parent no longer waiting */ - - /* Release the process table entry. */ - child->mp_flags = 0; - procs_in_use--; -} diff --git a/servers/mm/getset.c b/servers/mm/getset.c deleted file mode 100644 index cd8d6d55a..000000000 --- a/servers/mm/getset.c +++ /dev/null @@ -1,78 +0,0 @@ -/* This file handles the 4 system calls that get and set uids and gids. - * It also handles getpid(), setsid(), and getpgrp(). The code for each - * one is so tiny that it hardly seemed worthwhile to make each a separate - * function. - */ - -#include "mm.h" -#include -#include -#include "mproc.h" -#include "param.h" - -/*===========================================================================* - * do_getset * - *===========================================================================*/ -PUBLIC int do_getset() -{ -/* Handle GETUID, GETGID, GETPID, GETPGRP, SETUID, SETGID, SETSID. The four - * GETs and SETSID return their primary results in 'r'. GETUID, GETGID, and - * GETPID also return secondary results (the effective IDs, or the parent - * process ID) in 'reply_res2', which is returned to the user. - */ - - register struct mproc *rmp = mp; - register int r; - - switch(call_nr) { - case GETUID: - r = rmp->mp_realuid; - rmp->mp_reply.reply_res2 = rmp->mp_effuid; - break; - - case GETGID: - r = rmp->mp_realgid; - rmp->mp_reply.reply_res2 = rmp->mp_effgid; - break; - - case GETPID: - r = mproc[who].mp_pid; - rmp->mp_reply.reply_res2 = mproc[rmp->mp_parent].mp_pid; - break; - - case SETUID: - if (rmp->mp_realuid != (uid_t) m_in.usr_id && - rmp->mp_effuid != SUPER_USER) - return(EPERM); - rmp->mp_realuid = (uid_t) m_in.usr_id; - rmp->mp_effuid = (uid_t) m_in.usr_id; - tell_fs(SETUID, who, rmp->mp_realuid, rmp->mp_effuid); - r = OK; - break; - - case SETGID: - if (rmp->mp_realgid != (gid_t) m_in.grp_id && - rmp->mp_effuid != SUPER_USER) - return(EPERM); - rmp->mp_realgid = (gid_t) m_in.grp_id; - rmp->mp_effgid = (gid_t) m_in.grp_id; - tell_fs(SETGID, who, rmp->mp_realgid, rmp->mp_effgid); - r = OK; - break; - - case SETSID: - if (rmp->mp_procgrp == rmp->mp_pid) return(EPERM); - rmp->mp_procgrp = rmp->mp_pid; - tell_fs(SETSID, who, 0, 0); - /*FALL THROUGH*/ - - case GETPGRP: - r = rmp->mp_procgrp; - break; - - default: - r = EINVAL; - break; - } - return(r); -} diff --git a/servers/mm/glo.h b/servers/mm/glo.h deleted file mode 100644 index 6f99a59b1..000000000 --- a/servers/mm/glo.h +++ /dev/null @@ -1,20 +0,0 @@ -/* EXTERN should be extern except in table.c */ -#ifdef _TABLE -#undef EXTERN -#define EXTERN -#endif - -/* Global variables. */ -EXTERN struct mproc *mp; /* ptr to 'mproc' slot of current process */ -EXTERN int procs_in_use; /* how many processes are marked as IN_USE */ - -/* The parameters of the call are kept here. */ -EXTERN message m_in; /* the incoming message itself is kept here. */ -EXTERN int who; /* caller's proc number */ -EXTERN int call_nr; /* system call number */ - -extern _PROTOTYPE (int (*call_vec[]), (void) ); /* system call handlers */ -extern char core_name[]; /* file name where core images are produced */ -EXTERN sigset_t core_sset; /* which signals cause core images */ -EXTERN sigset_t ign_sset; /* which signals are by default ignored */ - diff --git a/servers/mm/main.c b/servers/mm/main.c deleted file mode 100644 index 7b7277323..000000000 --- a/servers/mm/main.c +++ /dev/null @@ -1,197 +0,0 @@ -/* This file contains the main program of the memory manager and some related - * procedures. When MINIX starts up, the kernel runs for a little while, - * initializing itself and its tasks, and then it runs MM and FS. Both MM - * and FS initialize themselves as far as they can. FS then makes a call to - * MM, because MM has to wait for FS to acquire a RAM disk. MM asks the - * kernel for all free memory and starts serving requests. - * - * The entry points into this file are: - * main: starts MM running - * setreply: set the reply to be sent to process making an MM system call - */ - -#include "mm.h" -#include -#include -#include -#include -#include -#include -#include "mproc.h" -#include "param.h" - -FORWARD _PROTOTYPE( void get_work, (void) ); -FORWARD _PROTOTYPE( void mm_init, (void) ); - -#define click_to_round_k(n) \ - ((unsigned) ((((unsigned long) (n) << CLICK_SHIFT) + 512) / 1024)) - -/*===========================================================================* - * main * - *===========================================================================*/ -PUBLIC void main() -{ -/* Main routine of the memory manager. */ - - int result, proc_nr; - struct mproc *rmp; - - mm_init(); /* initialize memory manager tables */ - - /* This is MM's main loop- get work and do it, forever and forever. */ - while (TRUE) { - get_work(); /* wait for an MM system call */ - - /* Check for system notifications first. Special cases. */ - if (call_nr == HARD_STOP) { /* MINIX is shutting down */ - check_sig(-1, SIGKILL); /* kill all processes */ - sys_exit(0); - /* never reached */ - } else if (call_nr == KSIG_PENDING) { /* signals pending */ - (void) ksig_pending(); - result = SUSPEND; /* don't reply */ - } - /* Else, if the system call number is valid, perform the call. */ - else if ((unsigned) call_nr >= NCALLS) { - result = ENOSYS; - } else { - result = (*call_vec[call_nr])(); - } - - /* Send the results back to the user to indicate completion. */ - if (result != SUSPEND) setreply(who, result); - - swap_in(); /* maybe a process can be swapped in? */ - - /* Send out all pending reply messages, including the answer to - * the call just made above. The processes must not be swapped out. - */ - for (proc_nr=0, rmp=mproc; proc_nr < NR_PROCS; proc_nr++, rmp++) { - if ((rmp->mp_flags & (REPLY | ONSWAP)) == REPLY) { - if (send(proc_nr, &rmp->mp_reply) != OK) - panic("MM can't reply to", proc_nr); - rmp->mp_flags &= ~REPLY; - } - } - } -} - - -/*===========================================================================* - * get_work * - *===========================================================================*/ -PRIVATE void get_work() -{ -/* Wait for the next message and extract useful information from it. */ - - if (receive(ANY, &m_in) != OK) panic("MM receive error", NO_NUM); - who = m_in.m_source; /* who sent the message */ - call_nr = m_in.m_type; /* system call number */ - - /* Process slot of caller. Misuse MM's own process slot if the kernel is - * calling. The can happen in case of pending kernel signals. - */ - mp = &mproc[who < 0 ? PM_PROC_NR : who]; -} - - -/*===========================================================================* - * setreply * - *===========================================================================*/ -PUBLIC void setreply(proc_nr, result) -int proc_nr; /* process to reply to */ -int result; /* result of the call (usually OK or error #)*/ -{ -/* Fill in a reply message to be sent later to a user process. System calls - * may occasionally fill in other fields, this is only for the main return - * value, and for setting the "must send reply" flag. - */ - - register struct mproc *rmp = &mproc[proc_nr]; - - rmp->mp_reply.reply_res = result; - rmp->mp_flags |= REPLY; /* reply pending */ - - if (rmp->mp_flags & ONSWAP) - swap_inqueue(rmp); /* must swap this process back in */ -} - - -/*===========================================================================* - * mm_init * - *===========================================================================*/ -PRIVATE void mm_init() -{ -/* Initialize the memory manager. */ - int s; - static char core_sigs[] = { SIGQUIT, SIGILL, SIGTRAP, SIGABRT, - SIGEMT, SIGFPE, SIGUSR1, SIGSEGV, SIGUSR2 }; - static char ign_sigs[] = { SIGCHLD }; - register int proc_nr; - register struct mproc *rmp; - register char *sig_ptr; - phys_clicks ram_clicks, total_clicks, minix_clicks, free_clicks; - message mess; - struct mem_map kernel_map[NR_LOCAL_SEGS]; - int mem; - - /* Build the set of signals which cause core dumps, and the set of signals - * that are by default ignored. - */ - sigemptyset(&core_sset); - for (sig_ptr = core_sigs; sig_ptr < core_sigs+sizeof(core_sigs); sig_ptr++) - sigaddset(&core_sset, *sig_ptr); - sigemptyset(&ign_sset); - for (sig_ptr = ign_sigs; sig_ptr < ign_sigs+sizeof(ign_sigs); sig_ptr++) - sigaddset(&ign_sset, *sig_ptr); - - /* Get the memory map of the kernel to see how much memory it uses. */ - if ((s=p_getmap(SYSTASK, kernel_map)) != OK) - panic("MM couldn't get proc entry of SYSTASK",s); - minix_clicks = (kernel_map[S].mem_phys + kernel_map[S].mem_len) - - kernel_map[T].mem_phys; - - /* Initialize MM's tables. Request a copy of the system image table that - * is defined at the kernel level to see which slots to fill in. - */ - for (proc_nr = 0; proc_nr <= INIT_PROC_NR; proc_nr++) { - rmp = &mproc[proc_nr]; - rmp->mp_flags |= IN_USE; - if ((s=p_getmap(proc_nr, rmp->mp_seg)) != OK) - panic("MM couldn't get proc entry",s); - if (rmp->mp_seg[T].mem_len != 0) rmp->mp_flags |= SEPARATE; - minix_clicks += (rmp->mp_seg[S].mem_phys + rmp->mp_seg[S].mem_len) - - rmp->mp_seg[T].mem_phys; - } - mproc[INIT_PROC_NR].mp_pid = INIT_PID; - sigemptyset(&mproc[INIT_PROC_NR].mp_ignore); - sigemptyset(&mproc[INIT_PROC_NR].mp_catch); - procs_in_use = LOW_USER + 1; - - /* Wait for FS to send a message telling the RAM disk size then go "on-line". - */ - if (receive(FS_PROC_NR, &mess) != OK) - panic("MM can't obtain RAM disk size from FS", NO_NUM); - - ram_clicks = mess.MEM_CHUNK_SIZE; - - /* Initialize tables to all physical mem. */ - mem_init(&free_clicks); - total_clicks = minix_clicks + ram_clicks + free_clicks; - - /* Print memory information. */ - printf("Memory size=%uK ", click_to_round_k(total_clicks)); - printf("MINIX=%uK ", click_to_round_k(minix_clicks)); - printf("RAM disk=%uK ", click_to_round_k(ram_clicks)); - printf("Available=%uK\n\n", click_to_round_k(free_clicks)); - - /* Tell FS to continue. */ - if (send(FS_PROC_NR, &mess) != OK) - panic("MM can't sync up with FS", NO_NUM); - - /* Tell the memory task where my process table is for the sake of ps(1). */ - if ((mem = open("/dev/ram", O_RDWR)) != -1) { - ioctl(mem, MIOCSPSINFO, (void *) mproc); - close(mem); - } -} diff --git a/servers/mm/misc.c b/servers/mm/misc.c deleted file mode 100644 index cbf1cb7a4..000000000 --- a/servers/mm/misc.c +++ /dev/null @@ -1,221 +0,0 @@ -/* Miscellaneous system calls. Author: Kees J. Bot - * 31 Mar 2000 - * The entry points into this file are: - * do_reboot: kill all processes, then reboot system - * do_svrctl: memory manager control - * do_getsysinfo: request copy of MM data structure - */ - -#include "mm.h" -#include -#include -#include -#include -#include -#include -#include "mproc.h" -#include "param.h" - -FORWARD _PROTOTYPE( char *find_key, (const char *params, const char *key)); - -/* MM gets a copy of all boot monitor parameters. */ -PRIVATE char monitor_params[128*sizeof(char *)]; - -/*=====================================================================* - * do_getsysinfo * - *=====================================================================*/ -PUBLIC int do_getsysinfo() -{ - return(OK); -} - - -/*=====================================================================* - * do_reboot * - *=====================================================================*/ -PUBLIC int do_reboot() -{ - register struct mproc *rmp = mp; - char monitor_code[32*sizeof(char *)]; - - if (rmp->mp_effuid != SUPER_USER) return(EPERM); - - switch (m_in.reboot_flag) { - case RBT_HALT: - case RBT_REBOOT: - case RBT_PANIC: - case RBT_RESET: - break; - case RBT_MONITOR: - if (m_in.reboot_size >= sizeof(monitor_code)) return(EINVAL); - if (sys_datacopy(who, (vir_bytes) m_in.reboot_code, - PM_PROC_NR, (vir_bytes) monitor_code, - (phys_bytes) (m_in.reboot_size+1)) != OK) return(EFAULT); - if (monitor_code[m_in.reboot_size] != 0) return(EINVAL); - break; - default: - return(EINVAL); - } - - check_sig(-1, SIGKILL); /* kill all processes except init */ - tell_fs(REBOOT,0,0,0); /* tell FS to prepare for shutdown */ - - sys_abort(m_in.reboot_flag, PM_PROC_NR, monitor_code, m_in.reboot_size); - sys_exit(0); -} - -/*=====================================================================* - * do_svrctl * - *=====================================================================*/ -PUBLIC int do_svrctl() -{ - static int initialized = 0; - int s, req; - vir_bytes ptr; - req = m_in.svrctl_req; - ptr = (vir_bytes) m_in.svrctl_argp; - - /* Initialize private copy of monitor parameters on first call. */ - if (! initialized) { - if ((s=sys_getmonparams(monitor_params, sizeof(monitor_params))) != OK) - printf("MM: Warning couldn't get copy of monitor params: %d\n",s); - else - initialized = 1; - } - - /* Binary compatibility check. */ - if (req == SYSGETENV) { -#if DEAD_CODE - printf("SYSGETENV by %d (fix!)\n", who); -#endif - req = MMGETPARAM; - } - - /* Is the request for the kernel? Forward it, except for SYSGETENV. */ - if (((req >> 8) & 0xFF) == 'S') { - - /* Simply forward call to the SYSTEM task. */ - return(sys_svrctl(who, req, mp->mp_effuid == SUPER_USER, ptr)); - } - - /* Control operations local to the MM. */ - switch(req) { - case MMGETPARAM: { - struct sysgetenv sysgetenv; - char search_key[64]; - char *val_start; - size_t val_len; - size_t copy_len; - - /* Check if boot monitor parameters are in place. */ - if (! initialized) return(EAGAIN); - - /* Copy sysgetenv structure to MM. */ - if (sys_datacopy(who, ptr, SELF, (vir_bytes) &sysgetenv, - sizeof(sysgetenv)) != OK) return(EFAULT); - - if (sysgetenv.keylen == 0) { /* copy all parameters */ - val_start = monitor_params; - val_len = sizeof(monitor_params); - } - else { /* lookup value for key */ - /* Try to get a copy of the requested key. */ - if (sysgetenv.keylen > sizeof(search_key)) return(EINVAL); - if ((s = sys_datacopy(who, (vir_bytes) sysgetenv.key, - SELF, (vir_bytes) search_key, sysgetenv.keylen)) != OK) - return(s); - - /* Make sure key is null-terminated and lookup value. */ - search_key[sysgetenv.keylen-1]= '\0'; - if ((val_start = find_key(monitor_params, search_key)) == NULL) - return(ESRCH); - val_len = strlen(val_start) + 1; - } - - /* Value found, make the actual copy (as far as possible). */ - copy_len = MAX(val_len, sysgetenv.vallen); - if ((s=sys_datacopy(SELF, (vir_bytes) val_start, - who, (vir_bytes) sysgetenv.val, copy_len)) != OK) - return(s); - - /* See if it fits in the client's buffer. */ - return (copy_len > sysgetenv.vallen) ? E2BIG : OK; - } - case MMSIGNON: { - /* A user process becomes a task. Simulate an exit by - * releasing a waiting parent and disinheriting children. - */ - struct mproc *rmp; - pid_t pidarg; - - if (mp->mp_effuid != SUPER_USER) return(EPERM); - - rmp = &mproc[mp->mp_parent]; - tell_fs(EXIT, who, 0, 0); - - pidarg = rmp->mp_wpid; - if ((rmp->mp_flags & WAITING) && (pidarg == -1 - || pidarg == mp->mp_pid || -pidarg == mp->mp_procgrp)) - { - /* Wake up the parent. */ - rmp->mp_reply.reply_res2 = 0; - setreply(mp->mp_parent, mp->mp_pid); - rmp->mp_flags &= ~WAITING; - } - - /* Disinherit children. */ - for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) { - if (rmp->mp_flags & IN_USE && rmp->mp_parent == who) { - rmp->mp_parent = INIT_PROC_NR; - } - } - - /* Become like MM and FS. */ - mp->mp_pid = mp->mp_procgrp = 0; - mp->mp_parent = 0; - return(OK); } - -#if ENABLE_SWAP - case MMSWAPON: { - struct mmswapon swapon; - - if (mp->mp_effuid != SUPER_USER) return(EPERM); - - if (sys_datacopy(who, (phys_bytes) ptr, - PM_PROC_NR, (phys_bytes) &swapon, - (phys_bytes) sizeof(swapon)) != OK) return(EFAULT); - - return(swap_on(swapon.file, swapon.offset, swapon.size)); } - - case MMSWAPOFF: { - if (mp->mp_effuid != SUPER_USER) return(EPERM); - - return(swap_off()); } -#endif /* SWAP */ - - default: - return(EINVAL); - } -} - -/*==========================================================================* - * find_key * - *==========================================================================*/ -PRIVATE char *find_key(params,name) -const char *params; -const char *name; -{ - register const char *namep; - register char *envp; - - for (envp = (char *) params; *envp != 0;) { - for (namep = name; *namep != 0 && *namep == *envp; namep++, envp++) - ; - if (*namep == '\0' && *envp == '=') - return(envp + 1); - while (*envp++ != 0) - ; - } - return(NULL); -} - diff --git a/servers/mm/mm.h b/servers/mm/mm.h deleted file mode 100644 index 9170251e1..000000000 --- a/servers/mm/mm.h +++ /dev/null @@ -1,25 +0,0 @@ -/* This is the master header for mm. It includes some other files - * and defines the principal constants. - */ -#define _POSIX_SOURCE 1 /* tell headers to include POSIX stuff */ -#define _MINIX 1 /* tell headers to include MINIX stuff */ -#define _SYSTEM 1 /* tell headers that this is the kernel */ - -/* The following are so basic, all the *.c files get them automatically. */ -#include /* MUST be first */ -#include /* MUST be second */ -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include "const.h" -#include "type.h" -#include "proto.h" -#include "glo.h" diff --git a/servers/mm/mproc.h b/servers/mm/mproc.h deleted file mode 100644 index 2973cfe8e..000000000 --- a/servers/mm/mproc.h +++ /dev/null @@ -1,62 +0,0 @@ -/* This table has one slot per process. It contains all the memory management - * information for each process. Among other things, it defines the text, data - * and stack segments, uids and gids, and various flags. The kernel and file - * systems have tables that are also indexed by process, with the contents - * of corresponding slots referring to the same process in all three. - */ - -EXTERN struct mproc { - struct mem_map mp_seg[NR_LOCAL_SEGS]; /* points to text, data, stack */ - char mp_exitstatus; /* storage for status when process exits */ - char mp_sigstatus; /* storage for signal # for killed procs */ - pid_t mp_pid; /* process id */ - pid_t mp_procgrp; /* pid of process group (used for signals) */ - pid_t mp_wpid; /* pid this process is waiting for */ - int mp_parent; /* index of parent process */ - - /* Real and effective uids and gids. */ - uid_t mp_realuid; /* process' real uid */ - uid_t mp_effuid; /* process' effective uid */ - gid_t mp_realgid; /* process' real gid */ - gid_t mp_effgid; /* process' effective gid */ - - /* File identification for sharing. */ - ino_t mp_ino; /* inode number of file */ - dev_t mp_dev; /* device number of file system */ - time_t mp_ctime; /* inode changed time */ - - /* Signal handling information. */ - sigset_t mp_ignore; /* 1 means ignore the signal, 0 means don't */ - sigset_t mp_catch; /* 1 means catch the signal, 0 means don't */ - sigset_t mp_sigmask; /* signals to be blocked */ - sigset_t mp_sigmask2; /* saved copy of mp_sigmask */ - sigset_t mp_sigpending; /* signals being blocked */ - struct sigaction mp_sigact[_NSIG + 1]; /* as in sigaction(2) */ - vir_bytes mp_sigreturn; /* address of C library __sigreturn function */ - - /* Backwards compatibility for signals. */ - sighandler_t mp_func; /* all sigs vectored to a single user fcn */ - - unsigned mp_flags; /* flag bits */ - vir_bytes mp_procargs; /* ptr to proc's initial stack arguments */ - struct mproc *mp_swapq; /* queue of procs waiting to be swapped in */ - message mp_reply; /* reply message to be sent to one */ - - char mp_name[PROC_NAME_LEN]; /* process name */ -} mproc[NR_PROCS]; - -/* Flag values */ -#define IN_USE 0x001 /* set when 'mproc' slot in use */ -#define WAITING 0x002 /* set by WAIT system call */ -#define ZOMBIE 0x004 /* set by EXIT, cleared by WAIT */ -#define PAUSED 0x008 /* set by PAUSE system call */ -#define ALARM_ON 0x010 /* set when SIGALRM timer started */ -#define SEPARATE 0x020 /* set if file is separate I & D space */ -#define TRACED 0x040 /* set if process is to be traced */ -#define STOPPED 0x080 /* set if process stopped for tracing */ -#define SIGSUSPENDED 0x100 /* set by SIGSUSPEND system call */ -#define REPLY 0x200 /* set if a reply message is pending */ -#define ONSWAP 0x400 /* set if data segment is swapped out */ -#define SWAPIN 0x800 /* set if on the "swap this in" queue */ - -#define NIL_MPROC ((struct mproc *) 0) diff --git a/servers/mm/param.h b/servers/mm/param.h deleted file mode 100644 index e5764812c..000000000 --- a/servers/mm/param.h +++ /dev/null @@ -1,46 +0,0 @@ -/* The following names are synonyms for the variables in the input message. */ -#define addr m1_p1 -#define exec_name m1_p1 -#define exec_len m1_i1 -#define func m6_f1 -#define grp_id m1_i1 -#define namelen m1_i1 -#define pid m1_i1 -#define seconds m1_i1 -#define sig m6_i1 -#define stack_bytes m1_i2 -#define stack_ptr m1_p2 -#define status m1_i1 -#define usr_id m1_i1 -#define request m2_i2 -#define taddr m2_l1 -#define data m2_l2 -#define sig_nr m1_i2 -#define sig_nsa m1_p1 -#define sig_osa m1_p2 -#define sig_ret m1_p3 -#define sig_set m2_l1 -#define sig_how m2_i1 -#define sig_flags m2_i2 -#define sig_context m2_p1 -#ifdef _SIGMESSAGE -#define sig_msg m1_i1 -#endif -#define reboot_flag m1_i1 -#define reboot_code m1_p1 -#define reboot_size m1_i2 -#define svrctl_req m2_i1 -#define svrctl_argp m2_p1 - -/* The following names are synonyms for the variables in a reply message. */ -#define reply_res m_type -#define reply_res2 m2_i1 -#define reply_ptr m2_p1 -#define reply_mask m2_l1 -#define reply_trace m2_l2 - -/* The following names are used to inform the FS about certain events. */ -#define tell_fs_arg1 m1_i1 -#define tell_fs_arg2 m1_i2 -#define tell_fs_arg3 m1_i3 - diff --git a/servers/mm/procutils.c b/servers/mm/procutils.c deleted file mode 100644 index d478b5f95..000000000 --- a/servers/mm/procutils.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "mm.h" -#include -#include -#include -#include "../../kernel/const.h" -#include "../../kernel/type.h" -#include "../../kernel/proc.h" - -/* The entry points into this file are: - * p_getmap: get memory map of given process - * p_getsp: get stack pointer of given process - */ - -/*===========================================================================* - * p_getmap * - *===========================================================================*/ -PUBLIC int p_getmap(proc_nr, mem_map) -int proc_nr; /* process to get map of */ -struct mem_map *mem_map; /* put memory map here */ -{ - struct proc p; - int s; - - if ((s=sys_getproc(&p, proc_nr)) != OK) - return(s); - memcpy(mem_map, p.p_memmap, sizeof(p.p_memmap)); - return(OK); -} - -/*===========================================================================* - * p_getsp * - *===========================================================================*/ -PUBLIC int p_getsp(proc_nr, sp) -int proc_nr; /* process to get sp of */ -vir_bytes *sp; /* put stack pointer here */ -{ - struct proc p; - int s; - - if ((s=sys_getproc(&p, proc_nr)) != OK) - return(s); - *sp = p.p_reg.sp; - return(OK); -} - diff --git a/servers/mm/proto.h b/servers/mm/proto.h deleted file mode 100644 index 9f755acd5..000000000 --- a/servers/mm/proto.h +++ /dev/null @@ -1,91 +0,0 @@ -/* Function prototypes. */ - -struct mproc; -struct stat; -struct mem_map; - -/* alloc.c */ -_PROTOTYPE( phys_clicks alloc_mem, (phys_clicks clicks) ); -_PROTOTYPE( void free_mem, (phys_clicks base, phys_clicks clicks) ); -_PROTOTYPE( void mem_init, (phys_clicks *free) ); -#if ENABLE_SWAP -_PROTOTYPE( int swap_on, (char *file, u32_t offset, u32_t size) ); -_PROTOTYPE( int swap_off, (void) ); -_PROTOTYPE( void swap_in, (void) ); -_PROTOTYPE( void swap_inqueue, (struct mproc *rmp) ); -#else /* !SWAP */ -#define swap_in() ((void)0) -#define swap_inqueue(rmp) ((void)0) -#endif /* !SWAP */ - -/* break.c */ -_PROTOTYPE( int adjust, (struct mproc *rmp, - vir_clicks data_clicks, vir_bytes sp) ); -_PROTOTYPE( int do_brk, (void) ); -_PROTOTYPE( int size_ok, (int file_type, vir_clicks tc, vir_clicks dc, - vir_clicks sc, vir_clicks dvir, vir_clicks s_vir) ); - -/* devio.c */ -_PROTOTYPE( int do_dev_io, (void) ); -_PROTOTYPE( int do_dev_io, (void) ); - -/* exec.c */ -_PROTOTYPE( int do_exec, (void) ); -_PROTOTYPE( void rw_seg, (int rw, int fd, int proc, int seg, - phys_bytes seg_bytes) ); -_PROTOTYPE( struct mproc *find_share, (struct mproc *mp_ign, Ino_t ino, - Dev_t dev, time_t ctime) ); - -/* forkexit.c */ -_PROTOTYPE( int do_fork, (void) ); -_PROTOTYPE( int do_mm_exit, (void) ); -_PROTOTYPE( int do_waitpid, (void) ); -_PROTOTYPE( void mm_exit, (struct mproc *rmp, int exit_status) ); - -/* getset.c */ -_PROTOTYPE( int do_getset, (void) ); - -/* main.c */ -_PROTOTYPE( void main, (void) ); - -/* misc.c */ -_PROTOTYPE( int do_reboot, (void) ); -_PROTOTYPE( int do_getsysinfo, (void) ); -_PROTOTYPE( int do_svrctl, (void) ); -_PROTOTYPE( int do_mstats, (void) ); - -#if (MACHINE == MACINTOSH) -_PROTOTYPE( phys_clicks start_click, (void) ); -#endif - -_PROTOTYPE( void setreply, (int proc_nr, int result) ); - -/* signal.c */ -_PROTOTYPE( int do_alarm, (void) ); -_PROTOTYPE( int do_kill, (void) ); -_PROTOTYPE( int ksig_pending, (void) ); -_PROTOTYPE( int do_ksig, (void) ); -_PROTOTYPE( int do_pause, (void) ); -_PROTOTYPE( int set_alarm, (int proc_nr, int sec) ); -_PROTOTYPE( int check_sig, (pid_t proc_id, int signo) ); -_PROTOTYPE( void sig_proc, (struct mproc *rmp, int sig_nr) ); -_PROTOTYPE( int do_sigaction, (void) ); -_PROTOTYPE( int do_sigpending, (void) ); -_PROTOTYPE( int do_sigprocmask, (void) ); -_PROTOTYPE( int do_sigreturn, (void) ); -_PROTOTYPE( int do_sigsuspend, (void) ); -_PROTOTYPE( void check_pending, (struct mproc *rmp) ); - -/* trace.c */ -_PROTOTYPE( int do_trace, (void) ); -_PROTOTYPE( void stop_proc, (struct mproc *rmp, int sig_nr) ); - -/* utility.c */ -_PROTOTYPE( int allowed, (char *name_buf, struct stat *s_buf, int mask) ); -_PROTOTYPE( int no_sys, (void) ); -_PROTOTYPE( void panic, (char *format, int num) ); -_PROTOTYPE( void tell_fs, (int what, int p1, int p2, int p3) ); - -/* procutils.c */ -_PROTOTYPE( int p_getsp, (int proc_nr, vir_bytes *sp) ); -_PROTOTYPE( int p_getmap, (int proc_nr, struct mem_map *mem_map) ); diff --git a/servers/mm/signal.c b/servers/mm/signal.c deleted file mode 100644 index 96e7b054e..000000000 --- a/servers/mm/signal.c +++ /dev/null @@ -1,646 +0,0 @@ -/* This file handles signals, which are asynchronous events and are generally - * a messy and unpleasant business. Signals can be generated by the KILL - * system call, or from the keyboard (SIGINT) or from the clock (SIGALRM). - * In all cases control eventually passes to check_sig() to see which processes - * can be signaled. The actual signaling is done by sig_proc(). - * - * The entry points into this file are: - * do_sigaction: perform the SIGACTION system call - * do_sigpending: perform the SIGPENDING system call - * do_sigprocmask: perform the SIGPROCMASK system call - * do_sigreturn: perform the SIGRETURN system call - * do_sigsuspend: perform the SIGSUSPEND system call - * do_kill: perform the KILL system call - * do_ksig: accept a signal originating in the kernel (e.g., SIGINT) - * do_alarm: perform the ALARM system call by calling set_alarm() - * set_alarm: tell the clock task to start or stop a timer - * do_pause: perform the PAUSE system call - * ksig_pending: the kernel notified about pending signals - * sig_proc: interrupt or terminate a signaled process - * check_sig: check which processes to signal with sig_proc() - * check_pending: check if a pending signal can now be delivered - */ - -#include "mm.h" -#include -#include -#include -#include -#include -#include -#include -#include "mproc.h" -#include "param.h" - -#define CORE_MODE 0777 /* mode to use on core image files */ -#define DUMPED 0200 /* bit set in status when core dumped */ - -FORWARD _PROTOTYPE( void dump_core, (struct mproc *rmp) ); -FORWARD _PROTOTYPE( void unpause, (int pro) ); -FORWARD _PROTOTYPE( void handle_ksig, (int proc_nr, sigset_t sig_map) ); - - -/*===========================================================================* - * do_sigaction * - *===========================================================================*/ -PUBLIC int do_sigaction() -{ - int r; - struct sigaction svec; - struct sigaction *svp; - - if (m_in.sig_nr == SIGKILL) return(OK); - if (m_in.sig_nr < 1 || m_in.sig_nr > _NSIG) return (EINVAL); - svp = &mp->mp_sigact[m_in.sig_nr]; - if ((struct sigaction *) m_in.sig_osa != (struct sigaction *) NULL) { - r = sys_datacopy(PM_PROC_NR,(vir_bytes) svp, - who, (vir_bytes) m_in.sig_osa, (phys_bytes) sizeof(svec)); - if (r != OK) return(r); - } - - if ((struct sigaction *) m_in.sig_nsa == (struct sigaction *) NULL) - return(OK); - - /* Read in the sigaction structure. */ - r = sys_datacopy(who, (vir_bytes) m_in.sig_nsa, - PM_PROC_NR, (vir_bytes) &svec, (phys_bytes) sizeof(svec)); - if (r != OK) return(r); - - if (svec.sa_handler == SIG_IGN) { - sigaddset(&mp->mp_ignore, m_in.sig_nr); - sigdelset(&mp->mp_sigpending, m_in.sig_nr); - sigdelset(&mp->mp_catch, m_in.sig_nr); - } else { - sigdelset(&mp->mp_ignore, m_in.sig_nr); - if (svec.sa_handler == SIG_DFL) - sigdelset(&mp->mp_catch, m_in.sig_nr); - else - sigaddset(&mp->mp_catch, m_in.sig_nr); - } - mp->mp_sigact[m_in.sig_nr].sa_handler = svec.sa_handler; - sigdelset(&svec.sa_mask, SIGKILL); - mp->mp_sigact[m_in.sig_nr].sa_mask = svec.sa_mask; - mp->mp_sigact[m_in.sig_nr].sa_flags = svec.sa_flags; - mp->mp_sigreturn = (vir_bytes) m_in.sig_ret; - return(OK); -} - -/*===========================================================================* - * do_sigpending * - *===========================================================================*/ -PUBLIC int do_sigpending() -{ - mp->mp_reply.reply_mask = (long) mp->mp_sigpending; - return OK; -} - -/*===========================================================================* - * do_sigprocmask * - *===========================================================================*/ -PUBLIC int do_sigprocmask() -{ -/* Note that the library interface passes the actual mask in sigmask_set, - * not a pointer to the mask, in order to save a copy. Similarly, - * the old mask is placed in the return message which the library - * interface copies (if requested) to the user specified address. - * - * The library interface must set SIG_INQUIRE if the 'act' argument - * is NULL. - */ - - int i; - - mp->mp_reply.reply_mask = (long) mp->mp_sigmask; - - switch (m_in.sig_how) { - case SIG_BLOCK: - sigdelset((sigset_t *)&m_in.sig_set, SIGKILL); - for (i = 1; i <= _NSIG; i++) { - if (sigismember((sigset_t *)&m_in.sig_set, i)) - sigaddset(&mp->mp_sigmask, i); - } - break; - - case SIG_UNBLOCK: - for (i = 1; i <= _NSIG; i++) { - if (sigismember((sigset_t *)&m_in.sig_set, i)) - sigdelset(&mp->mp_sigmask, i); - } - check_pending(mp); - break; - - case SIG_SETMASK: - sigdelset((sigset_t *) &m_in.sig_set, SIGKILL); - mp->mp_sigmask = (sigset_t) m_in.sig_set; - check_pending(mp); - break; - - case SIG_INQUIRE: - break; - - default: - return(EINVAL); - break; - } - return OK; -} - -/*===========================================================================* - * do_sigsuspend * - *===========================================================================*/ -PUBLIC int do_sigsuspend() -{ - mp->mp_sigmask2 = mp->mp_sigmask; /* save the old mask */ - mp->mp_sigmask = (sigset_t) m_in.sig_set; - sigdelset(&mp->mp_sigmask, SIGKILL); - mp->mp_flags |= SIGSUSPENDED; - check_pending(mp); - return(SUSPEND); -} - - -/*===========================================================================* - * do_sigreturn * - *===========================================================================*/ -PUBLIC int do_sigreturn() -{ -/* A user signal handler is done. Restore context and check for - * pending unblocked signals. - */ - - int r; - - mp->mp_sigmask = (sigset_t) m_in.sig_set; - sigdelset(&mp->mp_sigmask, SIGKILL); - - r = sys_sigreturn(who, (struct sigmsg *) m_in.sig_context, m_in.sig_flags); - check_pending(mp); - return(r); -} - -/*===========================================================================* - * do_kill * - *===========================================================================*/ -PUBLIC int do_kill() -{ -/* Perform the kill(pid, signo) system call. */ - - return check_sig(m_in.pid, m_in.sig_nr); -} - -/*===========================================================================* - * do_ksig_pending * - *===========================================================================*/ -PUBLIC int ksig_pending() -{ -/* The kernel has notified the MM about pending signals. Request pending - * signals until all signals are handled. If there are no more signals, - * NONE is returned in the process number field. - */ - int proc_nr; - sigset_t sig_map; - - while (TRUE) { - sys_getsig(&proc_nr, &sig_map); /* get an arbitrary pending signal */ - if (NONE == proc_nr) { /* stop if no more pending signals */ - break; - } else { - handle_ksig(proc_nr, sig_map); /* handle the receive signal */ - } - } - return(SUSPEND); /* prevents sending reply */ -} - -/*===========================================================================* - * do_ksig * - *===========================================================================*/ -PUBLIC int do_ksig() -{ -/* Certain signals, such as segmentation violations and DEL, originate in the - * kernel. When the kernel detects such signals, it sets bits in a bit map. - * As soon as MM is awaiting new work, the kernel sends MM a message containing - * the process slot and bit map. That message comes here. The File System - * also uses this mechanism to signal writing on broken pipes (SIGPIPE). - */ - int proc_nr; - sigset_t sig_map; - - /* Only kernel may make this call. */ - if (who != HARDWARE) return(EPERM); - proc_nr = m_in.SIG_PROC; - sig_map = (sigset_t) m_in.SIG_MAP; - handle_ksig(proc_nr, sig_map); - return(SUSPEND); -} - -/*===========================================================================* - * handle_ksig * - *===========================================================================*/ -PRIVATE void handle_ksig(proc_nr, sig_map) -int proc_nr; -sigset_t sig_map; -{ - register struct mproc *rmp; - int i; - pid_t proc_id, id; - - rmp = &mproc[proc_nr]; - if ((rmp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) return; - proc_id = rmp->mp_pid; - mp = &mproc[0]; /* pretend kernel signals are from MM */ - mp->mp_procgrp = rmp->mp_procgrp; /* get process group right */ - - /* Check each bit in turn to see if a signal is to be sent. Unlike - * kill(), the kernel may collect several unrelated signals for a - * process and pass them to MM in one blow. Thus loop on the bit - * map. For SIGINT and SIGQUIT, use proc_id 0 to indicate a broadcast - * to the recipient's process group. For SIGKILL, use proc_id -1 to - * indicate a systemwide broadcast. - */ - for (i = 1; i <= _NSIG; i++) { - if (!sigismember(&sig_map, i)) continue; - switch (i) { - case SIGINT: - case SIGQUIT: - id = 0; break; /* broadcast to process group */ - case SIGKILL: - id = -1; break; /* broadcast to all except INIT */ - case SIGALRM: - /* Disregard SIGALRM when the target process has not - * requested an alarm. This only applies for a KERNEL - * generated signal. - */ - if ((rmp->mp_flags & ALARM_ON) == 0) continue; - rmp->mp_flags &= ~ALARM_ON; - /* fall through */ - default: - id = proc_id; - break; - } - check_sig(id, i); - sys_endsig(proc_nr); /* tell kernel it's done */ - } -} - - -/*===========================================================================* - * do_alarm * - *===========================================================================*/ -PUBLIC int do_alarm() -{ -/* Perform the alarm(seconds) system call. */ - return(set_alarm(who, m_in.seconds)); -} - - -/*===========================================================================* - * set_alarm * - *===========================================================================*/ -PUBLIC int set_alarm(proc_nr, sec) -int proc_nr; /* process that wants the alarm */ -int sec; /* how many seconds delay before the signal */ -{ -/* This routine is used by do_alarm() to set the alarm timer. It is also used - * to turn the timer off when a process exits with the timer still on. - */ - clock_t ticks; /* number of ticks for alarm */ - int remaining; /* previous time left in seconds */ - int s; - - if (sec != 0) mproc[proc_nr].mp_flags |= ALARM_ON; - else mproc[proc_nr].mp_flags &= ~ALARM_ON; - - /* Tell the clock task to provide a signal message when the time comes. - * - * Large delays cause a lot of problems. First, the alarm system call - * takes an unsigned seconds count and the library has cast it to an int. - * That probably works, but on return the library will convert "negative" - * unsigneds to errors. Presumably no one checks for these errors, so - * force this call through. Second, If unsigned and long have the same - * size, converting from seconds to ticks can easily overflow. Finally, - * the kernel has similar overflow bugs adding ticks. - * - * Fixing this requires a lot of ugly casts to fit the wrong interface - * types and to avoid overflow traps. ALRM_EXP_TIME has the right type - * (clock_t) although it is declared as long. How can variables like - * this be declared properly without combinatorial explosion of message - * types? - */ - ticks = (clock_t) (HZ * (unsigned long) (unsigned) sec); - if ( (unsigned long) ticks / HZ != (unsigned) sec) - ticks = LONG_MAX; /* eternity (really TMR_NEVER) */ - - if ((s=sys_signalrm(proc_nr, &ticks)) != OK) - panic("MM couldn't set signal alarm", s); - - remaining = (int) ((ticks + (HZ-1))/HZ); - if (remaining < 0) remaining = INT_MAX; /* true value is too large */ - return(remaining); -} - - -/*===========================================================================* - * do_pause * - *===========================================================================*/ -PUBLIC int do_pause() -{ -/* Perform the pause() system call. */ - - mp->mp_flags |= PAUSED; - return(SUSPEND); -} - - -/*===========================================================================* - * sig_proc * - *===========================================================================*/ -PUBLIC void sig_proc(rmp, signo) -register struct mproc *rmp; /* pointer to the process to be signaled */ -int signo; /* signal to send to process (1 to _NSIG) */ -{ -/* Send a signal to a process. Check to see if the signal is to be caught, - * ignored, or blocked. If the signal is to be caught, coordinate with - * KERNEL to push a sigcontext structure and a sigframe structure onto - * the catcher's stack. Also, KERNEL will reset the program counter and - * stack pointer, so that when the process next runs, it will be executing - * the signal handler. When the signal handler returns, sigreturn(2) - * will be called. Then KERNEL will restore the signal context from the - * sigcontext structure. - * - * If there is insufficient stack space, kill the process. - */ - - vir_bytes new_sp; - int s; - int slot; - int sigflags; - struct sigmsg sm; - - slot = (int) (rmp - mproc); - if ((rmp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) { - printf("MM: signal %d sent to %s process %d\n", - (rmp->mp_flags & ZOMBIE) ? "zombie" : "dead", signo, slot); - panic("", NO_NUM); - } - if ((rmp->mp_flags & TRACED) && signo != SIGKILL) { - /* A traced process has special handling. */ - unpause(slot); - stop_proc(rmp, signo); /* a signal causes it to stop */ - return; - } - /* Some signals are ignored by default. */ - if (sigismember(&rmp->mp_ignore, signo)) return; - - if (sigismember(&rmp->mp_sigmask, signo)) { - /* Signal should be blocked. */ - sigaddset(&rmp->mp_sigpending, signo); - return; - } - sigflags = rmp->mp_sigact[signo].sa_flags; - if (sigismember(&rmp->mp_catch, signo)) { - if (rmp->mp_flags & ONSWAP) { - /* Process is swapped out, leave signal pending. */ - sigaddset(&rmp->mp_sigpending, signo); - swap_inqueue(rmp); - return; - } - if (rmp->mp_flags & SIGSUSPENDED) - sm.sm_mask = rmp->mp_sigmask2; - else - sm.sm_mask = rmp->mp_sigmask; - sm.sm_signo = signo; - sm.sm_sighandler = (vir_bytes) rmp->mp_sigact[signo].sa_handler; - sm.sm_sigreturn = rmp->mp_sigreturn; - if ((s=p_getsp(slot, &new_sp)) != OK) - panic("MM couldn't get new stack pointer",s); - sm.sm_stkptr = new_sp; - - /* Make room for the sigcontext and sigframe struct. */ - new_sp -= sizeof(struct sigcontext) - + 3 * sizeof(char *) + 2 * sizeof(int); - - if (adjust(rmp, rmp->mp_seg[D].mem_len, new_sp) != OK) - goto doterminate; - - rmp->mp_sigmask |= rmp->mp_sigact[signo].sa_mask; - if (sigflags & SA_NODEFER) - sigdelset(&rmp->mp_sigmask, signo); - else - sigaddset(&rmp->mp_sigmask, signo); - - if (sigflags & SA_RESETHAND) { - sigdelset(&rmp->mp_catch, signo); - rmp->mp_sigact[signo].sa_handler = SIG_DFL; - } - - sys_sigsend(slot, &sm); - sigdelset(&rmp->mp_sigpending, signo); - /* If process is hanging on PAUSE, WAIT, SIGSUSPEND, tty, pipe, etc., - * release it. - */ - unpause(slot); - return; - } -doterminate: - /* Signal should not or cannot be caught. Take default action. */ - if (sigismember(&ign_sset, signo)) return; - - rmp->mp_sigstatus = (char) signo; - if (sigismember(&core_sset, signo)) { - if (rmp->mp_flags & ONSWAP) { - /* Process is swapped out, leave signal pending. */ - sigaddset(&rmp->mp_sigpending, signo); - swap_inqueue(rmp); - return; - } - /* Switch to the user's FS environment and dump core. */ - tell_fs(CHDIR, slot, FALSE, 0); - dump_core(rmp); - } - mm_exit(rmp, 0); /* terminate process */ -} - - -/*===========================================================================* - * check_sig * - *===========================================================================*/ -PUBLIC int check_sig(proc_id, signo) -pid_t proc_id; /* pid of proc to sig, or 0 or -1, or -pgrp */ -int signo; /* signal to send to process (0 to _NSIG) */ -{ -/* Check to see if it is possible to send a signal. The signal may have to be - * sent to a group of processes. This routine is invoked by the KILL system - * call, and also when the kernel catches a DEL or other signal. - */ - - register struct mproc *rmp; - int count; /* count # of signals sent */ - int error_code; - - if (signo < 0 || signo > _NSIG) return(EINVAL); - - /* Return EINVAL for attempts to send SIGKILL to INIT alone. */ - if (proc_id == INIT_PID && signo == SIGKILL) return(EINVAL); - - /* Search the proc table for processes to signal. (See forkexit.c about - * pid magic.) - */ - count = 0; - error_code = ESRCH; - for (rmp = &mproc[INIT_PROC_NR]; rmp < &mproc[NR_PROCS]; rmp++) { - if (!(rmp->mp_flags & IN_USE)) continue; - if ((rmp->mp_flags & ZOMBIE) && signo != 0) continue; - - /* Check for selection. */ - if (proc_id > 0 && proc_id != rmp->mp_pid) continue; - if (proc_id == 0 && mp->mp_procgrp != rmp->mp_procgrp) continue; - if (proc_id == -1 && rmp->mp_pid <= INIT_PID) continue; - if (proc_id < -1 && rmp->mp_procgrp != -proc_id) continue; - - /* Check for permission. */ - if (mp->mp_effuid != SUPER_USER - && mp->mp_realuid != rmp->mp_realuid - && mp->mp_effuid != rmp->mp_realuid - && mp->mp_realuid != rmp->mp_effuid - && mp->mp_effuid != rmp->mp_effuid) { - error_code = EPERM; - continue; - } - - count++; - if (signo == 0) continue; - - /* 'sig_proc' will handle the disposition of the signal. The - * signal may be caught, blocked, ignored, or cause process - * termination, possibly with core dump. - */ - sig_proc(rmp, signo); - - if (proc_id > 0) break; /* only one process being signaled */ - } - - /* If the calling process has killed itself, don't reply. */ - if ((mp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) return(SUSPEND); - return(count > 0 ? OK : error_code); -} - - -/*===========================================================================* - * check_pending * - *===========================================================================*/ -PUBLIC void check_pending(rmp) -register struct mproc *rmp; -{ - /* Check to see if any pending signals have been unblocked. The - * first such signal found is delivered. - * - * If multiple pending unmasked signals are found, they will be - * delivered sequentially. - * - * There are several places in this file where the signal mask is - * changed. At each such place, check_pending() should be called to - * check for newly unblocked signals. - */ - - int i; - - for (i = 1; i <= _NSIG; i++) { - if (sigismember(&rmp->mp_sigpending, i) && - !sigismember(&rmp->mp_sigmask, i)) { - sigdelset(&rmp->mp_sigpending, i); - sig_proc(rmp, i); - break; - } - } -} - - -/*===========================================================================* - * unpause * - *===========================================================================*/ -PRIVATE void unpause(pro) -int pro; /* which process number */ -{ -/* A signal is to be sent to a process. If that process is hanging on a - * system call, the system call must be terminated with EINTR. Possible - * calls are PAUSE, WAIT, READ and WRITE, the latter two for pipes and ttys. - * First check if the process is hanging on an MM call. If not, tell FS, - * so it can check for READs and WRITEs from pipes, ttys and the like. - */ - - register struct mproc *rmp; - - rmp = &mproc[pro]; - - /* Check to see if process is hanging on a PAUSE, WAIT or SIGSUSPEND call. */ - if (rmp->mp_flags & (PAUSED | WAITING | SIGSUSPENDED)) { - rmp->mp_flags &= ~(PAUSED | WAITING | SIGSUSPENDED); - setreply(pro, EINTR); - return; - } - - /* Process is not hanging on an MM call. Ask FS to take a look. */ - tell_fs(UNPAUSE, pro, 0, 0); -} - - -/*===========================================================================* - * dump_core * - *===========================================================================*/ -PRIVATE void dump_core(rmp) -register struct mproc *rmp; /* whose core is to be dumped */ -{ -/* Make a core dump on the file "core", if possible. */ - - int s, fd, fake_fd, nr_written, seg, slot; - char *buf; - vir_bytes current_sp; - phys_bytes left; /* careful; 64K might overflow vir_bytes */ - unsigned nr_to_write; /* unsigned for arg to write() but < INT_MAX */ - long trace_data, trace_off; - - slot = (int) (rmp - mproc); - - /* Can core file be written? We are operating in the user's FS environment, - * so no special permission checks are needed. - */ - if (rmp->mp_realuid != rmp->mp_effuid) return; - if ( (fd = open(core_name, O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, - CORE_MODE)) < 0) return; - rmp->mp_sigstatus |= DUMPED; - - /* Make sure the stack segment is up to date. - * We don't want adjust() to fail unless current_sp is preposterous, - * but it might fail due to safety checking. Also, we don't really want - * the adjust() for sending a signal to fail due to safety checking. - * Maybe make SAFETY_BYTES a parameter. - */ - if ((s=p_getsp(slot, ¤t_sp)) != OK) - panic("MM couldn't get new stack pointer",s); - adjust(rmp, rmp->mp_seg[D].mem_len, current_sp); - - /* Write the memory map of all segments to begin the core file. */ - if (write(fd, (char *) rmp->mp_seg, (unsigned) sizeof rmp->mp_seg) - != (unsigned) sizeof rmp->mp_seg) { - close(fd); - return; - } - - /* Write out the whole kernel process table entry to get the regs. */ - trace_off = 0; - while (sys_trace(3, slot, trace_off, &trace_data) == OK) { - if (write(fd, (char *) &trace_data, (unsigned) sizeof (long)) - != (unsigned) sizeof (long)) { - close(fd); - return; - } - trace_off += sizeof (long); - } - - /* Loop through segments and write the segments themselves out. */ - for (seg = 0; seg < NR_LOCAL_SEGS; seg++) { - rw_seg(1, fd, slot, seg, - (phys_bytes) rmp->mp_seg[seg].mem_len << CLICK_SHIFT); - } - close(fd); -} diff --git a/servers/mm/table.c b/servers/mm/table.c deleted file mode 100644 index 1962678cd..000000000 --- a/servers/mm/table.c +++ /dev/null @@ -1,108 +0,0 @@ -/* This file contains the table used to map system call numbers onto the - * routines that perform them. - */ - -#define _TABLE - -#include "mm.h" -#include -#include -#include "mproc.h" -#include "param.h" - -/* Miscellaneous */ -char core_name[] = "core"; /* file name where core images are produced */ - -_PROTOTYPE (int (*call_vec[NCALLS]), (void) ) = { - no_sys, /* 0 = unused */ - do_mm_exit, /* 1 = exit */ - do_fork, /* 2 = fork */ - no_sys, /* 3 = read */ - no_sys, /* 4 = write */ - no_sys, /* 5 = open */ - no_sys, /* 6 = close */ - do_waitpid, /* 7 = wait */ - no_sys, /* 8 = creat */ - no_sys, /* 9 = link */ - no_sys, /* 10 = unlink */ - do_waitpid, /* 11 = waitpid */ - no_sys, /* 12 = chdir */ - no_sys, /* 13 = time */ - no_sys, /* 14 = mknod */ - no_sys, /* 15 = chmod */ - no_sys, /* 16 = chown */ - do_brk, /* 17 = break */ - no_sys, /* 18 = stat */ - no_sys, /* 19 = lseek */ - do_getset, /* 20 = getpid */ - no_sys, /* 21 = mount */ - no_sys, /* 22 = umount */ - do_getset, /* 23 = setuid */ - do_getset, /* 24 = getuid */ - no_sys, /* 25 = stime */ - do_trace, /* 26 = ptrace */ - do_alarm, /* 27 = alarm */ - no_sys, /* 28 = fstat */ - do_pause, /* 29 = pause */ - no_sys, /* 30 = utime */ - no_sys, /* 31 = (stty) */ - no_sys, /* 32 = (gtty) */ - no_sys, /* 33 = access */ - no_sys, /* 34 = (nice) */ - no_sys, /* 35 = (ftime) */ - no_sys, /* 36 = sync */ - do_kill, /* 37 = kill */ - no_sys, /* 38 = rename */ - no_sys, /* 39 = mkdir */ - no_sys, /* 40 = rmdir */ - no_sys, /* 41 = dup */ - no_sys, /* 42 = pipe */ - no_sys, /* 43 = times */ - no_sys, /* 44 = (prof) */ - no_sys, /* 45 = unused */ - do_getset, /* 46 = setgid */ - do_getset, /* 47 = getgid */ - no_sys, /* 48 = (signal)*/ - no_sys, /* 49 = unused */ - no_sys, /* 50 = unused */ - no_sys, /* 51 = (acct) */ - no_sys, /* 52 = (phys) */ - no_sys, /* 53 = (lock) */ - no_sys, /* 54 = ioctl */ - no_sys, /* 55 = fcntl */ - no_sys, /* 56 = (mpx) */ - no_sys, /* 57 = unused */ - no_sys, /* 58 = unused */ - do_exec, /* 59 = execve */ - no_sys, /* 60 = umask */ - no_sys, /* 61 = chroot */ - do_getset, /* 62 = setsid */ - do_getset, /* 63 = getpgrp */ - - do_ksig, /* 64 = KSIG: signals originating in the kernel */ - no_sys, /* 65 = UNPAUSE */ - no_sys, /* 66 = unused */ - no_sys, /* 67 = REVIVE */ - no_sys, /* 68 = TASK_REPLY */ - no_sys, /* 69 = unused */ - no_sys, /* 70 = unused */ - do_sigaction, /* 71 = sigaction */ - do_sigsuspend, /* 72 = sigsuspend */ - do_sigpending, /* 73 = sigpending */ - do_sigprocmask, /* 74 = sigprocmask */ - do_sigreturn, /* 75 = sigreturn */ - do_reboot, /* 76 = reboot */ - do_svrctl, /* 77 = svrctl */ - - no_sys, /* 78 = cmostime */ - do_getsysinfo, /* 79 = getsysinfo */ -#if ENABLE_MESSAGE_STATS - do_mstats, /* 80 = mstats */ -#else - no_sys, -#endif - no_sys, /* 81 = unused */ - no_sys, /* 82 = unused */ -}; -/* This should not fail with "array size is negative": */ -extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1]; diff --git a/servers/mm/trace.c b/servers/mm/trace.c deleted file mode 100644 index 731324ecf..000000000 --- a/servers/mm/trace.c +++ /dev/null @@ -1,111 +0,0 @@ -/* This file handles the memory manager's part of debugging, using the - * ptrace system call. Most of the commands are passed on to the system - * task for completion. - * - * The debugging commands available are: - * T_STOP stop the process - * T_OK enable tracing by parent for this process - * T_GETINS return value from instruction space - * T_GETDATA return value from data space - * T_GETUSER return value from user process table - * T_SETINS set value in instruction space - * T_SETDATA set value in data space - * T_SETUSER set value in user process table - * T_RESUME resume execution - * T_EXIT exit - * T_STEP set trace bit - * - * The T_OK and T_EXIT commands are handled here, and the T_RESUME and - * T_STEP commands are partially handled here and completed by the system - * task. The rest are handled entirely by the system task. - */ - -#include "mm.h" -#include -#include -#include -#include "mproc.h" -#include "param.h" - -#define NIL_MPROC ((struct mproc *) 0) - -FORWARD _PROTOTYPE( struct mproc *findproc, (pid_t lpid) ); - -/*===========================================================================* - * do_trace * - *===========================================================================*/ -PUBLIC int do_trace() -{ - register struct mproc *child; - - /* the T_OK call is made by the child fork of the debugger before it execs - * the process to be traced - */ - if (m_in.request == T_OK) { /* enable tracing by parent for this proc */ - mp->mp_flags |= TRACED; - mp->mp_reply.reply_trace = 0; - return(OK); - } - if ((child=findproc(m_in.pid))==NIL_MPROC || !(child->mp_flags & STOPPED)) { - return(ESRCH); - } - /* all the other calls are made by the parent fork of the debugger to - * control execution of the child - */ - switch (m_in.request) { - case T_EXIT: /* exit */ - mm_exit(child, (int) m_in.data); - mp->mp_reply.reply_trace = 0; - return(OK); - case T_RESUME: - case T_STEP: /* resume execution */ - if (m_in.data < 0 || m_in.data > _NSIG) return(EIO); - if (m_in.data > 0) { /* issue signal */ - child->mp_flags &= ~TRACED; /* so signal is not diverted */ - sig_proc(child, (int) m_in.data); - child->mp_flags |= TRACED; - } - child->mp_flags &= ~STOPPED; - break; - } - if (sys_trace(m_in.request,(int)(child-mproc),m_in.taddr,&m_in.data) != OK) - return(-errno); - mp->mp_reply.reply_trace = m_in.data; - return(OK); -} - -/*===========================================================================* - * findproc * - *===========================================================================*/ -PRIVATE struct mproc *findproc(lpid) -pid_t lpid; -{ - register struct mproc *rmp; - - for (rmp = &mproc[INIT_PROC_NR + 1]; rmp < &mproc[NR_PROCS]; rmp++) - if (rmp->mp_flags & IN_USE && rmp->mp_pid == lpid) return(rmp); - return(NIL_MPROC); -} - -/*===========================================================================* - * stop_proc * - *===========================================================================*/ -PUBLIC void stop_proc(rmp, signo) -register struct mproc *rmp; -int signo; -{ -/* A traced process got a signal so stop it. */ - - register struct mproc *rpmp = mproc + rmp->mp_parent; - - if (sys_trace(-1, (int) (rmp - mproc), 0L, (long *) 0) != OK) return; - rmp->mp_flags |= STOPPED; - if (rpmp->mp_flags & WAITING) { - rpmp->mp_flags &= ~WAITING; /* parent is no longer waiting */ - rpmp->mp_reply.reply_res2 = 0177 | (signo << 8); - setreply(rmp->mp_parent, rmp->mp_pid); - } else { - rmp->mp_sigstatus = signo; - } - return; -} diff --git a/servers/mm/type.h b/servers/mm/type.h deleted file mode 100644 index 65d9c846c..000000000 --- a/servers/mm/type.h +++ /dev/null @@ -1,5 +0,0 @@ -/* If there were any type definitions local to the Memory Manager, they would - * be here. This file is included only for symmetry with the kernel and File - * System, which do have some local type definitions. - */ - diff --git a/servers/mm/utility.c b/servers/mm/utility.c deleted file mode 100644 index e82f4f9bd..000000000 --- a/servers/mm/utility.c +++ /dev/null @@ -1,114 +0,0 @@ -/* This file contains some utility routines for MM. - * - * The entry points are: - * allowed: see if an access is permitted - * no_sys: this routine is called for invalid system call numbers - * panic: MM has run aground of a fatal error and cannot continue - * tell_fs: interface to FS - */ - -#include "mm.h" -#include -#include -#include -#include -#include /* needed only because mproc.h needs it */ -#include "mproc.h" -#include "param.h" - -/*===========================================================================* - * allowed * - *===========================================================================*/ -PUBLIC int allowed(name_buf, s_buf, mask) -char *name_buf; /* pointer to file name to be EXECed */ -struct stat *s_buf; /* buffer for doing and returning stat struct*/ -int mask; /* R_BIT, W_BIT, or X_BIT */ -{ -/* Check to see if file can be accessed. Return EACCES or ENOENT if the access - * is prohibited. If it is legal open the file and return a file descriptor. - */ - - int fd; - int save_errno; - - /* Use the fact that mask for access() is the same as the permissions mask. - * E.g., X_BIT in is the same as X_OK in and - * S_IXOTH in . tell_fs(DO_CHDIR, ...) has set MM's real ids - * to the user's effective ids, so access() works right for setuid programs. - */ - if (access(name_buf, mask) < 0) return(-errno); - - /* The file is accessible but might not be readable. Make it readable. */ - tell_fs(SETUID, PM_PROC_NR, (int) SUPER_USER, (int) SUPER_USER); - - /* Open the file and fstat it. Restore the ids early to handle errors. */ - fd = open(name_buf, O_RDONLY | O_NONBLOCK); - save_errno = errno; /* open might fail, e.g. from ENFILE */ - tell_fs(SETUID, PM_PROC_NR, (int) mp->mp_effuid, (int) mp->mp_effuid); - if (fd < 0) return(-save_errno); - if (fstat(fd, s_buf) < 0) panic("allowed: fstat failed", NO_NUM); - - /* Only regular files can be executed. */ - if (mask == X_BIT && (s_buf->st_mode & I_TYPE) != I_REGULAR) { - close(fd); - return(EACCES); - } - return(fd); -} - - -/*===========================================================================* - * no_sys * - *===========================================================================*/ -PUBLIC int no_sys() -{ -/* A system call number not implemented by MM has been requested. */ - - return(EINVAL); -} - - -/*===========================================================================* - * panic * - *===========================================================================*/ -PUBLIC void panic(format, num) -char *format; /* format string */ -int num; /* number to go with format string */ -{ -/* Something awful has happened. Panics are caused when an internal - * inconsistency is detected, e.g., a programming error or illegal value of a - * defined constant. - */ - - printf("Memory manager panic: %s ", format); - if (num != NO_NUM) printf("%d",num); - printf("\n"); - tell_fs(SYNC, 0, 0, 0); /* flush the cache to the disk */ - sys_abort(RBT_PANIC); -} - - -/*===========================================================================* - * tell_fs * - *===========================================================================*/ -PUBLIC void tell_fs(what, p1, p2, p3) -int what, p1, p2, p3; -{ -/* This routine is only used by MM to inform FS of certain events: - * tell_fs(CHDIR, slot, dir, 0) - * tell_fs(EXEC, proc, 0, 0) - * tell_fs(EXIT, proc, 0, 0) - * tell_fs(FORK, parent, child, pid) - * tell_fs(SETGID, proc, realgid, effgid) - * tell_fs(SETSID, proc, 0, 0) - * tell_fs(SETUID, proc, realuid, effuid) - * tell_fs(SYNC, 0, 0, 0) - * tell_fs(UNPAUSE, proc, signr, 0) - */ - message m; - - m.tell_fs_arg1 = p1; - m.tell_fs_arg2 = p2; - m.tell_fs_arg3 = p3; - _taskcall(FS_PROC_NR, what, &m); -}