home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright 1990,1991,1992 Eric R. Smith. All rights reserved.
- */
-
- /*
- * mem.c:: routines for managing memory regions
- */
-
- #include "mint.h"
-
- static long core_malloc P_((long, int));
-
- /* macro for testing whether a memory region is free */
- #define ISFREE(m) ((m)->links == 0)
-
- /*
- * initialize memory routines
- */
-
- /* initial number of memory regions */
- #define NREGIONS 512
-
- /* number of new regions to allocate when the initial ones are used up */
- #define NEWREGIONS 256
-
- static MEMREGION use_regions[NREGIONS+1];
- MEMREGION *rfreelist;
-
- void
- init_mem()
- {
- int i;
-
- use_regions[NREGIONS].next = 0;
- for (i = 0; i < NREGIONS; i++) {
- use_regions[i].next = &use_regions[i+1];
- }
- rfreelist = use_regions;
-
- init_core();
- init_swap();
- }
-
- /*
- * init_core(): initialize the core memory map (normal ST ram) and also
- * the alternate memory map (fast ram on the TT)
- */
-
- static MEMREGION *_core_regions = 0, *_alt_regions = 0,
- *_ker_regions = 0;
-
- MMAP core = &_core_regions;
- MMAP alt = &_alt_regions;
- MMAP ker = &_ker_regions;
-
- /* note: add_region must adjust both the size and starting
- * address of the region being added so that memory is
- * always properly aligned
- */
-
- int
- add_region(map, place, size, mflags)
- MMAP map;
- ulong place, size;
- unsigned mflags; /* initial flags for region */
- {
- MEMREGION *m;
- ulong newplace;
-
- newplace = ROUND(place);
- size = (place + size) - newplace;
- size &= ~MASKBITS;
- if (size <= 0) /* region too small to use */
- return 1;
-
- m = new_region();
- if (m == 0)
- return 0; /* failure */
- m->links = 0;
- m->len = size;
- m->loc = newplace;
- m->next = *map;
- m->mflags = mflags;
- *map = m;
- return 1; /* success */
- }
-
- static long
- core_malloc(amt, mode)
- long amt;
- int mode;
- {
- static int mxalloc = -1; /* does GEMDOS know about Mxalloc? */
- long ret;
-
- if (mxalloc < 0) {
- ret = (long)Mxalloc(-1L, 0);
- if (ret == -32) mxalloc = 0; /* unknown function */
- else if (ret >= 0) mxalloc = 1;
- else {
- ALERT("GEMDOS returned %ld from Mxalloc", ret);
- mxalloc = 0;
- }
- }
- if (mxalloc)
- return Mxalloc(amt, mode);
- else if (mode == 1)
- return 0L;
- else
- return Malloc(amt);
- }
-
- void
- init_core()
- {
- #ifdef JUNK_MEM
- extern void fillwjunk();
- #endif
- ulong size;
- ulong place;
- void *tossave;
-
- tossave = (void *)core_malloc((long)TOS_MEM, 0);
- if (!tossave) {
- FATAL("Not enough memory to run MiNT");
- }
-
- /* initialize kernel memory */
- place = (ulong)core_malloc(KERNEL_MEM, 3);
- if (place != 0) {
- (void)add_region(ker, place, KERNEL_MEM, M_KER);
- #ifdef JUNK_MEM
- fillwjunk(place, (long)KERNEL_MEM);
- #endif
- }
-
- /* initialize ST RAM */
- size = (ulong)core_malloc(-1L, 0);
- while (size > 0) {
- place = (ulong)core_malloc(size, 0);
- if (!add_region(core, place, size, M_CORE))
- FATAL("init_mem: unable to add a region");
- #ifdef JUNK_MEM
- fillwjunk(place, size);
- #endif
- size = (ulong)core_malloc(-1L, 0);
- }
-
- /* initialize alternate RAM */
- size = (ulong)core_malloc(-1L, 1);
- while (size > 0) {
- place = (ulong)core_malloc(size, 1);
- if (!add_region(alt, place, size, M_ALT))
- FATAL("init_mem: unable to add a region");
- size = (ulong)core_malloc(-1L, 1);
- }
-
- (void)Mfree(tossave); /* leave some memory for TOS to use */
- }
-
- /*
- * init_swap(): initialize the swap area; for now, this does nothing
- */
-
- MEMREGION *_swap_regions = 0;
- MMAP swap = &_swap_regions;
-
- void
- init_swap()
- {
- }
-
- /*
- * routines for allocating/deallocating memory regions
- */
-
- /*
- * new_region returns a new memory region descriptor, or NULL
- */
-
- MEMREGION *
- new_region()
- {
- MEMREGION *m, *newfrees;
- int i;
-
- m = rfreelist;
- if (!m) {
- ALERT("new_region: ran out of free regions");
- return 0;
- }
- assert(ISFREE(m));
- rfreelist = m->next;
- m->next = 0;
-
- /* if we're running low on free regions, allocate some more
- * we have to do this with at least 1 free region left so that get_region
- * has a chance of working
- */
- if (rfreelist && !rfreelist->next) {
- MEMREGION *newstuff;
-
- TRACE("get_region: getting new region descriptors");
- newstuff = get_region(ker, NEWREGIONS*SIZEOF(MEMREGION));
- if (!newstuff)
- newstuff = get_region(alt,NEWREGIONS*SIZEOF(MEMREGION));
- if (!newstuff)
- newstuff = get_region(core, NEWREGIONS*SIZEOF(MEMREGION));
- newfrees = newstuff ? (MEMREGION *)newstuff->loc : 0;
- if (newfrees) {
- newfrees[NEWREGIONS-1].next = 0;
- newfrees[NEWREGIONS-1].links = 0;
- for (i = 0; i < NEWREGIONS-1; i++) {
- newfrees[i].next = &newfrees[i+1];
- newfrees[i].links = 0;
- }
- rfreelist = newfrees;
- } else {
- DEBUG("couldn't get new region descriptors!");
- }
- }
-
- return m;
- }
-
- /*
- * dispose_region destroys a memory region descriptor
- */
-
- void
- dispose_region(m)
- MEMREGION *m;
- {
- assert(ISFREE(m));
- m->next = rfreelist;
- rfreelist = m;
- }
-
- /*
- * virtaddr
- * attach_region(proc, reg): attach the region to the given process:
- * returns the address at which it was attached, or NULL if the process
- * cannot attach more regions. The region link count is incremented if
- * the attachment is successful.
- */
-
- virtaddr
- attach_region(proc, reg)
- PROC *proc;
- MEMREGION *reg;
- {
- int i;
- MEMREGION **newmem;
- virtaddr *newaddr;
-
- if (!reg || !reg->loc) {
- ALERT("attach_region: attaching a null region??");
- return 0;
- }
- for (i = 0; i < proc->num_reg; i++) {
- if (!proc->mem[i]) {
- assert(proc->addr[i] == 0);
- reg->links++;
- proc->mem[i] = reg;
- proc->addr[i] = (virtaddr) reg->loc;
- return proc->addr[i];
- }
- }
-
- /* Hmmm, OK, we have to expand the process' memory table */
- TRACE("Expanding process memory table");
- i = proc->num_reg + NUM_REGIONS;
-
- newmem = kmalloc(i * SIZEOF(MEMREGION *));
- newaddr = kmalloc(i * SIZEOF(virtaddr));
-
- if (newmem && newaddr) {
- /* copy over the old address mapping */
- for (i = 0; i < proc->num_reg; i++) {
- newmem[i] = proc->mem[i];
- newaddr[i] = proc->addr[i];
- if (newmem[i] == 0)
- assert(newaddr[i] == 0);
- }
- /* initialize the rest of the tables */
- for(; i < proc->num_reg + NUM_REGIONS; i++) {
- newmem[i] = 0;
- newaddr[i] = 0;
- }
- /* free the old tables */
- kfree(proc->mem); kfree(proc->addr);
- proc->mem = newmem;
- proc->addr = newaddr;
- proc->num_reg += NUM_REGIONS;
- /* this call will succeed */
- TRACE("recursively calling attach_region");
- return attach_region(proc, reg);
- }
-
- DEBUG("attach_region: failed");
- return 0;
- }
-
- /*
- * detach_region(proc, reg): remove region from the procedure's address
- * space. If no more processes reference the region, return it to the
- * system. Note that we search backwards, so that the most recent
- * attachment of memory gets detached!
- */
-
- void
- detach_region(proc, reg)
- PROC *proc;
- MEMREGION *reg;
- {
- int i;
-
- if (!reg) return;
- for (i = proc->num_reg - 1; i >= 0; i--) {
- if (proc->mem[i] == reg) {
- reg->links--;
- proc->mem[i] = 0; proc->addr[i] = 0;
- if (reg->links == 0) {
- free_region(reg);
- }
- return;
- }
- }
- DEBUG("detach_region: region not attached");
- }
-
- /*
- * get_region(MMAP map, ulong size) -- allocate a new region of the
- * given size in the given memory map. if no region big enough is available,
- * return NULL, otherwise return a pointer to the region.
- * the "links" field in the region is set to 1
- *
- * BEWARE: new_region may call get_region (indirectly), so we have to be
- * _very_ careful with re-entrancy in this function
- */
-
- MEMREGION *
- get_region(map, size)
- MMAP map;
- ulong size;
- {
- MEMREGION *m, *n;
-
- /* precautionary measures */
- if (size == 0) {
- DEBUG("request for 0 bytes??");
- size = 1;
- }
-
- size = ROUND(size);
-
- n = *map;
-
- sanity_check(map);
- /* exact matches are likely to be rare, so we pre-allocate a new
- * region here; this helps us to avoid re-entrancy problems
- * when new_region calls get_region
- */
- m = new_region();
-
- while (n) {
- if (ISFREE(n)) {
- if (n->len == size) {
- if (m) dispose_region(m);
- n->links++;
- return n;
- }
- else if (n->len > size) {
- /* split a new region, 'm', which will contain the free bytes after n */
- if (m) {
- m->next = n->next;
- n->next = m;
- m->mflags = n->mflags & M_MAP;
- m->loc = n->loc + size;
- m->len = n->len - size;
- n->len = size;
- n->links++;
- return n;
- } else {
- DEBUG("get_region: no regions left");
- return 0;
- }
- }
- }
- n = n->next;
- }
-
- if (m)
- dispose_region(m);
- return NULL;
- }
-
- /*
- * free_region(MEMREGION *reg): free the indicated region. The map
- * in which the region is contained is given by reg->mflags.
- * the caller is responsible for making sure that the region
- * really should be freed, i.e. that reg->links == 0.
- */
-
- void
- free_region(reg)
- MEMREGION *reg;
- {
- MMAP map;
- MEMREGION *m;
-
- if (!reg) return;
-
- assert(ISFREE(reg));
-
- if (reg->mflags & M_CORE)
- map = core;
- else if (reg->mflags & M_ALT)
- map = alt;
- else if (reg->mflags & M_KER)
- map = ker;
- else {
- FATAL("free_region: region flags not valid (%x)", reg->mflags);
- }
- reg->mflags &= M_MAP;
- m = *map;
- assert(m);
-
- if (m == reg) goto merge_after;
-
- /* merge previous region if it's free and contiguous with 'reg' */
-
- /* first, we find the region */
- while (m && m->next != reg)
- m = m->next;
-
- assert(m != NULL);
-
- if (ISFREE(m) && (m->loc + m->len == reg->loc)) {
- m->len += reg->len;
- assert(m->next == reg);
- m->next = reg->next;
- reg->next = 0;
- dispose_region(reg);
- reg = m;
- }
-
- /* merge next region if it's free and contiguous with 'reg' */
- merge_after:
- m = reg->next;
- if (m && ISFREE(m) && reg->loc + reg->len == m->loc) {
- reg->len += m->len;
- reg->next = m->next;
- m->next = 0;
- dispose_region(m);
- }
-
- sanity_check(map);
- }
-
- /*
- * shrink_region(MEMREGION *reg, ulong newsize):
- * shrink region 'reg', so that it is now 'newsize' bytes long.
- * if 'newsize' is bigger than the region's current size, return EGSBF;
- * otherwise return 0.
- */
-
- long
- shrink_region(reg, newsize)
- MEMREGION *reg;
- ulong newsize;
- {
- MMAP map;
- MEMREGION *n;
- ulong diff;
-
-
- newsize = ROUND(newsize);
-
- assert(reg->links > 0);
-
- if (reg->mflags & M_CORE)
- map = core;
- else if (reg->mflags & M_ALT)
- map = alt;
- else if (reg->mflags & M_KER)
- map = ker;
- else {
- FATAL("shrink_region: bad region flags (%x)", reg->mflags);
- }
-
- /* shrinking to 0 is the same as freeing */
- if (newsize == 0) {
- detach_region(curproc, reg);
- return 0;
- }
-
- /* if new size is the same as old size, don't do anything */
- if (newsize == reg->len) {
- return 0; /* nothing to do */
- }
-
- if (newsize > reg->len) {
- DEBUG("shrink_region: request to make region bigger");
- return EGSBF; /* growth failure */
- }
-
- /* OK, we're going to free (reg->len - newsize) bytes at the end of
- this block. If the block after us is already free, simply add the
- space to that block.
- */
- n = reg->next;
- diff = reg->len - newsize;
-
- if (n && ISFREE(n) && reg->loc + reg->len == n->loc) {
- reg->len = newsize;
- n->loc -= diff;
- n->len += diff;
- return 0;
- }
- else {
- n = new_region();
- if (!n) {
- DEBUG("shrink_region: new_region failed");
- return EINTRN;
- }
- reg->len = newsize;
- n->loc = reg->loc + newsize;
- n->len = diff;
- n->mflags = reg->mflags & M_MAP;
- n->next = reg->next;
- reg->next = n;
- }
- return 0;
- }
-
- /*
- * max_rsize(map): return the length of the biggest free region
- * in the given memory map, or 0 if no regions remain.
- */
-
- long
- max_rsize(map)
- MMAP map;
- {
- MEMREGION *m, *max = 0;
- long size = 0;
-
- for (m = *map; m; m = m->next) {
- if (ISFREE(m)) {
- if (m->len > size) {
- max = m;
- size = m->len;
- }
- }
- }
- return size;
- }
-
- /*
- * tot_rsize(map, flag): if flag == 1, return the total number of bytes in
- * the given memory map; if flag == 0, return only the number of free
- * bytes
- */
-
- long
- tot_rsize(map, flag)
- MMAP map;
- int flag;
- {
- MEMREGION *m;
- long size = 0;
-
- for (m = *map; m; m = m->next) {
- if (flag || ISFREE(m)) {
- size += m->len;
- }
- }
- return size;
- }
-
- /*
- * alloc_region(MMAP map, ulong size): allocate a new region and attach
- * it to the current process; returns the address at which the region
- * was attached, or NULL. If not enough memory is found, wait a bit
- * and try again before giving up (maybe someone else will free some
- * memory)
- */
-
- virtaddr
- alloc_region(map, size)
- MMAP map;
- ulong size;
- {
- MEMREGION *m;
- PROC *proc = curproc;
- virtaddr v;
-
- m = get_region(map, size);
- if (!m) {
- return 0;
- }
-
- v = attach_region(proc, m);
- /* NOTE: get_region returns a region with link count 1; since attach_region
- * increments the link count, we restore it after calling attach_region
- */
- m->links = 1;
- if (!v) {
- m->links = 0;
- free_region(m);
- return 0;
- }
- return v;
- }
-
- /*
- * routines for creating a copy of an environment, and a new basepage.
- * note that the memory regions created should immediately be attached to
- * a process! Also note that create_env always operates in ST RAM, but
- * create_base might not.
- */
-
- MEMREGION *
- create_env(env)
- const char *env;
- {
- long size;
- MEMREGION *m;
- virtaddr v;
- const char *old;
- char *new;
-
- if (!env) {
- env = ((BASEPAGE *)curproc->base)->p_env;
- /* duplicate parent's environment */
- }
- size = 2;
- old = env;
- while (*env || *(env+1))
- env++,size++;
- v = alloc_region(core, size);
- if (!v) {
- DEBUG("create_env: alloc_region failed");
- return (MEMREGION *)0;
- }
- m = addr2mem(v);
-
- /* copy the old environment into the new */
- new = (char *) m->loc;
- while (size > 0) {
- *new++ = *old++;
- --size;
- }
- return m;
- }
-
- MEMREGION *
- create_base(cmd, env, flags, prgsize)
- const char *cmd;
- MEMREGION *env;
- ulong flags, prgsize;
- {
- long len, coresize, altsize;
- MMAP map;
- MEMREGION *m;
- BASEPAGE *b;
-
- /* if flags & F_ALTLOAD == 1, then we might decide to load in alternate
- RAM if enough is available. "enough" is: if more alt ram than ST ram,
- load there; otherwise, if more than (minalt+1)*128K alt ram available
- for heap space, load in alt ram ("minalt" is the high byte of flags)
- */
- if (flags & F_ALTLOAD) {
- coresize = max_rsize(core);
- altsize = max_rsize(alt);
- if (altsize >= coresize)
- map = alt;
- else {
- len = (flags & 0xf0000000) >> 28L;
- len = (len+1)*128*1024L + prgsize + 256;
- if (altsize >= len)
- map = alt;
- else
- map = core;
- }
- }
- else
- map = core;
-
- len = max_rsize(map);
-
- /* make sure that a little bit of memory is left over */
- if (len > 2*KEEP_MEM) {
- len -= KEEP_MEM;
- }
- m = addr2mem(alloc_region(map, len));
- if (!m) {
- DEBUG("create_base: alloc_region failed");
- return 0;
- }
- b = (BASEPAGE *)(m->loc);
-
- zero((char *)b, (long)sizeof(BASEPAGE));
- b->p_lowtpa = (long)b;
- b->p_hitpa = m->loc + m->len;
- b->p_env = (char *)env->loc;
- b->p_flags = flags;
-
- if (cmd)
- strncpy(b->p_cmdlin, cmd, 126);
- return m;
- }
-
- /*
- * load_region(filename): loads the program with the given file name
- * into a new region, and returns a pointer to that region. On an error,
- * returns 0 and leaves the error number in mint_errno.
- */
-
- static struct fileheader {
- short fmagic;
- long ftext;
- long fdata;
- long fbss;
- long fsym;
- long reserved;
- long flag;
- short reloc;
- } fh;
-
- MEMREGION *
- load_region(filename, env, cmdlin, xp)
- const char *filename;
- MEMREGION *env;
- const char *cmdlin;
- XATTR *xp; /* attributes for the file just loaded */
- {
- FILEPTR *f;
- DEVDRV *dev;
- MEMREGION *reg;
- BASEPAGE *b;
- long size, fixup, base, bytes_read;
- unsigned char c, *next;
- #define LRBUFSIZ 8196
- static unsigned char buffer[LRBUFSIZ];
- int trycount = 0;
-
- next = buffer;
-
- f = do_open(filename, O_DENYNONE | O_EXEC, 0, xp);
- if (!f) {
- return 0; /* mint_errno set by do_open */
- }
-
- dev = f->dev; /* could be different from fs */
- if ( (*dev->read)(f, (void *)&fh, (long)sizeof(fh)) != sizeof(fh) ||
- fh.fmagic != 0x601a ) {
- DEBUG("load_region: file not executable");
- mint_errno = ENOEXEC;
- failed:
- do_close(f);
- return 0;
- }
-
- size = fh.ftext + fh.fdata + fh.fbss;
- reg = 0;
- for (trycount = 0; (trycount < 1) && (reg == 0); trycount++) {
- reg = create_base(cmdlin, env, fh.flag, size);
- if (size+1024L > reg->len) {
- DEBUG("load_region: insufficient memory to load");
- detach_region(curproc, reg);
- reg = 0;
- }
- if (!reg) {
- /* maybe the memory shortage is short-term; sleep a bit to see */
- nap(10);
- }
- }
-
- if (reg == 0) {
- mint_errno = ENSMEM;
- goto failed;
- }
-
- b = (BASEPAGE *)reg->loc;
- b->p_flags = fh.flag;
- b->p_tbase = b->p_lowtpa + 256;
- b->p_tlen = fh.ftext;
- b->p_dbase = b->p_tbase + b->p_tlen;
- b->p_dlen = fh.fdata;
- b->p_bbase = b->p_dbase + b->p_dlen;
- size = (*dev->read)(f, (void *)b->p_tbase, fh.ftext+fh.fdata);
- if (size != fh.ftext + fh.fdata) {
- DEBUG("load_region: unexpected EOF");
- failed_reloc: /* come here when loading/relocation fails */
- mint_errno = ENOEXEC;
- detach_region(curproc, reg);
- goto failed;
- }
-
- b->p_blen = fh.fbss;
- if (fh.flag & F_FASTLOAD) /* fastload bit */
- size = b->p_blen;
- else
- size = b->p_hitpa - b->p_bbase;
- zero((char *)b->p_bbase, size);
- (*dev->lseek)(f, fh.fsym, SEEK_CUR); /* skip over symbol table */
- base = b->p_tbase;
-
- /* now read the relocation info; we use the temporary buffer provided
- * above to speed things up
- */
-
- if (fh.reloc == 0 && (*dev->read)(f, (char *)&fixup, 4L) && fixup) {
- fixup += base;
- size = LRBUFSIZ;
- bytes_read = 0;
- do {
- if (fixup >= b->p_hitpa) {
- DEBUG("load_region: bad relocation");
- goto failed_reloc;
- }
- else
- *((long *)fixup) += base;
- do {
- if (!bytes_read) {
- bytes_read =
- (*dev->read)(f,(char *)buffer,size);
- next = buffer;
- }
- if (bytes_read < 0) {
- DEBUG("load_region: EOF in relocation");
- goto failed_reloc;
- }
- else if (bytes_read == 0)
- c = 0;
- else {
- c = *next++; bytes_read--;
- }
- if (c == 1) fixup += 254;
- } while (c == 1);
- fixup += ( (unsigned) c) & 0xff;
- } while (c);
- }
-
- do_close(f);
- return reg;
- }
-
- /*
- * exec_region(p, mem, thread): create a child process out of a mem region
- * "p" is the process structure set up by the parent; it may be "curproc",
- * if we're overlaying. "mem" is the loaded memory region returned by
- * "load region". Any open files (other than the standard handles) owned
- * by "p" are closed, and if thread !=0 all memory is released; the caller
- * must explicitly attach the environment and base region. The caller must
- * also put "p" on the appropriate queue (most likely READY_Q).
- */
-
- extern long mint_dos(), mint_bios();
-
- void rts() {} /* dummy termination routine */
-
- PROC *
- exec_region(p, mem, thread)
- PROC *p;
- MEMREGION *mem;
- int thread;
- {
- BASEPAGE *b;
- FILEPTR *f;
- int i;
- MEMREGION *m;
-
- TRACE("exec_region");
-
- b = (BASEPAGE *) mem->loc;
-
- /* set some (undocumented) variables in the basepage */
- b->p_defdrv = p->curdrv;
- for (i = 0; i < 6; i++)
- b->p_devx[i] = i;
-
- p->dta = (DTABUF *)(b->p_dta = &b->p_cmdlin[0]);
- p->base = b;
-
- /* close extra open files */
- for (i = MIN_OPEN; i < MAX_OPEN; i++) {
- if ( (f = p->handle[i]) && (p->fdflags[i] & FD_CLOEXEC) ) {
- do_pclose(p, f);
- p->handle[i] = 0;
- }
- }
-
- /* initialize memory */
- recalc_maxmem(p);
- if (p->maxmem) {
- shrink_region(mem, p->maxmem);
- b->p_hitpa = b->p_lowtpa + mem->len;
- }
-
- p->memflags = b->p_flags;
-
- if (!thread) {
- for (i = 0; i < p->num_reg; i++) {
- m = p->mem[i];
- if (m) {
- m->links--;
- if (m->links <= 0)
- free_region(m);
- }
- }
- if (p->num_reg > NUM_REGIONS) {
- kfree(p->mem); kfree(p->addr);
- p->mem = kmalloc(NUM_REGIONS * SIZEOF(MEMREGION *));
- p->addr = kmalloc(NUM_REGIONS * SIZEOF(virtaddr));
- /* note: the mallocs have succeeded, since we just freed bigger areas */
- assert(p->mem && p->addr);
- p->num_reg = NUM_REGIONS;
- }
- zero((char *)p->mem, (p->num_reg)*SIZEOF(MEMREGION *));
- zero((char *)p->addr, (p->num_reg)*SIZEOF(virtaddr));
- }
-
- /* initialize signals */
- p->sigmask = 0;
- for (i = 0; i < NSIG; i++) {
- if (p->sighandle[i] != SIG_IGN) {
- p->sighandle[i] = SIG_DFL;
- p->sigflags[i] = 0;
- p->sigextra[i] = 0;
- }
- }
-
- /* zero the user registers, and set the FPU in a "clear" state */
- for (i = 0; i < 15; i++)
- p->ctxt[CURRENT].regs[i] = 0;
- p->ctxt[CURRENT].sr = 0;
- p->ctxt[CURRENT].fstate[0] = 0;
-
- /* set PC, stack registers, etc. appropriately */
- p->ctxt[CURRENT].pc = b->p_tbase;
-
- /* The "-0x20" is to make sure that syscall.s won't run past the end of
- * memory when the user makes a system call and doesn't push very many
- * parameters -- syscall always tries to copy the maximum possible number
- * of parms.
- *
- * NOTE: there's a sanity check here in case programs Mshrink a basepage
- * without fixing the p_hitpa field in the basepage; this is to ensure
- * compatibility with older versions of MiNT, which ignore p_hitpa.
- */
- if (valid_address(b->p_hitpa - 0x20))
- p->ctxt[CURRENT].usp = b->p_hitpa - 0x20;
- else
- p->ctxt[CURRENT].usp = mem->loc + mem->len - 0x20;
-
- p->ctxt[CURRENT].ssp = (long)(p->stack + ISTKSIZE);
- p->ctxt[CURRENT].term_vec = (long)rts;
-
- /* set up stack for process */
- *((long *)(p->ctxt[CURRENT].usp + 4)) = (long) b;
-
- /* check for a valid text region. some compilers (e.g. Lattice 3) just throw
- everything into the text region, including data; fork() must be careful
- to save the whole region, then. We assume that if the compiler (or
- assembler, or whatever) goes to the trouble of making separate text, data,
- and bss regions, then the text region is code and isn't modified and
- fork doesn't have to save it.
- */
- if (b->p_tlen != 0 && b->p_blen != 0 && b->p_dlen != 0)
- p->txtsize = b->p_tlen;
- else
- p->txtsize = 0;
-
- /*
- * An ugly hack: dLibs tries to poke around in the parent's address space
- * to find stuff. For now, we'll allow this by faking a pointer into
- * the parent's address space in the place in the basepage where dLibs is
- * expecting it. This ugly hack only works correctly if the Pexec'ing
- * program (i.e. curproc) is in user mode.
- */
- curproc->base->p_usp = curproc->ctxt[SYSCALL].usp - 0x32;
-
- return p;
- }
-
- /*
- * misc. utility routines
- */
-
- /*
- * long memused(p): return total memory allocated to process p
- */
-
- long
- memused(p)
- PROC *p;
- {
- int i;
- long size;
-
- size = 0;
- for (i = 0; i < p->num_reg; i++) {
- if (p->mem[i])
- size += p->mem[i]->len;
- }
- return size;
- }
-
- /*
- * recalculate the maximum memory limit on a process; this limit depends
- * on the max. allocated memory and max. total memory limits set by
- * p_setlimit (see dos.c), and (perhaps) on the size of the program
- * that the process is executing. whenever any of these things
- * change (through p_exec or p_setlimit) this routine must be called
- */
-
- void
- recalc_maxmem(p)
- PROC *p;
- {
- BASEPAGE *b;
- long siz;
-
- b = (BASEPAGE *)p->base;
- if (b)
- siz = b->p_tlen + b->p_dlen + b->p_blen;
- else
- siz = 0;
- p->maxmem = 0;
- if (p->maxdata) {
- p->maxmem = p->maxdata + siz;
- }
-
- if (p->maxcore) {
- if (p->maxmem == 0 || p->maxmem > p->maxcore)
- p->maxmem = p->maxcore;
- }
- if (p->maxmem && p->maxmem < siz)
- p->maxmem = siz;
- }
-
- /*
- * valid_address: checks to see if the indicated address falls within
- * memory attached to the current process
- */
-
- int
- valid_address(addr)
- long addr;
- {
- int i;
- MEMREGION *m;
-
- for (i = 0; i < curproc->num_reg; i++) {
- if ((m = curproc->mem[i]) != 0) {
- if (addr >= m->loc && addr <= m->loc + m->len)
- return 1;
- }
- }
- return 0;
- }
-
- /*
- * some debugging stuff
- */
-
- void
- DUMPMEM(map)
- MMAP map;
- {
- MEMREGION *m;
-
- m = *map;
- ALERT("memory dump: starting at region %lx", m);
- while (m) {
- ALERT("%ld bytes at %lx (%d links); next region %lx", m->len, m->loc,
- m->links, m->next);
- m = m->next;
- }
- }
-
- void
- sanity_check(map)
- MMAP map;
- {
- #ifdef SANITY_CHECK
- MEMREGION *m, *nxt;
- long end;
-
- m = *map;
- while (m) {
- nxt = m->next;
- if (nxt) {
- end = m->loc + m->len;
- if (m->loc < nxt->loc && end > nxt->loc) {
- FATAL("MEMORY CHAIN CORRUPTED");
- }
- else if (end == nxt->loc && ISFREE(m) && ISFREE(nxt)) {
- ALERT("Continguous memory regions not merged!");
- }
- }
- m = nxt;
- }
- #endif
- }
-