Process Management in Unix/Linux: Process Synchronization

An operating system comprises many concurrent processes, which may interact with one another. Process synchronization refers to the rules and mechanisms used to control and coordinate process interactions to ensure their proper executions. The simplest tools for process synchronization are sleep and wakeup operations.

1. Sleep Operation

Whenever a process needs something, e.g. a memory area for exclusive use, an input char from stdin, etc. that’s currently not available, it goes to sleep on an event value, which represents the reason of the sleep. To implement the sleep operation, we can add an event field to the PROC structure and implement a ksleep(int event) function, which lets a process go to sleep. In the following, we shall assume that the PROC structure is modified to include the added fields shown in bold face.

The algorithm of ksleep() is

/************ Algorithm of ksleep(int event) **************/

    1. record event value in PROC.event: running->event = event;
    2. change status to SLEEP: running->status = SLEEP;
    3. for ease of maintenance, enter caller into a PROC *sleepList enqueue(&sleepList, running);
    1. give up CPU: tswitch();

Since a sleeping process is not in the readyQueue, it’s not runnable until it is woken up by another process. So after putting itself to sleep, the process calls tswitch() to give up the CPU.

2. Wakeup Operation

Many processes may sleep on the same event, which is natural since all of them may need the same resource, e.g. a printer, which is currently busy. In that case, all such processes would go to sleep on the same event value. When an awaited event occurs, another execution entity, which may be either a process or an interrupt handler, will call kwakeup(event), which wakes up ALL the processes sleeping on the event value. If no process is sleeping on the event, kwakeup() has no effect, i.e. it does nothing. The algorithm of kwakeup() is

/*********** Algorithm of kwakeup(int event) **********/

// Assume SLEEPing procs are in a global sleepList

for each PROC *p in sleepList do{

if (p->event == event){          // if p is sleeping for the event

delete p from sleepList;

p->status = READY;          // make p READY to run again

enqueue(&readyQueue, p);    // enter p into readyQueue

}

}

It is noted that an awakened process may not run immediately. It is only put into the readyQueue, waiting for its turn to run. When an awakened process runs, it must try to get the resource again if it was trying to get a resource before the sleep. This is because the resource may no longer be available by the time it runs. The ksleep() and kwakeup() functions are intended for process synchronization in general, but they are also used in the special case to synchronize parent and child processes, which is our next topic.

Source: Wang K.C. (2018), Systems Programming in Unix/Linux, Springer; 1st ed. 2018 edition.

Leave a Reply

Your email address will not be published. Required fields are marked *