2

我有这个内核代码,我在其中禁用中断以使该锁获取操作原子化,但是如果您看到最后一个 else 条件,即当锁不可用时,线程进入睡眠状态,并且只有在线程从睡眠状态恢复后才启用中断。我的问题是,整个操作系统都禁用中断,直到该线程退出睡眠?

无效锁::Acquire()
{
    IntStatus oldLevel = 中断->SetLevel(IntOff); // 禁用中断以使以下语句具有原子性
    if(lockOwnerThread == currentThread) //检查请求线程是否已经拥有锁
    {
        //printf("SM:error:%s 已经拥有锁\n",currentThread->getName());
        DEBUG('z', "SM:error:%s 已经拥有锁\n",currentThread->getName());
        (void) 中断->SetLevel(oldLevel);
        返回;
    }
    如果(lockOwnerThread==NULL)
    {
       lockOwnerThread = 当前线程;// 锁拥有权赋予当前线程
       DEBUG('z', "SM:锁%s的所有权给%s \n",name,currentThread->getName());
    }
    别的
    {
        DEBUG('z', "SM: 将线程 %s 添加到请求队列并使其进入睡眠状态\n",currentThread->getName());
        queueForLock->Append((void *)currentThread); // 锁很忙,所以将线程添加到队列中;
        当前线程->睡眠();// 然后去睡觉
    }
       (void) 中断->SetLevel(oldLevel); // 启用中断
 }

4

1 回答 1

1

我不知道 NACHOS,我不会自己做任何假设。所以你必须测试它。

这个想法很简单。如果此中断启用/禁用功能在当前进程上下文中是本地的,那么当您调用时应该会发生以下情况Sleep():进程被标记为未运行,即它被排除在scheduler将考虑给予 CPU 时间的进程列表之外。然后 Sleep() 函数强制调度程序执行它的常规工作 - 查找要运行的进程。如果正在运行的进程列表不为空,则调度程序选择下一个可用进程并进行上下文切换到该进程。在此之后,中断管理的状态从这个新的上下文中恢复。

如果没有要运行的进程,则调度程序进入Idle loop状态并通常启用中断。当调度程序在其中时,Idle loop它会继续轮询正在运行的进程的队列,直到它得到一些要调度的东西。

当您的进程再次被标记为运行时,您的进程将获得控制权。如果其他一些进程调用WakeUp()(或类似的,正如我提到的 API 对我来说是未知的),则可能会发生这种情况

当调度程序将选择您的进程切换到它时,它会执行通常的(对于您的系统)上下文切换,该切换将标志设置为 false,因此在禁用中断interrupts enabled的调用后继续执行语句。Sleep()

如果上面的假设不正确并且interrupts enabled标志是全局的,那么有两种可能性:系统挂起,因为它不能提供中断服务,或者它有一些workaround用于这种情况。

所以,你需要尝试。最好的方法当然是阅读内核源代码,如果你有访问权限的话。))

于 2012-09-26T17:40:20.373 回答