/* malloc() called by: * RCCE_shmalloc_init() * RCCE_shmalloc() * RCCE_malloc_init() * RCCE_malloc() * RCCE_flag_alloc() */ void *malloc(size_t nbytes) { irqmask im; struct memblock *prev, *curr, *leftover; /* we don't allocate 0 bytes. */ if (0 == nbytes) { return NULL; } /* round request to size of memblock */ nbytes = (uint)roundmb(nbytes); /* make room for accounting information */ nbytes += sizeof(struct memblock); im = disable(); prev = &memlist; curr = memlist.next; while (curr != NULL) { if (curr->length == nbytes) { /* perfect size */ prev->next = curr->next; memlist.length -= nbytes; break; } else if (curr->length > nbytes) { /* split block into two */ leftover = (struct memblock *)((ulong)curr + nbytes); prev->next = leftover; leftover->next = curr->next; leftover->length = curr->length - nbytes; memlist.length -= nbytes; break; } prev = curr; curr = curr->next; } if (curr == NULL) { restore(im); return NULL; } curr->next = curr; curr->length = nbytes; restore(im); return (void *)(curr + 1); /* +1 to skip accounting info */ }
/*------------------------------------------------------------------------ * freemem -- free a memory block, returning it to memlist *------------------------------------------------------------------------ */ SYSCALL freemem(struct mblock *block, unsigned size) { STATWORD ps; struct mblock *p, *q; unsigned top; if (size==0 || (unsigned)block>(unsigned)maxaddr || ((unsigned)block)<((unsigned) &end)) return(SYSERR); size = (unsigned)roundmb(size); disable(ps); // Iterate through the list until we get to the end or // the next block (p) is greater than the block we are // freeing. Basically this is so we can insert our block // back into the list in sorted order. for( p=memlist.mnext,q= &memlist; p != (struct mblock *) NULL && p < block ; q=p,p=p->mnext ) ; // Check for errors // - Is the block already a part of a free block? // - Does q include part of it? // - Does p include part of it? if (((top=q->mlen+(unsigned)q)>(unsigned)block && q!= &memlist) || (p!=NULL && (size+(unsigned)block) > (unsigned)p )) { restore(ps); return(SYSERR); } // Is the top of the current block equal to the start of the // block that is being freed? If so then just make the current // free block bigger (adjust mlen). if ( q!= &memlist && top == (unsigned)block ) { q->mlen += size; // If not then create a new block and add it to the list. } else { block->mlen = size; block->mnext = p; q->mnext = block; q = block; } // We may now be able to merge this block with the next block // if they are now right next to one another. if ( (unsigned)( q->mlen + (unsigned)q ) == (unsigned)p) { q->mlen += p->mlen; q->mnext = p->mnext; } restore(ps); return(OK); }
/** * @ingroup memory_mgmt * * Allocate stack memory. * * @param nbytes * Number of bytes requested. * * @return * ::SYSERR if @p nbytes was 0 or there is no memory to satisfy the * request; otherwise returns a pointer to the <b>topmost word</b> of the * allocated memory region. The intention is that this is the base of a * stack growing down. Free the stack with stkfree() when done with it. */ void *stkget(uint nbytes) { irqmask im; struct memblock *prev, *next, *fits, *fitsprev; if (0 == nbytes) { return (void *)SYSERR; } /* round to multiple of memblock size */ nbytes = (uint)roundmb(nbytes); im = disable(); prev = &memlist; next = memlist.next; fits = NULL; fitsprev = NULL; /* scan list for highest block that fits */ while (next != NULL) { if (next->length >= nbytes) { fits = next; fitsprev = prev; } prev = next; next = next->next; } if (NULL == fits) { /* no block big enough */ restore(im); return (void *)SYSERR; } if (nbytes == fits->length) { fitsprev->next = fits->next; } else { /* take top portion */ fits->length -= nbytes; fits = (struct memblock *)((ulong)fits + fits->length); } memlist.length -= nbytes; restore(im); return (void *)((ulong)fits + nbytes - sizeof(int)); }
/** * Intializes all XINU data structures and devices. * @return OK if everything is initialized successfully */ local sysinit(void) { int i = 0; pcb *ppcb = NULL; /* process control block pointer */ semblk *psem = NULL; /* semaphore block pointer */ memblk *pmem = NULL; /* memory block pointer */ /* Initialize system variables */ /* Count this NULLPROC as the first process in the system. */ numproc = 1; /* Initialize free memory list */ freelist.next = pmem = (memblk *) roundmb(minheap); freelist.length = (ulong)truncew((ulong)platform.maxaddr - (ulong)minheap); pmem->next = NULL; pmem->length = freelist.length; /* Initialize process table */ for (i = 0; i < NPROC; i++) { proctab[i].state = PRFREE; } /* initialize null process entry */ ppcb = &proctab[NULLPROC]; ppcb->state = PRCURR; strncpy(ppcb->name, "prnull", 7); ppcb->stkbase = (void *)&end; ppcb->stkptr = NULL; ppcb->stklen = (ulong)minheap - (ulong)&end; ppcb->priority = 0; currpid = NULLPROC; /* Initialize semaphores */ for (i = 0; i < NSEM; i++) { psem = &semtab[i]; psem->state = SFREE; psem->count = 0; psem->queue = newqueue(); } /* initialize bounded-waiting mutex subsystems */ mutexInit(); /* initialize process ready list */ readylist = newqueue(); #if RTCLOCK /* initialize real time clock */ clockinit(); #endif return OK; }
void init_heap() { struct memblock *heap; /* round memheap up to memblock alignment */ heap = (struct memblock *)roundmb(memheap); memlist.next = heap; memlist.length = (ulong)_start - (ulong)memheap; heap->next = NULL; heap->length = memlist.length; }
/** * Free a memory block, returning it to free list. * @param pmem pointer to memory block * @param nbytes size of memory block * @return OK on success, SYSERR on failure * */ syscall freemem(void *pmem, ulong nbytes) { ulong im = disable(); // Insert back into free list, and compact with adjacent blocks. if ((0 >= nbytes) || (pmem == NULL)) { restore(im); return SYSERR; } memblk *newblock = (memblk *)pmem; if (((void *)newblock < minheap) || ((void *)newblock > platform.maxaddr) || ((void *)(newblock + nbytes/8) > platform.maxaddr)) { restore(im); return SYSERR; } nbytes = (ulong)roundmb(nbytes); memblk *curr = freelist.next; memblk *prev = NULL; while((curr != NULL) && (curr < newblock)) { prev = curr; curr = curr->next; } newblock->length = nbytes; newblock->next = curr; if (NULL == prev) freelist.next = newblock; else prev->next = newblock; if ((newblock + newblock->length/8) == newblock->next) { newblock->next = curr->next; newblock->length += curr->length; } if (NULL != prev) { if ((prev + prev->length/8) == newblock) { prev->next = newblock->next; prev->length += newblock->length; } } freelist.length += nbytes; restore(im); return OK; }
/*------------------------------------------------------------------------ * getstk - Allocate stack memory, returning highest word address *------------------------------------------------------------------------ */ char *getstk( uint32 nbytes /* Size of memory requested */ ) { intmask mask; /* Saved interrupt mask */ struct memblk *prev, *curr; /* Walk through memory list */ struct memblk *fits, *fitsprev; /* Record block that fits */ uint32 read = 0; /* jteague6 - for best-fit finding */ mask = disable(); if (nbytes == 0) { restore(mask); return (char *)SYSERR; } nbytes = (uint32) roundmb(nbytes); /* Use mblock multiples */ prev = &memlist; curr = memlist.mnext; fits = NULL; fitsprev = NULL; /* Just to avoid a compiler warning */ while (curr != NULL) { /* Scan entire list */ /* jteague6 - for best fit, we want to not only make sure the block * fitst, but we want to also make sure it is the first fitting block * that has been found, or that it is smaller than the current * fitting block. */ if (curr->mlength >= nbytes && ( read == 0 || curr->mlength < fits->mlength )) { /* Record block address */ fits = curr; /* when request fits */ fitsprev = prev; read = 1; /* To prevent erroneous positives */ } prev = curr; curr = curr->mnext; } if (fits == NULL) { /* No block was found */ restore(mask); return (char *)SYSERR; } if (nbytes == fits->mlength) { /* Block is exact match */ fitsprev->mnext = fits->mnext; } else { /* Remove top section */ fits->mlength -= nbytes; fits = (struct memblk *)((uint32)fits + fits->mlength); } memlist.mlength -= nbytes; restore(mask); return (char *)((uint32) fits + nbytes - 2 * sizeof(uint32)); }
void nulluser(void) { sysinit(); kprintf("\n\r%s\n\n\r", VERSION); /* Output Xinu memory layout */ kprintf("%10d bytes physical memory.\n", (uint32)maxheap - (uint32)0); kprintf(" [0x%08X to 0x%08X]\r\n", (uint32)0, (uint32)maxheap - 1); kprintf("%10d bytes of Xinu code.\n", (uint32)&etext - (uint32)0); kprintf(" [0x%08X to 0x%08X]\n", (uint32)0, (uint32)&etext - 1); kprintf("%10d bytes of data.\n", (uint32)&end - (uint32)&etext); kprintf(" [0x%08X to 0x%08X]\n", (uint32)&etext, (uint32)&end - 1); if ( (char *)minheap < HOLESTART) { kprintf("%10d bytes of heap space below 640K.\n", (uint32)HOLESTART - (uint32)roundmb(minheap)); } if ( (char *)maxheap > HOLEEND ) { kprintf("%10d bytes of heap space above 1M.\n", (uint32)maxheap - (uint32)HOLEEND); kprintf(" [0x%08X to 0x%08X]\n", (uint32)HOLEEND, (uint32)truncmb(maxheap) - 1); } /* Enable interrupts */ enable(); /* Start the network */ resume(create((void *)netin, NETSTK, NETPRIO, "netin", 0)); /* Create a process to execute function main() */ resume ( create((void *)main, INITSTK, INITPRIO, "Main process", 2, 0, NULL)); /* Become the Null process (i.e., guarantee that the CPU has */ /* something to run when no other process is ready to execute) */ while (TRUE) { ; /* do nothing */ } }
/** * Allocate heap storage, returning lowest word address * @param nbytes bytes requested * @return pointer to region on success, SYSERR on failure */ void *memget(uint nbytes) { register struct memblock *prev, *curr, *leftover; irqmask im; if (0 == nbytes) { return (void *)SYSERR; } /* round to multiple of memblock size */ nbytes = (ulong)roundmb(nbytes); im = disable(); prev = &memlist; curr = memlist.next; while (curr != NULL) { if (curr->length == nbytes) { prev->next = curr->next; memlist.length -= nbytes; restore(im); return (void *)(curr); } else if (curr->length > nbytes) { /* split block into two */ leftover = (struct memblock *)((ulong)curr + nbytes); prev->next = leftover; leftover->next = curr->next; leftover->length = curr->length - nbytes; memlist.length -= nbytes; restore(im); return (void *)(curr); } prev = curr; curr = curr->next; } restore(im); return (void *)SYSERR; }
/*------------------------------------------------------------------------ * getstk - Allocate stack memory, returning highest word address *------------------------------------------------------------------------ */ char *newgetstk( uint32 nbytes /* Size of memory requested */ ) { intmask mask; /* Saved interrupt mask */ struct memblk *prev, *curr; /* Walk through memory list */ struct memblk *fits, *fitsprev; /* Record block that fits */ mask = disable(); if (nbytes == 0) { restore(mask); return (char *)SYSERR; } nbytes = (uint32) roundmb(nbytes); /* Use mblock multiples */ prev = &memlist; curr = memlist.mnext; fits = NULL; fitsprev = NULL; /* Just to avoid a compiler warning */ while (curr != NULL) { /* Scan entire list */ if (curr->mlength >= nbytes) { /* Record block address */ fits = curr; /* when request fits */ fitsprev = prev; break; // } prev = curr; curr = curr->mnext; } if (fits == NULL) { /* No block was found */ restore(mask); return (char *)SYSERR; } if (nbytes == fits->mlength) { // Block is exact match fitsprev->mnext = fits->mnext; } else { //Remove top section fits->mlength -= nbytes; fits = (struct memblk *)((uint32)fits + fits->mlength); } memlist.mlength -= nbytes; restore(mask); return (char *)((uint32) fits + nbytes - sizeof(uint32)); }
/*------------------------------------------------------------------------ * getmem - Allocate heap storage, returning lowest word address *------------------------------------------------------------------------ */ char *getmem( uint32 nbytes /* Size of memory requested */ ) { intmask mask; /* Saved interrupt mask */ struct memblk *prev, *curr, *leftover; mask = disable(); if (nbytes == 0) { restore(mask); return (char *)SYSERR; } nbytes = (uint32) roundmb(nbytes); /* Use memblk multiples */ prev = &memlist; curr = memlist.mnext; while (curr != NULL) { /* Search free list */ if (curr->mlength == nbytes) { /* Block is exact match */ prev->mnext = curr->mnext; memlist.mlength -= nbytes; OS_sendevent(getpid(), PROCESS_GETMEM_EVENT); restore(mask); return (char *)(curr); } else if (curr->mlength > nbytes) { /* Split big block */ leftover = (struct memblk *)((uint32) curr + nbytes); prev->mnext = leftover; leftover->mnext = curr->mnext; leftover->mlength = curr->mlength - nbytes; memlist.mlength -= nbytes; OS_sendevent(getpid(), PROCESS_GETMEM_EVENT); restore(mask); return (char *)(curr); } else { /* Move to next block */ prev = curr; curr = curr->mnext; } } restore(mask); return (char *)SYSERR; }
/*------------------------------------------------------------------------ * freemem -- free a memory block, returning it to memlist *------------------------------------------------------------------------ */ SYSCALL freemem(struct mblock *block, unsigned size) { int start; if(activated == 1) start = ctr1000; STATWORD ps; struct mblock *p, *q; unsigned top; if (size==0 || (unsigned)block>(unsigned)maxaddr || ((unsigned)block)<((unsigned) &end)) return(SYSERR); size = (unsigned)roundmb(size); disable(ps); for( p=memlist.mnext,q= &memlist; p != (struct mblock *) NULL && p < block ; q=p,p=p->mnext ) ; if (((top=q->mlen+(unsigned)q)>(unsigned)block && q!= &memlist) || (p!=NULL && (size+(unsigned)block) > (unsigned)p )) { restore(ps); return(SYSERR); } if ( q!= &memlist && top == (unsigned)block ) q->mlen += size; else { block->mlen = size; block->mnext = p; q->mnext = block; q = block; } if ( (unsigned)( q->mlen + (unsigned)q ) == (unsigned)p) { q->mlen += p->mlen; q->mnext = p->mnext; } restore(ps); if(activated == 1) { Info[currpid][FREEMEM].freq++; Info[currpid][FREEMEM].time += (ctr1000 - start); } return(OK); }
/*------------------------------------------------------------------------ * getstk - Allocate stack memory, returning highest word address *------------------------------------------------------------------------ */ char *getstk( uint32 nbytes /* size of memory requested */ ) { intmask mask; /* saved interrupt mask */ struct memblk *prev, *curr; /* walk through memory list */ struct memblk *fits, *fitsprev; /* record block that fits */ mask = disable(); if (nbytes == 0) { restore(mask); return (char *)SYSERR; } nbytes = (uint32) roundmb(nbytes); /* use mblock multiples */ prev = &memlist; curr = memlist.mnext; fits = NULL; while (curr != NULL) { /* scan entire list */ if (curr->mlength >= nbytes) { /* record block address */ fits = curr; /* when request fits */ fitsprev = prev; } prev = curr; curr = curr->mnext; } if (fits == NULL) { /* no block was found */ restore(mask); return (char *)SYSERR; } if (nbytes == fits->mlength) { /* block is exact match */ fitsprev->mnext = fits->mnext; } else { /* remove top section */ fits->mlength -= nbytes; fits = (struct memblk *)((uint32)fits + fits->mlength); } memlist.mlength -= nbytes; restore(mask); return (char *)((uint32) fits + nbytes - sizeof(uint32)); }
/*------------------------------------------------------------------------ * freemem -- free a memory block, returning it to memlist *------------------------------------------------------------------------ */ SYSCALL freemem(void *block0, unsigned size) { struct mblock *block = (struct mblock *)block0; STATWORD ps; struct mblock *p, *q; unsigned top; if (size==0 || (unsigned)block>(unsigned)maxaddr || ((unsigned)block)<((unsigned) &end)) return(SYSERR); size = (unsigned)roundmb(size); disable(ps); for( p=memlist.mnext,q= &memlist; p != (struct mblock *) NULL && p < block ; q=p,p=p->mnext ) ; if ((top=q->mlen+(unsigned)q)>(unsigned)block && q!= &memlist || p!=NULL && (size+(unsigned)block) > (unsigned)p ) { restore(ps); return(SYSERR); } if ( q!= &memlist && top == (unsigned)block ) q->mlen += size; else { block->mlen = size; block->mnext = p; q->mnext = block; q = block; } if ( (unsigned)( q->mlen + (unsigned)q ) == (unsigned)p) { q->mlen += p->mlen; q->mnext = p->mnext; } restore(ps); return(OK); }
////////////////////////////////////////////////////////////////////////// // vheap_test ////////////////////////////////////////////////////////////////////////// void vheaptask() { int i,x; char * str; char * pass = "******"; char * fail = "FAIL"; // Values for proc structure char pstate = 'Z'; int pprio = 100; int pesp = 45; // Values for bs_map_t structure int pid = 99; int npages = 32; int vpno = 4200; // Values for frame_t structure int status = 75; int type = 1; int refcnt = 7200; // Create a proc structure.. populate some print it out kprintf("Allocating pentry structure\n\n"); struct pentry * pptr; pptr = vgetmem(sizeof(struct pentry)); if (pptr == SYSERR) { kprintf("Could not allocate mem for pentry"); return; } kprintf("Mem for pentry structure: 0x%08x\n", pptr); pptr->pstate = pstate; pptr->pprio = pprio; pptr->pesp = pesp; str = (pptr->pstate == pstate) ? pass : fail; kprintf("task1: UT1 pptr->pstate: \t%s\n", str); str = (pptr->pprio == pprio) ? pass : fail; kprintf("task1: UT2 pptr->pprio: \t%s\n", str); str = (pptr->pesp == pesp) ? pass : fail; kprintf("task1: UT3 pptr->pesp: \t%s\n", str); kprintf("\n\n"); // Create a bs_map_t structure.. populate some print it out kprintf("Allocating bs_map_t structure\n\n"); bs_map_t * bsmptr; bsmptr = vgetmem(sizeof(bs_map_t)); if (bsmptr == SYSERR) { kprintf("Could not allocate mem for bs_map_t"); return; } kprintf("Mem for bs_map_t structure: 0x%08x\n", bsmptr); bsmptr->pid = pid; bsmptr->npages = npages; bsmptr->vpno = vpno; str = (bsmptr->pid == pid) ? pass : fail; kprintf("task1: UT4 bsmptr->pid: \t%s\n", str); str = (bsmptr->npages == npages) ? pass : fail; kprintf("task1: UT5 bsmptr->npages: \t%s\n", str); str = (bsmptr->pid == pid) ? pass : fail; kprintf("task1: UT6 bsmptr->vpno: \t%s\n", str); kprintf("\n\n"); // Free the proc structure kprintf("Freeing pentry structure\n\n"); vfreemem((struct mblock *)pptr, sizeof(struct pentry)); kprintf("\n\n"); // Create a frame_t structure kprintf("Allocating frame_t structure\n\n"); frame_t * frame; frame = vgetmem(sizeof(frame_t)); if (frame == SYSERR) { kprintf("Could not allocate mem for frame_t"); return; } kprintf("Mem for frame_t structure: 0x%08x\n", frame); frame->status = status; frame->type = type; frame->refcnt = refcnt; str = (frame->status == status) ? pass : fail; kprintf("task1: UT7 frame->status: \t%s\n", str); str = (frame->type == type) ? pass : fail; kprintf("task1: UT8 frame->type: \t%s\n", str); str = (frame->refcnt == refcnt) ? pass : fail; kprintf("task1: UT9 frame->refcnt: \t%s\n", str); kprintf("\n\n"); // Test the bs_map_t structure str = (bsmptr->pid == pid) ? pass : fail; kprintf("task1: UT10 bsmptr->pid: \t%s\n", str); str = (bsmptr->npages == npages) ? pass : fail; kprintf("task1: UT11 bsmptr->npages: \t%s\n", str); str = (bsmptr->pid == pid) ? pass : fail; kprintf("task1: UT12 bsmptr->vpno: \t%s\n", str); kprintf("\n\n"); // Create a proc structure.. populate some print it out kprintf("Allocating pentry structure\n\n"); struct pentry * pptr2; pptr2 = vgetmem(sizeof(struct pentry)); if (pptr2 == SYSERR) { kprintf("Could not allocate mem for pentry"); return; } kprintf("Mem for pentry structure: 0x%08x\n", pptr2); pptr2->pstate = pstate; pptr2->pprio = pprio; pptr2->pesp = pesp; str = (pptr2->pstate == pstate) ? pass : fail; kprintf("task1: UT13 pptr2->pstate: \t%s\n", str); str = (pptr2->pprio == pprio) ? pass : fail; kprintf("task1: UT14 pptr2->pprio: \t%s\n", str); str = (pptr2->pesp == pesp) ? pass : fail; kprintf("task1: UT15 pptr2->pesp: \t%s\n", str); kprintf("\n\n"); // Free the bsmptr structure kprintf("Freeing bsmptr structure\n\n"); vfreemem((struct mblock *)pptr, sizeof(bs_map_t)); kprintf("\n\n"); // Create a proc structure.. populate some print it out kprintf("Allocating pentry structure\n\n"); struct pentry * pptr3; pptr3 = vgetmem(sizeof(struct pentry)); if (pptr3 == SYSERR) { kprintf("Could not allocate mem for pentry"); return; } kprintf("Mem for pentry structure: 0x%08x\n", pptr3); pptr3->pstate = pstate; pptr3->pprio = pprio; pptr3->pesp = pesp; str = (pptr3->pstate == pstate) ? pass : fail; kprintf("task1: UT16 pptr3->pstate: \t%s\n", str); str = (pptr3->pprio == pprio) ? pass : fail; kprintf("task1: UT17 pptr3->pprio: \t%s\n", str); str = (pptr3->pesp == pesp) ? pass : fail; kprintf("task1: UT18 pptr3->pesp: \t%s\n", str); kprintf("\n\n"); // Final Tests.. So here is what we had: // 1. pptr = vgetmem(sizeof(struct pentry *) // -> Gets the first address (4096*NBPG) // 2. bsmptr = vgetmem(sizeof(bs_map_t) // -> Gets addr immediately following // 3. vfreemem(pptr) // 4. frame = vgetmem(sizeof(frame_t) // -> Since smaller -> Gets slot that pptr occupied // 5. pptr2 = vgetmem(sizeof(struct pentry *) // -> Gets address after frame // 6. vfreemem(bsmptr) // 5. pptr3 = vgetmem(sizeof(struct pentry *) // -> Since larger than bsmptr cannot occupy that space // -> Gets address at end. // str = (pptr == 4096*NBPG) ? pass : fail; kprintf("task1: UT19 pptr mem: \t%s\n", str); x = 4096*NBPG; x += (int)roundmb(sizeof(struct pentry)); x += (int)roundmb(sizeof(bs_map_t)); str = (pptr2 == x) ? pass : fail; kprintf("task1: UT20 pptr2 mem: \t%s\n", str); x = 4096*NBPG; x += 2*(int)roundmb(sizeof(struct pentry)); x += (int)roundmb(sizeof(bs_map_t)); str = (pptr3 == x) ? pass : fail; kprintf("task1: UT21 pptr3 mem: \t%s\n", str); x = 4096*NBPG + sizeof(struct pentry); str = (bsmptr == x) ? pass : fail; kprintf("task1: UT22 bsmptr mem: \t%s\n", str); str = (frame == 4096*NBPG) ? pass : fail; kprintf("task1: UT23 frame mem: \t%s\n", str); }
/*------------------------------------------------------------------------ * freemem - Free a memory block, returning the block to the free list *------------------------------------------------------------------------ */ syscall freestk( char *blkaddr, /* Pointer to memory block */ uint32 nbytes /* Size of block in bytes */ ) { intmask mask; /* Saved interrupt mask */ struct memblk *next, *prev, *block; uint32 top; mask = disable(); /* jteague6 - modify arguments so they are set to the same values they * would be if the macro was still in use. */ blkaddr = (char *)((uint32)blkaddr - ((uint32)roundmb(nbytes)) + (uint32)sizeof(uint32)); nbytes = (uint32)roundmb(nbytes); /* jteague6 - from here, we search from the front to free. This is slow, * but it allows a massive amount of code reuse, and frankly I had issues * getting it to work searching from the rear. */ if ((nbytes == 0) || ((uint32) blkaddr < (uint32) minheap) || ((uint32) blkaddr > (uint32) maxheap)) { restore(mask); return SYSERR; } nbytes = (uint32) roundmb(nbytes); /* Use memblk multiples */ block = (struct memblk *)blkaddr; prev = &memlist; /* Walk along free list */ next = memlist.mnext; while ((next != NULL) && (next < block)) { prev = next; next = next->mnext; } if (prev == &memlist) { /* Compute top of previous block*/ top = (uint32) NULL; } else { top = (uint32) prev + prev->mlength; } /* Ensure new block does not overlap previous or next blocks */ if (((prev != &memlist) && (uint32) block < top) || ((next != NULL) && (uint32) block+nbytes>(uint32)next)) { restore(mask); return SYSERR; } memlist.mlength += nbytes; /* Either coalesce with previous block or add to free list */ if (top == (uint32) block) { /* Coalesce with previous block */ prev->mlength += nbytes; block = prev; } else { /* Link into list as new node */ block->mnext = next; block->mlength = nbytes; prev->mnext = block; /* jteague6 - support for rear list searching - modify mprev * links and reset memtail->mprev if needed */ if( prev == &memlist ) { block->mprev = NULL; } else { block->mprev = prev; } if( block->mnext == NULL ) { memtail.mprev = block; } else { block->mnext->mprev = block; } } /* Coalesce with next block if adjacent */ if (((uint32) block + block->mlength) == (uint32) next) { block->mlength += next->mlength; block->mnext = next->mnext; /* jteague6 - support for rear list searching - modify mprev * links and reset memtail->mprev if needed */ if( block->mnext == NULL ) { memtail.mprev = block; } else { block->mnext->mprev = block; } } restore(mask); return OK; }
/*------------------------------------------------------------------------ * sysinit -- initialize all Xinu data structeres and devices *------------------------------------------------------------------------ */ LOCAL sysinit() { static long currsp; int i,j, avail; struct pentry *pptr; struct sentry *sptr; struct mblock *mptr; SYSCALL pfintr(); /*********************/ set_evec(14, pfintr); pptr = &proctab[NULLPROC]; /* initialize null process entry */ /*********************/ numproc = 0; /* initialize system variables */ nextproc = NPROC-1; nextsem = NSEM-1; nextqueue = NPROC; /* q[0..NPROC-1] are processes */ /* initialize free memory list */ /* PC version has to pre-allocate 640K-1024K "hole" */ if (maxaddr+1 > HOLESTART) { memlist.mnext = mptr = (struct mblock *) roundmb(&end); mptr->mnext = (struct mblock *)HOLEEND; mptr->mlen = (int) truncew(((unsigned) HOLESTART - (unsigned)&end)); mptr->mlen -= 4; mptr = (struct mblock *) HOLEEND; mptr->mnext = 0; mptr->mlen = (int) truncew((unsigned)maxaddr - HOLEEND - NULLSTK); /* mptr->mlen = (int) truncew((unsigned)maxaddr - (4096 - 1024 ) * 4096 - HOLEEND - NULLSTK); */ } else { /* initialize free memory list */ memlist.mnext = mptr = (struct mblock *) roundmb(&end); mptr->mnext = 0; mptr->mlen = (int) truncew((unsigned)maxaddr - (int)&end - NULLSTK); } for (i=0 ; i<NPROC ; i++) /* initialize process table */ proctab[i].pstate = PRFREE; #ifdef MEMMARK _mkinit(); /* initialize memory marking */ #endif #ifdef RTCLOCK clkinit(); /* initialize r.t.clock */ #endif mon_init(); /* init monitor */ #ifdef NDEVS for (i=0 ; i<NDEVS ; i++ ) { init_dev(i); } #endif pptr = &proctab[NULLPROC]; /* initialize null process entry */ pptr->pstate = PRCURR; for (j=0; j<7; j++) pptr->pname[j] = "prnull"[j]; pptr->plimit = (WORD)(maxaddr + 1) - NULLSTK; pptr->pbase = (WORD) maxaddr - 3; /* pptr->plimit = (WORD)(maxaddr + 1) - NULLSTK - (4096 - 1024 )*4096; pptr->pbase = (WORD) maxaddr - 3 - (4096-1024)*4096; */ pptr->pesp = pptr->pbase-4; /* for stkchk; rewritten before used */ *( (int *)pptr->pbase ) = MAGIC; pptr->paddr = (WORD) nulluser; pptr->pargs = 0; pptr->pprio = 0; currpid = NULLPROC; for (i=0 ; i<NSEM ; i++) { /* initialize semaphores */ (sptr = &semaph[i])->sstate = SFREE; sptr->sqtail = 1 + (sptr->sqhead = newqueue()); } rdytail = 1 + (rdyhead=newqueue());/* initialize ready list */ init_bsm(); init_frm(); kprintf("initialize page tables for null process\n"); init_glb_pgs(glb_pg_tbl_frm_mapping); // init pg dir for proc 0 frame_t *pg_dir = get_free_frame(); init_pg_dir(pg_dir, NULLPROC); pptr->pdbr = pg_dir->frm_num; pptr->pd = pg_dir; return(OK); }
/** * Intializes all Xinu data structures and devices. * @return OK if everything is initialized successfully */ static int sysinit(void) { int i; void *userheap; /* pointer to user memory heap */ struct thrent *thrptr; /* thread control block pointer */ device *devptr; /* device entry pointer */ struct sement *semptr; /* semaphore entry pointer */ struct memblock *pmblock; /* memory block pointer */ struct bfpentry *bfpptr; /* Initialize system variables */ /* Count this NULLTHREAD as the first thread in the system. */ thrcount = 1; kprintf("variable i in this function is at 0x%x\r\n", &i); kprintf("this function sysinit is at 0x%x\r\n", &sysinit); kprintf("_start is at 0x%x\r\n", _start); kprintf("_end is at (the end) at 0x%x\r\n", &_end); kprintf("readylist is at 0x%x\r\n", &readylist); kprintf("kputc is at 0x%x\r\n", &kputc); kprintf("NTHREAD is %d\r\n", NTHREAD); kprintf("memheap is 0x%x\r\n", memheap); /* Initialize free memory list */ memheap = roundmb(memheap); platform.maxaddr = truncmb(platform.maxaddr); kprintf("platform.maxaddr is 0x%x\r\n", platform.maxaddr); memlist.next = pmblock = (struct memblock *)memheap; memlist.length = (uint)(platform.maxaddr - memheap); pmblock->next = NULL; pmblock->length = (uint)(platform.maxaddr - memheap); /* Initialize thread table */ for (i = 0; i < NTHREAD; i++) { thrtab[i].state = THRFREE; } kprintf("thrtab is at 0x%x, size %d\r\n", thrtab, sizeof(thrtab)); /* initialize null thread entry */ thrptr = &thrtab[NULLTHREAD]; thrptr->state = THRCURR; thrptr->prio = 0; strncpy(thrptr->name, "prnull", 7); thrptr->stkbase = (void *)&_end; thrptr->stklen = (ulong)memheap - (ulong)&_end; thrptr->stkptr = 0; thrptr->memlist.next = NULL; thrptr->memlist.length = 0; thrcurrent = NULLTHREAD; kprintf("&_end is 0x%x\n", &_end); /* Initialize semaphores */ for (i = 0; i < NSEM; i++) { semptr = &semtab[i]; semptr->state = SFREE; semptr->count = 0; semptr->queue = queinit(); } kprintf("NPOOL is %d\n", NPOOL); /* Initialize buffer pools */ for (i = 0; i < NPOOL; i++) { bfpptr = &bfptab[i]; bfpptr->state = BFPFREE; } kprintf("calling queinit() for readylist\r\n"); /* initialize thread ready list */ readylist = queinit(); #if SB_BUS backplaneInit(NULL); #endif /* SB_BUS */ #if RTCLOCK /* initialize real time clock */ kprintf("Clock being initialized.\r\n" ); clkinit(); #endif /* RTCLOCK */ #ifdef UHEAP_SIZE /* Initialize user memory manager */ userheap = stkget(UHEAP_SIZE); if (SYSERR != (int)userheap) { userheap = (void *)((uint)userheap - UHEAP_SIZE + sizeof(int)); memRegionInit(userheap, UHEAP_SIZE); /* initialize memory protection */ safeInit(); /* initialize kernel page mappings */ safeKmapInit(); } #else userheap = NULL; #endif /* UHEAP_SIZE */ #if USE_TLB /* initialize TLB */ tlbInit(); /* register system call handler */ exceptionVector[EXC_SYS] = syscall_entry; #endif /* USE_TLB */ #if NMAILBOX /* intialize mailboxes */ mailboxInit(); #endif #if NDEVS for (i = 0; i < NDEVS; i++) { if (!isbaddev(i)) { devptr = (device *)&devtab[i]; (devptr->init) (devptr); } } #endif #if 0 #if NVRAM nvramInit(); #endif kprintf("SO MUCH MORE NOT done with sysinit()\r\n"); #if NNETIF netInit(); #endif kprintf("NOT done with sysinit()\r\n"); #if GPIO gpioLEDOn(GPIO_LED_CISCOWHT); #endif #endif kprintf("done with sysinit()\r\n"); return OK; }
static void sysinit(void) { int32 i; struct procent *prptr; /* ptr to process table entry */ struct dentry *devptr; /* ptr to device table entry */ struct sentry *semptr; /* prr to semaphore table entry */ struct memblk *memptr; /* ptr to memory block */ /* Initialize the interrupt vectors */ initevec(); /* Initialize system variables */ /* Count the Null process as the first process in the system */ prcount = 1; /* Scheduling is not currently blocked */ Defer.ndefers = 0; /* Initialize the free memory list */ /* Note: PC version has to pre-allocate 640K-1024K "hole" */ maxheap = (void *)MAXADDR; minheap = &end; memptr = memlist.mnext = (struct memblk *)roundmb(minheap); if ((char *)(maxheap+1) > HOLESTART) { /* create two blocks that straddle the hole */ memptr->mnext = (struct memblk *)HOLEEND; memptr->mlength = (int) truncmb((unsigned) HOLESTART - (unsigned)&end - 4); memptr = (struct memblk *) HOLEEND; memptr->mnext = (struct memblk *) NULL; memptr->mlength = (int) truncmb( (uint32)maxheap - (uint32)HOLEEND - NULLSTK); } else { /* initialize free memory list to one block */ memlist.mnext = memptr = (struct memblk *) roundmb(&end); memptr->mnext = (struct memblk *) NULL; memptr->mlength = (uint32) truncmb((uint32)maxheap - (uint32)&end - NULLSTK); } /* Initialize process table entries free */ for (i = 0; i < NPROC; i++) { prptr = &proctab[i]; prptr->prstate = PR_FREE; prptr->prname[0] = NULLCH; prptr->prstkbase = NULL; prptr->prprio = 0; } /* Initialize the Null process entry */ prptr = &proctab[NULLPROC]; prptr->prstate = PR_CURR; prptr->prprio = 0; strncpy(prptr->prname, "prnull", 7); prptr->prstkbase = getstk(NULLSTK); prptr->prstklen = NULLSTK; prptr->prstkptr = 0; currpid = NULLPROC; /* Initialize semaphores */ for (i = 0; i < NSEM; i++) { semptr = &semtab[i]; semptr->sstate = S_FREE; semptr->scount = 0; semptr->squeue = newqueue(); } /* Initialize buffer pools */ bufinit(); /* Create a ready list for processes */ readylist = newqueue(); /* Initialize the PCI bus */ pci_init(); /* Initialize the real time clock */ clkinit(); for (i = 0; i < NDEVS; i++) { if (! isbaddev(i)) { devptr = (struct dentry *) &devtab[i]; (devptr->dvinit) (devptr); } } return; }
SYSCALL create(int (*procaddr)(), int ssize, int priority, char *name, int nargs, ...) { STATWORD ps; int pid; /* stores new process id */ struct pentry *pptr; /* pointer to proc. table entry */ int i; unsigned char *saddr; /* stack address */ int INITRET(); va_list ap; disable(ps); ssize = (int) roundmb(ssize); if ( (saddr = (unsigned char *)getstk(ssize)) == (unsigned char *)SYSERR ) { restore(ps); return (SYSERR); } if ( ssize < MINSTK || (pid=newpid()) == SYSERR || priority < 1 ) { freestk((unsigned)saddr, (unsigned)ssize); restore(ps); return(SYSERR); } numproc++; pptr = &proctab[pid]; /* stderr set to &kprint_out (see kprintf.c and initialize.c) */ pptr->fildes[0] = fdopen(CONSOLE, "r"); /* stdin set to console */ pptr->fildes[1] = fdopen(CONSOLE, "w"); /* stdout set to console */ pptr->fildes[2] = &kprint_out; /* stderr set to &kprint_out */ for (i=2; i < _NFILE; i++) /* others set to unused */ pptr->fildes[i] = (FILE *)FDFREE; pptr->pstate = PRSUSP; for (i=0 ; i<PNMLEN && (int)(pptr->pname[i]=name[i])!=0 ; i++) ; pptr->pprio = priority; pptr->pbase = saddr; pptr->pstklen = ssize; pptr->psem = 0; pptr->phasmsg = FALSE; pptr->plimit = pptr->pbase - ssize + sizeof (WORD); *saddr-- = (char)MAGIC; /* Bottom of stack */ pptr->pargs = nargs; for (i=0 ; i<PNREGS ; i++) pptr->pregs[i] = INITREG; pptr->paddr = (int *)procaddr; pptr->pregs[SPC_L] = lobyte((unsigned) procaddr); pptr->pregs[SPC_H] = hibyte((unsigned) procaddr); pptr->pregs[SSREG] = INITPS; pptr->pnxtkin = BADPID; pptr->pdevs[0] = pptr->pdevs[1] = BADDEV; va_start(ap,nargs); for (i=0 ; i < nargs; i++) { pptr->parg[i] = va_arg(ap, unsigned int); } va_end(ap); pptr->parg[nargs] = 0; /* machine/compiler dependent pass arguments to created process */ pptr->pregs[24] = lobyte((unsigned)pptr->pargs); /*r24*/ pptr->pregs[25] = hibyte((unsigned)pptr->pargs); pptr->pregs[22] = lobyte((unsigned)&pptr->parg[0]); /*r22*/ pptr->pregs[23] = hibyte((unsigned)&pptr->parg[0]); *saddr-- = lobyte((unsigned)INITRET); /* push on initial return address*/ *saddr-- = hibyte((unsigned)INITRET); // *saddr-- = 0; /* 256Kb memory device */ /*TODO make conditional*/ *saddr-- = lobyte((unsigned)procaddr); /* push on procedure address */ *saddr-- = hibyte((unsigned)procaddr); // *saddr-- = 0; /* 256Kb memory device */ /*TODO make conditional*/ pptr->pregs[SSP_L] = lobyte((unsigned) saddr); pptr->pregs[SSP_H] = hibyte((unsigned) saddr); restore(ps); return(pid); }
/*------------------------------------------------------------------------ * meminit - initialize memory bounds and the free memory list *------------------------------------------------------------------------ */ void meminit(void) { struct memblk *memptr; /* Ptr to memory block */ struct mbmregion *mmap_addr; /* Ptr to mmap entries */ struct mbmregion *mmap_addrend; /* Ptr to end of mmap region */ struct memblk *next_memptr; /* Ptr to next memory block */ uint32 next_block_length; /* Size of next memory block */ mmap_addr = (struct mbmregion*)NULL; mmap_addrend = (struct mbmregion*)NULL; /* Initialize the free list */ memptr = &memlist; memptr->mnext = (struct memblk *)NULL; memptr->mlength = 0; /* Initialize the memory counters */ /* Heap starts at the end of Xinu image */ minheap = (void*)&end; maxheap = minheap; /* Check if Xinu was loaded using the multiboot specification */ /* and a memory map was included */ if(bootsign != MULTIBOOT_SIGNATURE) { panic("could not find multiboot signature"); } if(!(bootinfo->flags & MULTIBOOT_BOOTINFO_MMAP)) { panic("no mmap found in boot info"); } /* Get base address of mmap region (passed by GRUB) */ mmap_addr = (struct mbmregion*)bootinfo->mmap_addr; /* Calculate address that follows the mmap block */ mmap_addrend = (struct mbmregion*)((uint8*)mmap_addr + bootinfo->mmap_length); /* Read mmap blocks and initialize the Xinu free memory list */ while(mmap_addr < mmap_addrend) { /* If block is not usable, skip to next block */ if(mmap_addr->type != MULTIBOOT_MMAP_TYPE_USABLE) { mmap_addr = (struct mbmregion*)((uint8*)mmap_addr + mmap_addr->size + 4); continue; } if((uint32)maxheap < ((uint32)mmap_addr->base_addr + (uint32)mmap_addr->length)) { maxheap = (void*)((uint32)mmap_addr->base_addr + (uint32)mmap_addr->length); } /* Ignore memory blocks within the Xinu image */ if((mmap_addr->base_addr + mmap_addr->length) < ((uint32)minheap)) { mmap_addr = (struct mbmregion*)((uint8*)mmap_addr + mmap_addr->size + 4); continue; } /* The block is usable, so add it to Xinu's memory list */ /* This block straddles the end of the Xinu image */ if((mmap_addr->base_addr <= (uint32)minheap) && ((mmap_addr->base_addr + mmap_addr->length) > (uint32)minheap)) { /* This is the first free block, base address is the minheap */ next_memptr = (struct memblk *)roundmb(minheap); /* Subtract Xinu image from length of block */ next_block_length = (uint32)truncmb(mmap_addr->base_addr + mmap_addr->length - (uint32)minheap); } else { /* Handle a free memory block other than the first one */ next_memptr = (struct memblk *)roundmb(mmap_addr->base_addr); /* Initialize the length of the block */ next_block_length = (uint32)truncmb(mmap_addr->length); } /* Add then new block to the free list */ memptr->mnext = next_memptr; memptr = memptr->mnext; memptr->mlength = next_block_length; memlist.mlength += next_block_length; /* Move to the next mmap block */ mmap_addr = (struct mbmregion*)((uint8*)mmap_addr + mmap_addr->size + 4); } /* End of all mmap blocks, and so end of Xinu free list */ if(memptr) { memptr->mnext = (struct memblk *)NULL; } }
/** * Intializes all Xinu data structures and devices. * @return OK if everything is initialized successfully */ static int sysinit(void) { int i; struct thrent *thrptr; /* thread control block pointer */ struct memblock *pmblock; /* memory block pointer */ /* Initialize system variables */ /* Count this NULLTHREAD as the first thread in the system. */ thrcount = 1; /* Initialize free memory list */ memheap = roundmb(memheap); platform.maxaddr = truncmb(platform.maxaddr); memlist.next = pmblock = (struct memblock *)memheap; memlist.length = (uint)(platform.maxaddr - memheap); pmblock->next = NULL; pmblock->length = (uint)(platform.maxaddr - memheap); /* Initialize thread table */ for (i = 0; i < NTHREAD; i++) { thrtab[i].state = THRFREE; } /* initialize null thread entry */ thrptr = &thrtab[NULLTHREAD]; thrptr->state = THRCURR; thrptr->prio = 0; strlcpy(thrptr->name, "prnull", TNMLEN); thrptr->stkbase = (void *)&_end; thrptr->stklen = (ulong)memheap - (ulong)&_end; thrptr->stkptr = 0; thrptr->memlist.next = NULL; thrptr->memlist.length = 0; thrcurrent = NULLTHREAD; /* Initialize semaphores */ for (i = 0; i < NSEM; i++) { semtab[i].state = SFREE; semtab[i].queue = queinit(); } /* Initialize monitors */ for (i = 0; i < NMON; i++) { montab[i].state = MFREE; } /* Initialize buffer pools */ for (i = 0; i < NPOOL; i++) { bfptab[i].state = BFPFREE; } /* initialize thread ready list */ readylist = queinit(); #if SB_BUS backplaneInit(NULL); #endif /* SB_BUS */ #if RTCLOCK /* initialize real time clock */ clkinit(); #endif /* RTCLOCK */ #ifdef UHEAP_SIZE /* Initialize user memory manager */ { void *userheap; /* pointer to user memory heap */ userheap = stkget(UHEAP_SIZE); if (SYSERR != (int)userheap) { userheap = (void *)((uint)userheap - UHEAP_SIZE + sizeof(int)); memRegionInit(userheap, UHEAP_SIZE); /* initialize memory protection */ safeInit(); /* initialize kernel page mappings */ safeKmapInit(); } } #endif #if USE_TLB /* initialize TLB */ tlbInit(); /* register system call handler */ exceptionVector[EXC_SYS] = syscall_entry; #endif /* USE_TLB */ #if NMAILBOX /* intialize mailboxes */ mailboxInit(); #endif #if NDEVS for (i = 0; i < NDEVS; i++) { devtab[i].init((device*)&devtab[i]); } #endif #ifdef WITH_USB usbinit(); #endif #if NVRAM nvramInit(); #endif #if NNETIF netInit(); #endif #if GPIO gpioLEDOn(GPIO_LED_CISCOWHT); #endif return OK; }
/*------------------------------------------------------------------------ * create - Create a process to start running a function on x86 *------------------------------------------------------------------------ */ pid32 create( void *funcaddr, /* Address of the function */ uint32 ssize, /* Stack size in bytes */ pri16 priority, /* Process priority > 0 */ char *name, /* Name (for debugging) */ uint32 nargs, /* Number of args that follow */ ... ) { uint32 savsp, *pushsp; intmask mask; /* Interrupt mask */ pid32 pid; /* Stores new process id */ struct procent *prptr; /* Pointer to proc. table entry */ int32 i; uint32 *a; /* Points to list of args */ uint32 *saddr; /* Stack address */ mask = disable(); if (ssize < MINSTK) ssize = MINSTK; ssize = (uint32) roundmb(ssize); if ( (priority < 1) || ((pid=newpid()) == SYSERR) || ((saddr = (uint32 *)getstk(ssize)) == (uint32 *)SYSERR) ) { restore(mask); return SYSERR; } prcount++; prptr = &proctab[pid]; /* Initialize process table entry for new process */ prptr->prstate = PR_SUSP; /* Initial state is suspended */ prptr->prprio = priority; prptr->prstkbase = (char *)saddr; prptr->prstklen = ssize; prptr->prname[PNMLEN-1] = NULLCH; for (i=0 ; i<PNMLEN-1 && (prptr->prname[i]=name[i])!=NULLCH; i++) ; prptr->prsem = -1; prptr->prparent = (pid32)getpid(); prptr->prhasmsg = FALSE; // message queue for mysend<n> and myreceive<n> initMsgBuffer(&(prptr->mBuff)); prptr->prnmsgwait = 0; // initially waiting for 0 messages from mysendn /* Set up stdin, stdout, and stderr descriptors for the shell */ prptr->prdesc[0] = CONSOLE; prptr->prdesc[1] = CONSOLE; prptr->prdesc[2] = CONSOLE; /* Initialize stack as if the process was called */ *saddr = STACKMAGIC; savsp = (uint32)saddr; /* Push arguments */ a = (uint32 *)(&nargs + 1); /* Start of args */ a += nargs -1; /* Last argument */ for ( ; nargs > 0 ; nargs--) /* Machine dependent; copy args */ *--saddr = *a--; /* onto created process's stack */ *--saddr = (long)INITRET; /* Push on return address */ /* The following entries on the stack must match what ctxsw */ /* expects a saved process state to contain: ret address, */ /* ebp, interrupt mask, flags, registers, and an old SP */ *--saddr = (long)funcaddr; /* Make the stack look like it's*/ /* half-way through a call to */ /* ctxsw that "returns" to the*/ /* new process */ *--saddr = savsp; /* This will be register ebp */ /* for process exit */ savsp = (uint32) saddr; /* Start of frame for ctxsw */ *--saddr = 0x00000200; /* New process runs with */ /* interrupts enabled */ /* Basically, the following emulates an x86 "pushal" instruction*/ *--saddr = 0; /* %eax */ *--saddr = 0; /* %ecx */ *--saddr = 0; /* %edx */ *--saddr = 0; /* %ebx */ *--saddr = 0; /* %esp; value filled in below */ pushsp = saddr; /* Remember this location */ *--saddr = savsp; /* %ebp (while finishing ctxsw) */ *--saddr = 0; /* %esi */ *--saddr = 0; /* %edi */ *pushsp = (unsigned long) (prptr->prstkptr = (char *)saddr); restore(mask); return pid; }
/*------------------------------------------------------------------------ * sysinit -- initialize all Xinu data structeres and devices *------------------------------------------------------------------------ */ LOCAL sysinit() { int i,j,len; struct pentry *pptr; /* null process entry */ struct sentry *sptr; struct mblock *volatile mptr; numproc = 0; /* initialize system variables */ nextproc = NPROC-1; nextsem = NSEM-1; nextqueue = NPROC; /* q[0..NPROC-1] are processes */ memlist.mnext = mptr = /* initialize free memory list */ (struct mblock *volatile) roundmb(__malloc_heap_start); mptr->mnext = (struct mblock *)NULL; mptr->mlen = len = (int) truncmb(RAMEND - NULLSTK - (unsigned)&__bss_end); __malloc_heap_start = (char *)mptr; __malloc_heap_end = __malloc_heap_start + len; kprintf_P(PSTR("Heap: %p of length %d\n"), mptr, len); for (i=0 ; i<NPROC ; i++) /* initialize process table */ proctab[i].pstate = PRFREE; /* initialize null process entry */ pptr = &proctab[NULLPROC]; pptr->pstate = PRCURR; for (j=0; j<6; j++) pptr->pname[j] = "nullp"[j]; pptr->plimit = (unsigned char *)(RAMEND + 1) - NULLSTK; pptr->pbase = (unsigned char *) RAMEND; *pptr->pbase = (unsigned char)MAGIC; /* clobbers return, but proc 0 doesn't return */ pptr->paddr = (int *) main; pptr->pargs = 0; pptr->pprio = 0; pptr->pregs[SSP_L] = lobyte((unsigned int)pptr->plimit); /* for error checking */ pptr->pregs[SSP_H] = hibyte((unsigned int)pptr->plimit); /* for error checking */ currpid = NULLPROC; for (i=0 ; i<NSEM ; i++) { /* initialize semaphores */ (sptr = &semaph[i])->sstate = SFREE; sptr->sqtail = 1 + (sptr->sqhead = newqueue()); } rdytail = 1 + (rdyhead=newqueue()); /* initialize ready list */ #ifdef MEMMARK kprintf("Memory marking\n"); _mkinit(); /* initialize memory marking */ #else kprintf("Pool init\n"); poolinit(); /* explicitly */ pinit(MAXMSGS); #endif #ifdef RTCLOCK kprintf("init RTC\n"); clkinit(); /* initialize r.t.clock */ #endif #ifdef NDEVS for ( i=0 ; i<NDEVS ; i++ ) { if (i>0) kprintf("init dev %d\n", i); init(i); } #endif #ifdef NNETS // kprintf("net init\n"); netinit(); #endif return (OK); }
/*------------------------------------------------------------------------ * sysinit -- initialize all Xinu data structeres and devices *------------------------------------------------------------------------ */ LOCAL int sysinit() { int i,j; struct pentry *pptr; struct sentry *sptr; struct mblock *mptr; numproc = 0; /* initialize system variables */ nextproc = NPROC-1; nextsem = NSEM-1; nextqueue = NPROC; /* q[0..NPROC-1] are processes */ /* initialize free memory list */ /* PC version has to pre-allocate 640K-1024K "hole" */ if (maxaddr+1 > (char *)HOLESTART) { memlist.mnext = mptr = (struct mblock *) roundmb(&end); mptr->mnext = (struct mblock *)HOLEEND; mptr->mlen = (int) truncew(((unsigned) HOLESTART - (unsigned)&end)); mptr->mlen -= 4; mptr = (struct mblock *) HOLEEND; mptr->mnext = 0; mptr->mlen = (int) truncew((unsigned)maxaddr - HOLEEND - NULLSTK); } else { /* initialize free memory list */ memlist.mnext = mptr = (struct mblock *) roundmb(&end); mptr->mnext = 0; mptr->mlen = (int) truncew((unsigned)maxaddr - (int)&end - NULLSTK); } for (i=0 ; i<NPROC ; i++) /* initialize process table */ proctab[i].pstate = PRFREE; pptr = &proctab[NULLPROC]; /* initialize null process entry */ pptr->pstate = PRCURR; for (j=0; j<7; j++) pptr->pname[j] = "prnull"[j]; pptr->plimit = (WORD)(maxaddr + 1) - NULLSTK; pptr->pbase = (WORD) maxaddr - 3; pptr->pesp = pptr->pbase-4; /* for stkchk; rewritten before used */ *( (int *)pptr->pbase ) = MAGIC; pptr->paddr = (WORD) nulluser; pptr->pargs = 0; pptr->pprio = 0; currpid = NULLPROC; for (i=0 ; i<NSEM ; i++) { /* initialize semaphores */ (sptr = &semaph[i])->sstate = SFREE; sptr->sqtail = 1 + (sptr->sqhead = newqueue()); } rdytail = 1 + (rdyhead=newqueue());/* initialize ready list */ #ifdef MEMMARK _mkinit(); /* initialize memory marking */ #endif #ifdef RTCLOCK clkinit(); /* initialize r.t.clock */ #endif pci_init(); /* PCI */ mon_init(); /* init monitor */ // ripinit(); #ifdef NDEVS for (i=0 ; i<NDEVS ; i++ ) { init_dev(i); } #endif buf_init(); return(OK); }
/*------------------------------------------------------------------------ * getmem - Allocate heap storage, returning lowest word address *------------------------------------------------------------------------ */ char *getmem( uint32 nbytes /* Size of memory requested */ ) { intmask mask; /* Saved interrupt mask */ struct memblk *prev, *curr, *leftover; mask = disable(); if (nbytes == 0) { restore(mask); return (char *)SYSERR; } nbytes = (uint32) roundmb(nbytes); /* Use memblk multiples */ prev = &memlist; curr = memlist.mnext; while (curr != NULL) { /* Search free list */ if (curr->mlength == nbytes) { /* Block is exact match */ prev->mnext = curr->mnext; /* jteague6 - allow prev node re-linking to support * from-the-back node searching */ if( curr == memtail.mprev ) { memtail.mprev = prev; } else { curr->mnext->mprev = prev; } memlist.mlength -= nbytes; restore(mask); return (char *)(curr); } else if (curr->mlength > nbytes) { /* Split big block */ leftover = (struct memblk *)((uint32) curr + nbytes); prev->mnext = leftover; leftover->mnext = curr->mnext; leftover->mlength = curr->mlength - nbytes; memlist.mlength -= nbytes; /* jteague6 - support prev node re-linking to allow * from-the-back memory searching */ leftover->mprev = curr->mprev; if( curr == memtail.mprev ) { memtail.mprev = leftover; } else { curr->mnext->mprev = leftover; } restore(mask); return (char *)(curr); } else { /* Move to next block */ prev = curr; curr = curr->mnext; } } restore(mask); return (char *)SYSERR; }
/*------------------------------------------------------------------------ * freemem - Free a memory block, returning the block to the free list *------------------------------------------------------------------------ */ syscall freemem( char *blkaddr, /* Pointer to memory block */ uint32 nbytes /* Size of block in bytes */ ) { intmask mask; /* Saved interrupt mask */ struct memblk *next, *prev, *block; uint32 top; mask = disable(); if ((nbytes == 0) || ((uint32) blkaddr < (uint32) minheap) || ((uint32) blkaddr > (uint32) maxheap)) { restore(mask); return SYSERR; } nbytes = (uint32) roundmb(nbytes); /* Use memblk multiples */ block = (struct memblk *)blkaddr; prev = &memlist; /* Walk along free list */ next = memlist.mnext; while ((next != NULL) && (next < block)) { prev = next; next = next->mnext; } if (prev == &memlist) { /* Compute top of previous block*/ top = (uint32) NULL; } else { top = (uint32) prev + prev->mlength; } /* Ensure new block does not overlap previous or next blocks */ if (((prev != &memlist) && (uint32) block < top) || ((next != NULL) && (uint32) block+nbytes>(uint32)next)) { restore(mask); return SYSERR; } memlist.mlength += nbytes; /* Either coalesce with previous block or add to free list */ if (top == (uint32) block) { /* Coalesce with previous block */ prev->mlength += nbytes; block = prev; } else { /* Link into list as new node */ block->mnext = next; block->mlength = nbytes; prev->mnext = block; } /* Coalesce with next block if adjacent */ if (((uint32) block + block->mlength) == (uint32) next) { block->mlength += next->mlength; block->mnext = next->mnext; } restore(mask); return OK; }
/* * vfreemem - free a virtual memory block, returning it to vmemlist * */ SYSCALL vfreemem(struct mblock* block, unsigned int size) { STATWORD ps; struct mblock * curr; struct mblock * next; struct pentry * pptr; unsigned top; // Make sure they passed us a valid value for size if (size==0) return SYSERR; // Make sure they passed us a valid value for block if ((unsigned) block < (unsigned)(NBPG*4096)) return SYSERR; // Get pointer to proctab entry for this proc pptr = &proctab[currpid]; // Round up to a multiple of the size of a memory block size = (unsigned)roundmb(size); // Disable interrupts disable(ps); // Iterate through the list until we get to the end or // the next block (p) is greater than the block we are // freeing. Basically this is so we can insert our block // back into the list in sorted order. curr = &(pptr->vmemlist); next = curr->mnext; while((next != (struct mblock *) NULL) && (next < block)) { curr=next; next=next->mnext; } // Check for errors // - Is the block already a part of a free block? // - Does curr include part of it? // - Does next include part of it? // Check for errors.. See if the block is already a member of the // current block (make sure the current block isn't the head of // the list). top = curr->mlen + (unsigned)curr; // The top of the current block if ((curr != &(pptr->vmemlist)) && (top > (unsigned)block)) { restore(ps); return SYSERR; } // Check for errors.. See if the block is a member of the next // block if ((next != NULL) && ((size + (unsigned)block) > (unsigned)next)) { restore(ps); return(SYSERR); } // Is the top of the current block equal to the start of the // block that is being freed? If so then just make the current // free block bigger (adjust mlen). if ((curr != &(pptr->vmemlist)) && (top == (unsigned)block)) { curr->mlen += size; // If not then create a new block and add it to the list. } else { block->mlen = size; block->mnext = next; curr->mnext = block; curr = block; } // We may now be able to merge this block with the next block // if they are now right next to one another. if ((unsigned)(curr->mlen + (unsigned)curr) == (unsigned)next) { curr->mlen += next->mlen; curr->mnext = next->mnext; } restore(ps); return(OK); }
/*------------------------------------------------------------------------ * sysinit -- initialize all Xinu data structeres and devices *------------------------------------------------------------------------ */ LOCAL sysinit() { static long currsp; int i,j; struct pentry *pptr; struct sentry *sptr; struct mblock *mptr; numproc = 0; /* initialize system variables */ nextproc = NPROC-1; nextsem = NSEM-1; nextqueue = NPROC; /* q[0..NPROC-1] are processes */ #ifdef X__COM32__ puts_com32("sysinit()\n"); #endif #ifdef __COM32__ /* initialize free memory list */ kprintf("com32topmem %d\n", (unsigned long) com32topmem); com32topmem = com32topmem - 1024*64; /* !!! we need some space fort this code */ maxaddr = (char*) com32topmem; kprintf("maxaddr %d\n", (unsigned long) maxaddr); memlist.mnext = mptr = (struct mblock *) roundmb(&end); mptr->mnext = 0; mptr->mlen = (int) truncew((unsigned)maxaddr - (int)&end - NULLSTK); #else /* initialize free memory list */ /* PC version has to pre-allocate 640K-1024K "hole" */ if (maxaddr+1 > HOLESTART) { memlist.mnext = mptr = (struct mblock *) roundmb(&end); mptr->mnext = (struct mblock *)HOLEEND; mptr->mlen = (int) truncew((unsigned) HOLESTART - (unsigned)&end - 4); mptr = (struct mblock *) HOLEEND; mptr->mnext = 0; mptr->mlen = (int) truncew(maxaddr - HOLEEND - NULLSTK); } else { /* initialize free memory list */ memlist.mnext = mptr = (struct mblock *) roundmb(&end); mptr->mnext = 0; mptr->mlen = (int) truncew((unsigned)maxaddr - (int)&end - NULLSTK); } #endif #ifdef X__COM32__ puts_com32("sysinit() free memory list done\n"); #endif for (i=0 ; i<NPROC ; i++) /* initialize process table */ proctab[i].pstate = PRFREE; #ifdef X__COM32__ puts_com32("sysinit() proctab done\n"); #endif pptr = &proctab[NULLPROC]; /* initialize null process entry */ pptr->pstate = PRCURR; for (j=0; j<7; j++) pptr->pname[j] = "prnull"[j]; pptr->plimit = (WORD)(maxaddr + 1) - NULLSTK; pptr->pbase = (WORD) maxaddr - 3; pptr->pesp = pptr->pbase-4; /* for stkchk; rewritten before used */ *( (int *)pptr->pbase ) = MAGIC; pptr->paddr = (WORD) nulluser; pptr->pargs = 0; pptr->pprio = 0; currpid = NULLPROC; for (i=0 ; i<NSEM ; i++) { /* initialize semaphores */ (sptr = &semaph[i])->sstate = SFREE; sptr->sqtail = 1 + (sptr->sqhead = newqueue()); } rdytail = 1 + (rdyhead=newqueue());/* initialize ready list */ #ifdef X__COM32__ puts_com32("sysinit() semaphores done\n"); #endif #ifdef MEMMARK _mkinit(); /* initialize memory marking */ #ifdef __COM32__ puts_com32("sysinit() memory marking done\n"); #endif #endif #ifdef RTCLOCK clkinit(); /* initialize r.t.clock */ #ifdef __COM32__ puts_com32("sysinit() rtc done\n"); #endif #endif #ifdef NDEVS for ( i=0 ; i<NDEVS ; i++ ) { init(i); } #ifdef __COM32__ puts_com32("sysinit() devs done\n"); #endif #endif #ifdef NNETS netinit(); #ifdef __COM32__ puts_com32("sysinit() netinit() done\n"); #endif #endif return(OK); }
/*------------------------------------------------------------------------ * getmem -- allocate heap storage, returning lowest WORD address *------------------------------------------------------------------------ */ WORD *vgetmem(unsigned nbytes) { STATWORD ps; struct mblock *p, *q, *leftover; disable(ps); if (nbytes==0 || memlist.mnext== (struct mblock *) NULL) { restore(ps); return( (WORD *)SYSERR); } nbytes = (unsigned int) roundmb(nbytes); for (q= &memlist,p=memlist.mnext ; p != (struct mblock *) NULL ; q=p,p=p->mnext) if ( p->mlen == nbytes) { q->mnext = p->mnext; restore(ps); return( (WORD *)p ); } else if ( p->mlen > nbytes ) { leftover = (struct mblock *)( (unsigned)p + nbytes ); q->mnext = leftover; leftover->mnext = p->mnext; leftover->mlen = p->mlen - nbytes; restore(ps); return( (WORD *)p ); } restore(ps); return( (WORD *)SYSERR ); }