xref: /xv6-public/kalloc.c (revision 1a81e38b)
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 "mmu.h"
9 #include "spinlock.h"
10 
11 struct run {
12   struct run *next;
13 };
14 
15 struct {
16   struct spinlock lock;
17   struct run *freelist;
18 } kmem;
19 
20 extern char end[]; // first address after kernel loaded from ELF file
21 
22 // Initialize free list of physical pages.
23 void
24 kinit(void)
25 {
26   char *p;
27 
28   initlock(&kmem.lock, "kmem");
29   p = (char*)PGROUNDUP((uint)end);
30   for(; p + PGSIZE - 1 < (char*)PHYSTOP; p += PGSIZE)
31     kfree(p);
32 }
33 
34 //PAGEBREAK: 21
35 // Free the page of physical memory pointed at by v,
36 // which normally should have been returned by a
37 // call to kalloc().  (The exception is when
38 // initializing the allocator; see kinit above.)
39 void
40 kfree(char *v)
41 {
42   struct run *r;
43 
44   if((uint)v % PGSIZE || v < end || (uint)v >= PHYSTOP)
45     panic("kfree");
46 
47   // Fill with junk to catch dangling refs.
48   memset(v, 1, PGSIZE);
49 
50   acquire(&kmem.lock);
51   r = (struct run*)v;
52   r->next = kmem.freelist;
53   kmem.freelist = r;
54   release(&kmem.lock);
55 }
56 
57 // Allocate one 4096-byte page of physical memory.
58 // Returns a pointer that the kernel can use.
59 // Returns 0 if the memory cannot be allocated.
60 char*
61 kalloc(void)
62 {
63   struct run *r;
64 
65   acquire(&kmem.lock);
66   r = kmem.freelist;
67   if(r)
68     kmem.freelist = r->next;
69   release(&kmem.lock);
70   return (char*)r;
71 }
72 
73