Process and thread life cycle

by: burt rosenberg
at: university of miami
update: 27 sept 2019

caos85: The Canes Operating Systems

To illustrate context switching, we build upon the 8085 architecture, imaginatively extended with virtual memory, privileged mode, and richer interrupt and addressing mechanisms, to create Cane OS 85, also known as caos85.

Process Control Blocks

// caos85 kernel data structures


extern struct PCB * current ;
extern struct PCB * pcb_head ;
extern struct IVT * ivt ;  // ivt = NULL ;

typedef enum { 
	INIT, READY, RUNNING, SLEEP, ZOMBIE  } 
	ThreadState ;

struct PCB {
	// PCB points
	struct PCB * next ;
	struct PCB * next_sibling ;
	struct PCB * parent_process ;
	int pid ; // process ID
	
	// process context
	int process_state ;
	int process_priority ; // for scheduling
	struct TCB * threads ;
	struct MMAP * memory_map ;
	
	// other
	int exit_status ;


} ;

struct TCB {

	// thread information
	ThreadState  thread_state ;
	struct TCP * next ;
	struct PCB * parent ;
	int tid ; // thread ID

	// register save area
	int reg_BC ;
	int reg_DE ;
	int reg_EF ;
	int reg_HL ;
	int thread_PC ;
	int thread_SP ;
	int reg_Flags ;

} ;

struct MMAP {
	struct PTE[VM_SIZE/PAGE_SIZE] ;
} ;

struct PTE {
	void * physical_address ; // also contains flags
} ;

struct CALL_GATE {
	void * base_interrupt_stack ;
	void * handler_entry_point ;
} ;

struct IVT {
	struct CALL_GATE [INTERRUPT_LEVELS]
} ;

The fundamental abstraction of an operating system is the process. The process is the context in which a program runs. In the kernel, the process is represented by a kernel data structure called the process control block, PCB. Typically, all the PCB's are arranged in a linked list. The data stored in the PCB includes,

Thread Control Blocks

Each process contains at least one thread. A thread represents the actual running of code. The PCB and TCP's cross link, so that a TCP can reference data about its containing process, and the process can enumerate the threads it contains.

Process Life Cycle

  1. Process creation: A call is made to the kernel by fork. The kernel allocates a PCB, an initial TCB, and a MMAP, and copies the information by the called process into these structures. It then assigns a new PID, TID, updates the parent and sibling pointers in the TCB. It updates the return value for the child to be zero, and the parent to be the PID, and remaps the stack area, copying the physical pages pointed to by the stack PTE's.

    It sets the new PCB and TCP to READY and returns to the calling process.

  2. Process ready: The process is ready to run but is not running.

  3. Process running: The thread is selected to run. Its status is updated to RUNNING, and the saved registers are copied into the interrupt stack.

    The global current is set to the PCB pointer.

    When the interrupt returns, the thread resumes running.

    On interrupts, the priority of the current thread is considered with other threads to determine to preempt the current. If so, the registers on the interrupt stack are copied into the TCB and the status of the thread is set to READY.

    A new thread is selected, and is made running.

    Sleeping thread set to ready 
    on completion of read.
    
           TCB          TCB
         +-----+      +-----+     
    ---->|  +-------->|  +--------> ... 
         +-----+      +-----+ 
         |     |      |     | 
         +-----+      +-----+ 
         |READY|      |SLEEP|<---+
         +-----+      +-----+    |
         |     |      |     |    |
           ...          ...
         |     |      |     |    |
         +-----+      +-----+    |
         |     |      |     |    |
         +-----+      +-----+    | send signal
         |     |      |     |    |<=== (2)
         +-----+      +-----+    |
                                 |
          complete read          |
    (1) ===+                 +---|---+
           V                 |   +   |
        +--------------------+-------+
        | target of read data buffer |
        +----------------------------+
                          
    
  4. Process wait: Some calls byt the thread to a kernel will cause the thread to wait while the called is serviced. For instance, read from a disk will wait the thread until the read is completed. Threads in the wait state will not be considered for transition to the running state. When the wait is completed, the thread will be placed into the ready state and is again a candidate for running.

    The return to ready will be event driven. The satisfaction of the request upon which the thread waits will be associated with some interrupt. For example, in the case of a disk read wait, with the interrupt from the disk control signalling it has finished the read and is ready for a new read request.

    The read is completed by copying the requested disk block into a kernel disk buffer. Associated with this buffer is a pointer to the TCB waiting on the completion of the disk read. As part of the interrupt the pointer will be followed, and the state of the TCP referenced is updated.

  5. Process zombie: When all thread of a process have completed, the process state is set to ZOMBIE. The zombie process can be reaped by the parent process of the process, or by the operating system. Once reaped, the kernel data structures reserved for the process are unlinked from their lists and returned to the free pool.

    The point of the zombie is to allow the parent process to request the exit status of the process. If a process is waiting on child death, its interest is registered so that it can be set to ready, by following the parent pointer of the process moving to a zombie state to update the parent's status.

    If ever a process goes into a zombie state, its child processes are orphans. They must be reparented to the parent of the parent. Process with PID 1 is the ancestor of all processes. And it cannot exit.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

Author: Burton Rosenberg
Created: 16 September 2019
Last Update: 3 October 2019