In this lab you will try to avoid lock contention for certain workloads.
The program user/kalloctest stresses xv6's memory allocator: three processes grow and shrink there address space, which will results in many calls to kalloc and kfree, respectively. kalloc and kfree obtain kmem.lock. To see if there is lock contention for kmem.lock replace the call to acquire in kalloc with the following code:
while(!tryacquire(&kmem.lock)) { printf("!"); }
tryacquire tries to acquire kmem.lock: if the lock is taking it returns false (0); otherwise, it returns true (1) and with the lock acquired. Your first job is to implement tryacquire in kernel/spinlock.c.
A few hints:
Run usertests to see if you didn't break anything. Note that usertests never prints "!"; there is never contention for kmem.lock. The caller is always able to immediately acquire the lock and never has to wait because some other process has the lock.
Now run kalloctest. You should see quite a number of "!" on the console. kalloctest causes many processes to contend on the kmem.lock. This lock contention is a bit artificial, because qemu is simulating 3 processors, but it is likely on real hardware, there would be contention too.
The root cause of lock contention in kalloctest is that there is a single free list, protected by a single lock. To remove lock contention, you will have to redesign the memory allocator to avoid a single lock and list. The basic idea is to maintain a free list per CPU, each list with its own lock. Allocations and frees on each CPU can run in parallel, because each CPU will operate on a different list.
The main challenge will be to deal with the case that one CPU runs out of memory, but another CPU has still free memory; in that case, the one CPU must "steal" part of the other CPU's free list. Stealing may introduce lock contention, but that may be acceptable because it may happen infrequently.
Your job is to implement per-CPU freelists and stealing when one CPU is out of memory. Run kalloctest() to see if your implementation has removed lock contention.
Some hints:
Run usertests to see if you don't break anything.