12. Implementation of the Wait() system call for the simple Operating
    System.
    Book : Operating Systems - A design Space Approach
           by Charles Crowley.

The Wait() is modeled after the one given in Chapter. 3, p. 46 (not Unix wait())
The changes are as follows:


Changes in the Global Data (p. 123)

// Add two new states
enum ProcessState {Ready, Running, Blocked, Waiting, Exited};

// Add three new fields to the process descriptor
struct ProcessDescriptor
    {
        // ...  other fields remain unchanged
        int returnCode;     // exit status code of the process.
        int waitingProcess; // if there is a process waiting, then store the
                            // index of the table of the waiting process.
        int exitTime;       // the number of time quantums an exited process has
        // stayed in the descriptor table.
    }

The added fields can be initialized during process creation in
the CreateProcessSysProc (p. 126)

int CreateProcessSysProc(int first_block, int n_blocks)
{
    // ...
    pd[pid].exitTime = 0;
    pd[pid].returnCode = 0;
    pd[pid].waitingProcess = 0; // No process is waiting.
    // ... rest unchanged
}

Change in the System call Interrupt Handler(p. 141)

void SystemCallInterruptHandler (void)
{
    // ...

    // All cases remain the same except for the ExitProcessSystemCall
    // which is modified as follows

case ExitProcessSystemCall:

    char * return_code;
    // Get the argument passed(pid) from register R9
    asm { store r9, return_code }

    // Save the return code in the process descriptor
    pd[current_process].returnCode = return_code;

    // The exitTime will be used to later remove the process
    // from process descriptor table.
    pd[current_process].exitTime = 0;

    if (pd[current_process].waitingProcess)
        {
            // There is already a process that is waiting for
            // the current process(by executing Wait() ).
            // Move that process from Waiting to Ready state
            pd[pd[current_process].waitingProcess] = Exited;
            // The slotAllocated field cannot be made False
            // as the return code has to be preserved.
        }
    // Change the state of the current process
    pd[current_process].state = Exited;
    // The state Exited ensures that the Dispatcher does
    // not choose this slot to allocate a new process.
    break;

    // A new case is added for the Wait

case WaitSystemCall:

    int pidToWait;
    // The argument passed to Wait is the pid of the
    // process to wait, store it in pidToWait.
    asm { store r8, pidToWait }

    int i;
    for (i = 1; i < NumberOfProcesses; ++i ) // 0 is the OS
        {
            if (pd[i].slotAllocated = True &&
                                      pd[i].sa.reg[1] == pidToWait)
                {
                    // The field 1 of the save area store the pid
                    // of the process - if it matches that of pidToWait
                    // then i is the required index to the descriptor table.
                    break;
                }
        }

    if (i >= NumberOfProcesses)
        {
            // The required pid is not found, the argument
            // passed may be invalid - handle suitably.
        }


    // The process we are waiting for has already
    // exited (i.e. Exit() occurs before Wait())
    if (pd[i].state == Exited )
        {
            // R1 is used to pass return value(the exit code)
            asm { load pd[i].returnCode, r1 }
            // Now the slot can be freed as we got the exit status
            pd[i].slotAllocated = False;
            // The state of the current process does not change.
        }
    else
        { // Wait() occurs before Exit()
            // The current process goes to waiting state
            pd[current_process].state = Waiting;
            // Also the index of the current process is
            // stored in pd[i] so that later we can unblock.
            pd[i].waitingProcess = current_process;
        }
    break;

    // ...

}


Changes to the Dispatcher

void Dispatcher (void)
{
    // ...
    // Add one more procedure to handle exited processes

    HandleExitedProcessesSlots ();
    // ... rest of the code is unchanged
}

void HandleExitedProcessesSlots ()
{
    int i;

    // This function makes sure that no process stays in the
    // descriptor table even if no process waits for it.

    for (i = 1; i < NumberOfProcesses ; ++i)
        {
            // If the process has already exited, check the exitTime field
            if (pd[i].state == Exited)
                {
                    // The field is an integer that stores the number
                    // of time quantums the exited process has stayed
                    // in the descriptor table. If that exceeds a maximum
                    // value the slot can be claimed.
                    if (pd[i].exitTime >= 10)
                        pd[i].slotAllocated = False;
                    else
                        pd[i].exitTime ++;
                    // The maximum value is chosen such that no process exceeds
                    // the maximum number of time quantums.
                }
        }
}

1
Hosted by www.Geocities.ws