xref: /xv6-public/kalloc.c (revision 66ba8079)
1 // Physical memory allocator, intended to allocate
2 // memory for user processes, kernel stacks, page table pages,
3 // and pipe buffers. Allocates 4096-byte pages.
4 
5 #include "types.h"
6 #include "defs.h"
7 #include "param.h"
8 #include "memlayout.h"
9 #include "mmu.h"
10 #include "spinlock.h"
11 
12 struct run {
13   struct run *next;
14 };
15 
16 struct {
17   struct spinlock lock;
18   struct run *freelist;
19 } kmem;
20 
21 extern char end[]; // first address after kernel loaded from ELF file
22 char *newend;
23 
24 // simple page allocator to get off the ground during boot
25 char *
26 boot_alloc(void)
27 {
28   if (newend == 0)
29     newend = end;
30 
31   if ((uint) newend >= KERNBASE + 0x400000)
32     panic("only first 4Mbyte are mapped during boot");
33   void *p = (void*)PGROUNDUP((uint)newend);
34   memset(p, 0, PGSIZE);
35   newend = newend + PGSIZE;
36   return p;
37 }
38 
39 // Initialize free list of physical pages.
40 void
41 kinit(void)
42 {
43   char *p;
44 
45   initlock(&kmem.lock, "kmem");
46   p = (char*)PGROUNDUP((uint)newend);
47   for(; p + PGSIZE <= (char*)p2v(PHYSTOP); p += PGSIZE)
48     kfree(p);
49 }
50 
51 //PAGEBREAK: 21
52 // Free the page of physical memory pointed at by v,
53 // which normally should have been returned by a
54 // call to kalloc().  (The exception is when
55 // initializing the allocator; see kinit above.)
56 void
57 kfree(char *v)
58 {
59   struct run *r;
60 
61   if((uint)v % PGSIZE || v < end || v2p(v) >= PHYSTOP)
62     panic("kfree");
63 
64   // Fill with junk to catch dangling refs.
65   memset(v, 1, PGSIZE);
66 
67   acquire(&kmem.lock);
68   r = (struct run*)v;
69   r->next = kmem.freelist;
70   kmem.freelist = r;
71   release(&kmem.lock);
72 }
73 
74 // Allocate one 4096-byte page of physical memory.
75 // Returns a pointer that the kernel can use.
76 // Returns 0 if the memory cannot be allocated.
77 char*
78 kalloc(void)
79 {
80   struct run *r;
81 
82   acquire(&kmem.lock);
83   r = kmem.freelist;
84   if(r)
85     kmem.freelist = r->next;
86   release(&kmem.lock);
87   return (char*)r;
88 }
89 
90