xv6, line by line
kernel/kalloc.c

kernel/kalloc.c

C · 82 lines · annotated 100% · kernel · upstream

About this file

The kernel’s page allocator. All memory the kernel hands out at run time comes from here, one 4096-byte page at a time: page-table pages, user memory, kernel stacks, trapframes, pipe buffers, the virtio disk’s rings and the buffers that hold exec arguments. There is no malloc for smaller objects; everything else in the kernel is a fixed-size global array.

The design is the simplest possible one: a linked list of free pages, where each free page itself stores the pointer to the next one. kalloc pops a page off the list, kfree pushes one on, and a spinlock keeps harts from doing so at the same time.

The pages are the RAM between the end of the kernel image (end) and PHYSTOP; see the map in kernel/memlayout.h. kalloc returns a physical address. The kernel can use it as an ordinary pointer because physical memory is either untranslated (before paging is turned on, when kinit runs) or covered by the direct map (after).

Read before: kernel/memlayout.h. Read next: kernel/vm.c, the main user of these pages.

1// Physical memory allocator, for user processes,
2// kernel stacks, page-table pages,
3// and pipe buffers. Allocates whole 4096-byte pages.
5#include "types.h"
6#include "param.h"
8#include "spinlock.h"
9#include "riscv.h"
10#include "defs.h"
12void freerange(void *pa_start, void *pa_end);
14extern char end[]; // first address after kernel.
15 // defined by kernel.ld.
17struct run {
18 struct run *next;
19};
21struct {
22 struct spinlock lock;
23 struct run *freelist;
26void
29 initlock(&kmem.lock, "kmem");
30 freerange(end, (void *)PHYSTOP);
33void
36 char *p;
38 for (; p + PGSIZE <= (char *)pa_end; p += PGSIZE)
42// Free the page of physical memory pointed at by pa,
43// which normally should have been returned by a
44// call to kalloc(). (The exception is when
45// initializing the allocator; see kinit above.)
46void
47kfree(void *pa)
49 struct run *r;
51 if (((uint64)pa % PGSIZE) != 0 || (char *)pa < end || (uint64)pa >= PHYSTOP)
52 panic("kfree");
54 // Fill with junk to catch dangling refs.
57 r = (struct run *)pa;
65// Allocate one 4096-byte page of physical memory.
66// Returns a pointer that the kernel can use.
67// Returns 0 if the memory cannot be allocated.
68void *
69kalloc(void)
71 struct run *r;
75 if (r)
79 if (r)
80 memset((char *)r, 5, PGSIZE); // fill with junk
81 return (void *)r;