【发布时间】:2020-03-20 09:14:42
【问题描述】:
xv6 有 spinlock.c 文件,用于为内核创建自旋锁。但我需要实现在用户级别使用的自旋锁 API。例如,我将实现 sp_create() 以在用户级别创建自旋锁。或者调用 sp_acquire(int id) 来获取锁等。为此,我应该创建系统调用并将实际实现放在内核中。 xv6 具有自旋锁功能,但只能在内核级别使用。
我想过创建系统调用,它实际上是调用 spinlock.c 中的相应函数来创建锁,获取它,释放它等。但是由于中断禁用的一些问题,它不起作用。
我在下面复制我到目前为止写的代码:
//system call for lock_take():
int l_take(int lockid) {
struct proc *curproc = myproc();
//process will take lock
..
acquire(&LL.arraylockList[lockid].spnLock);
..
return 0;
}
我在这里遇到的问题是它给了我关于恐慌的错误:sched locks 我认为这是因为 acquire() 代码中有 pushcli() 。
void
acquire(struct spinlock *lk)
{
pushcli(); // disable interrupts to avoid deadlock.
if (holding(lk)) panic("acquire");
// The xchg is atomic.
while (xchg(&lk->locked, 1) != 0)
;
// 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);
}
然后我将代码复制到一个新函数 acquire2() 并在我的系统调用中使用它,其中 pushcli() 被注释掉:
acquire2(struct spinlock *lk)
{
// pushcli(); // disable interrupts to avoid deadlock.
if (holding(lk)) panic("acquire");
// The xchg is atomic.
while (xchg(&lk->locked, 1) != 0) {
;
}
// 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);
}
但是,错误消息更改为: 恐慌:在启用中断的情况下调用 mycpu()
原来是禁用中断是不允许的。因此,不应使用 pushcli() 和 popcli()。然后我需要弄清楚如何以原子方式运行 mycpu() 。它的实现是这样的:
// Must be called with interrupts disabled to avoid the caller being rescheduled
// between reading lapicid and running through the loop.
struct cpu *
mycpu(void)
{
int apicid, i;
if (readeflags() & FL_IF) panic("mycpu called with interrupts enabled\n");
apicid = lapicid();
// APIC IDs are not guaranteed to be contiguous. Maybe we should have
// a reverse map, or reserve a register to store &cpus[i].
for (i = 0; i < ncpu; ++i) {
if (cpus[i].apicid == apicid) return &cpus[i];
}
panic("unknown apicid\n");
}
for 循环和它上面的行需要原子执行。 我该怎么做?
【问题讨论】:
标签: c system-calls spinlock xv6