xref: /xv6-public/kalloc.c (revision 547c28fc)
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 pgalloc(void)
27 {
28   if (newend == 0)
29     newend = end;
30 
31   void *p = (void*)PGROUNDUP((uint)newend);
32   memset(p, 0, PGSIZE);
33   newend = newend + PGSIZE;
34   return p;
35 }
36 
37 // Initialize free list of physical pages.
38 void
39 kinit(void)
40 {
41   char *p;
42 
43   initlock(&kmem.lock, "kmem");
44   p = (char*)PGROUNDUP((uint)newend);
45   for(; p + PGSIZE <= (char*)p2v(PHYSTOP); p += PGSIZE)
46     kfree(p);
47 }
48 
49 //PAGEBREAK: 21
50 // Free the page of physical memory pointed at by v,
51 // which normally should have been returned by a
52 // call to kalloc().  (The exception is when
53 // initializing the allocator; see kinit above.)
54 void
55 kfree(char *v)
56 {
57   struct run *r;
58 
59   if((uint)v % PGSIZE || v < end || v2p(v) >= PHYSTOP)
60     panic("kfree");
61 
62   // Fill with junk to catch dangling refs.
63   memset(v, 1, PGSIZE);
64 
65   acquire(&kmem.lock);
66   r = (struct run*)v;
67   r->next = kmem.freelist;
68   kmem.freelist = r;
69   release(&kmem.lock);
70 }
71 
72 // Allocate one 4096-byte page of physical memory.
73 // Returns a pointer that the kernel can use.
74 // Returns 0 if the memory cannot be allocated.
75 char*
76 kalloc(void)
77 {
78   struct run *r;
79 
80   acquire(&kmem.lock);
81   r = kmem.freelist;
82   if(r)
83     kmem.freelist = r->next;
84   release(&kmem.lock);
85   return (char*)r;
86 }
87 
88