xref: /xv6-public/kalloc.c (revision 1a81e38b)
1f5527388Srsc // Physical memory allocator, intended to allocate
27d7dc933SRobert Morris // memory for user processes, kernel stacks, page table pages,
37d7dc933SRobert Morris // and pipe buffers. Allocates 4096-byte pages.
455e95b16Srtm 
555e95b16Srtm #include "types.h"
655e95b16Srtm #include "defs.h"
78148b6eeSrtm #include "param.h"
840889627SFrans Kaashoek #include "mmu.h"
94e8f237bSrtm #include "spinlock.h"
104e8f237bSrtm 
1155e95b16Srtm struct run {
1255e95b16Srtm   struct run *next;
1355e95b16Srtm };
1434295f46Srsc 
1534295f46Srsc struct {
1634295f46Srsc   struct spinlock lock;
1755e95b16Srtm   struct run *freelist;
1834295f46Srsc } kmem;
1955e95b16Srtm 
204587b358SRobert Morris extern char end[]; // first address after kernel loaded from ELF file
214587b358SRobert Morris 
22f5527388Srsc // Initialize free list of physical pages.
2355e95b16Srtm void
248d774afbSRobert Morris kinit(void)
2555e95b16Srtm {
26*1a81e38bSRuss Cox   char *p;
27*1a81e38bSRuss Cox 
2834295f46Srsc   initlock(&kmem.lock, "kmem");
29*1a81e38bSRuss Cox   p = (char*)PGROUNDUP((uint)end);
303597d5dcSRobert Morris   for(; p + PGSIZE - 1 < (char*)PHYSTOP; p += PGSIZE)
313597d5dcSRobert Morris     kfree(p);
3255e95b16Srtm }
3355e95b16Srtm 
345048762cSAustin Clements //PAGEBREAK: 21
357d7dc933SRobert Morris // Free the page of physical memory pointed at by v,
3631085bb4Srsc // which normally should have been returned by a
377d7dc933SRobert Morris // call to kalloc().  (The exception is when
3831085bb4Srsc // initializing the allocator; see kinit above.)
3955e95b16Srtm void
407d7dc933SRobert Morris kfree(char *v)
4155e95b16Srtm {
427d7dc933SRobert Morris   struct run *r;
4355e95b16Srtm 
44*1a81e38bSRuss Cox   if((uint)v % PGSIZE || v < end || (uint)v >= PHYSTOP)
4555e95b16Srtm     panic("kfree");
4655e95b16Srtm 
47d4c64e5dSrsc   // Fill with junk to catch dangling refs.
487d7dc933SRobert Morris   memset(v, 1, PGSIZE);
498b4e2a08Srtm 
5034295f46Srsc   acquire(&kmem.lock);
517d7dc933SRobert Morris   r = (struct run*)v;
527d7dc933SRobert Morris   r->next = kmem.freelist;
537d7dc933SRobert Morris   kmem.freelist = r;
5434295f46Srsc   release(&kmem.lock);
5555e95b16Srtm }
5655e95b16Srtm 
577d7dc933SRobert Morris // Allocate one 4096-byte page of physical memory.
587d7dc933SRobert Morris // Returns a pointer that the kernel can use.
59f5527388Srsc // Returns 0 if the memory cannot be allocated.
6055e95b16Srtm char*
61*1a81e38bSRuss Cox kalloc(void)
6255e95b16Srtm {
637d7dc933SRobert Morris   struct run *r;
6455e95b16Srtm 
6534295f46Srsc   acquire(&kmem.lock);
667d7dc933SRobert Morris   r = kmem.freelist;
677d7dc933SRobert Morris   if(r)
687d7dc933SRobert Morris     kmem.freelist = r->next;
6934295f46Srsc   release(&kmem.lock);
707d7dc933SRobert Morris   return (char*)r;
7155e95b16Srtm }
7240889627SFrans Kaashoek 
73