2
votes

I have this kernel code where I disable the interrupt to make this lock acquire operation atomic, but if u see the last else condition i.e. when lock is not available thread goes to sleep and interrupts are enable only after thread comes back from sleep. My question is so interrupts are disabled for whole OS until this thread comes out of sleep?


void Lock::Acquire() 
{
    IntStatus oldLevel = interrupt->SetLevel(IntOff); // Disabling the interrups          to make the following statements atomic
    if(lockOwnerThread == currentThread)            //Checking if the requesting thread already owns lock
    {
        //printf("SM:error:%s already owns the lock\n",currentThread->getName());
        DEBUG('z', "SM:error:%s already owns the lock\n",currentThread->getName());
        (void) interrupt->SetLevel(oldLevel);
        return;
    }
    if(lockOwnerThread==NULL)
    {
       lockOwnerThread = currentThread;          // Lock owner ship is given to current  thread
       DEBUG('z', "SM:The ownership of the lock %s is given to %s \n",name,currentThread->getName());
    }
    else
    {
        DEBUG('z', "SM:Adding thread %s to request queue and putting it to sleep\n",currentThread->getName());
        queueForLock->Append((void *)currentThread);    // Lock is busy so add the thread to queue;
        currentThread->Sleep(); // And go to sleep
    }
       (void) interrupt->SetLevel(oldLevel); // Enable  the interrupts
 }

1
Could you please clarify what kernel you are talking about?Serge
This piece of above code is from the NACHOS. and i think it might be same in Linux also, as i see same kind of lock acquire implementation when i googled for it.user1698605

1 Answers

1
votes

I don't know the NACHOS and I would not make any assumptions on my own. So you have to test it.

The idea is simple. If this interrupt enable/disable functionality is local to the current process context then the following should happen when you call Sleep(): the process is marked as not-running, i.e. it is excluded from the list of processes the scheduler will consider to give a CPU time. Then the Sleep() function enforces the scheduler to do it's regular work - to find a process to run. If the list of running processes is not empty, the scheduler picks up a next available process and makes a context switch to this process. After this the state of interrupt management is restored from this new context.

If there are no processes to run then scheduler enters the Idle loop state and usually enables the interrupts. While the scheduler is in Idle loop it continues to poll the queue of the running processes until it get something to schedule.

Your process will get the control when it will be marked as running again. This could happen if some other process calls WakeUp() (or a like, as I mentioned the API is unknown to me)

When the scheduler will pick up your process to switch to it performs the usual (for your system) context switch that has the interrupts enabled flag set to false, so the execution continues at statement after the Sleep() call with interrupts disabled.

If the assumptions above are incorrect and the interrupts enabled flag is global, then there are two possibilities: either the system hangs as it can't serve the interrupts, or it has some workaround for such a situations.

So, you need to try. The best way is to read the kernel sources of course, if you have the access.))