As we know, xv6 doesn't let a spinlock be acquired twice (even by a process itself).
I am trying to add this feature which lets a process to acquire a lock more than once.
In order to reach this, I am adding an attribute called lock_holder_pid
to the struct spinlock
which is supposed to hold the pid of the process which has acquired this lock.
The only file I have changed is spinlock.c
Here is my new acquire()
function:
// Acquire the lock.
// Loops (spins) until the lock is acquired.
// Holding a lock for a long time may cause
// other CPUs to waste time spinning to acquire it.
void
acquire(struct spinlock *lk)
{
pushcli(); // disable interrupts to avoid deadlock.
uint cur_proc_pid = myproc()->pid; //Added by me
if (holding(lk) && lk->lock_holder_pid == cur_proc_pid) //Added by me
{
popcli();
return;
}
if(holding(lk) && lk->lock_holder_pid != cur_proc_pid) //Added by me
panic("acquire");
/* Commented by me
if(holding(lk))
panic("acquire");
*/
// The xchg is atomic.
while(xchg(&lk->locked, 1) != 0)
;
lk-> lock_holder_pid = cur_proc_pid; //Added by me
// Tell the C compiler and the processor to not move loads or stores
// past this point, to ensure that the critical section's memory
// references happen after the lock is acquired.
__sync_synchronize();
// Record info about lock acquisition for debugging.
lk->cpu = mycpu();
getcallerpcs(&lk, lk->pcs);
}
I also changed the initlock()
function to this:
void
initlock(struct spinlock *lk, char *name)
{
lk->name = name;
lk->locked = 0;
lk->cpu = 0;
lk->lock_holder_pid = -1; //Added by me
}
The last function I modified is:
void
release(struct spinlock *lk)
{
if(!holding(lk))
panic("release");
lk->pcs[0] = 0;
lk->cpu = 0;
lk->lock_holder_pid = -1; //Added by me
...
The problem is that the xv6 terminal get's stuck when booting with the message:
Booting from Hard Disk...
As far as I have understood, the line causing the problem is:
uint cur_proc_pid = myproc()->pid;
When I comment this line and only set lock_holder_pid to a constant number, it boots successfully.
Can anyone please help me with this?
The sections in the code marked with "Added by me" are the parts I have added.
This is simply because you are trying to have access to a field of a null struct (myproc()->pid
).
As you may know, myproc()
returns a process running on the current processor. If you look at main.c
, you may notice that the bootstrap processor starts running there. Therefore, if we can find a function which calls the acquire()
function before setting up the first process, the problem will be solved.
If you take a close look at the kinit1
function, you can realize that the acquire
function is called in it. Consequently, we found a function that uses the acquire
function, even before initializing the ptable
struct. Therefore, when you try to access the myproc()
value, it is not initialized yet.