Presentation is loading. Please wait.

Presentation is loading. Please wait.

Today’s agenda Lab 1 Module 4: Process Management

Similar presentations


Presentation on theme: "Today’s agenda Lab 1 Module 4: Process Management"— Presentation transcript:

1 Today’s agenda Lab 1 Module 4: Process Management
Read Chapter 2 (2.8, 2.9) Semaphores: wait(), signal(),semcreate(),semdelete(), … Module 4: Process Management Chap 4: List and Queue Manipulation CS354-Fall2018

2 Lab 1: Producer-Consumer
Read Chapter 2.8, 2.9 ex4.c, ex5.c and ex6.c two concurrent processes that each increments a shared integer n Race condition (how to handle it?) CS354-Fall2018

3 What if producer-consumer?
write integer n read consumer CS354-Fall2018

4 How to synchronize independent processes?
Semaphore abstraction wait() signal() semcreate() semdelete() Two semaphores: One on which the consumer waits One on which the producer waits CS354-Fall2018

5 Ex5.c /* ex5.c - main, prod2, cons2 */ # include <xinu.h>
void prod2(sid32,sid32), cons2(sid32,sid32); int32 n = 0; /* variable n has initial value zero */ /* * main - producer and consumer processes sychronizaed with semaphores * */ void main(void) { sid32 produced, consumed; consumed = semcreate(0); produced = semcreate(1); resume (create (cons2, 1024, 20, "cons", 2, consumed, produced)); resume (create (prod2, 1024, 20, "prod", 2, consumed, produced)); } CS354-Fall2018

6 * prod2 - Increment n 2000 times, waiting for it to be consumed.
/* * prod2 - Increment n 2000 times, waiting for it to be consumed. * */   void prod2( sid32 consumed, sid32 produced) { int32 i; for (i=1; i<=2000; i++){ wait(consumed); n++; signal(produced); } /* * cons2 - print n 2000 times, waiting for it to be produced * */ void cons2( sid32 consumed, sid32 produced) { int32 i; for (i=1; i<=2000; i++){ wait(produced); printf("n is %d \n", n); signal(consumed); } CS354-Fall2018

7 Semaphores: Mutual Exclusion
Only one of two executing processes obtains access to a shared resource what if not n? but a shared list? Accessed by many processes shared[n++] = item; /* n is updated over time */ CS354-Fall2018

8 # include <xinu.h>
/* ex6.c - additem */ # include <xinu.h> sid32 mutex; /* assume initialized with semcreate */ int32 shared[100]; /* An array shared by many processes */ int32 n = 0; /* Count of items in the array */ int32 n = 0; /* variable n has initial value zero */ /* * addiotem - obtain exclusive use of array shared and add an item to it. * */ void additem (int32 item) { wait(mutex); shared[n++] = item; signal(mutex); } CS354-Fall2018

9 Lab1 https://www.cs.purdue.edu/homes/c s354/lab1/ Mutual exclusion
Circled buffer Producer: insert into the buffer Consumer: extract from the buffer Multiple producers and consumers CS354-Fall2018

10 Switch to Module 4 CS354-Fall2018

11 Chapter 4: List and Queue Manipulation
A linked list A single data structure A single set of nodes used by all levels of OS to maintain list of processes CS354-Fall2018

12 Doubly-linked List previous process key next Head Tail x - 4 2 - x 25
14 greater than max key Smaller than max key CS354-Fall2018

13 In Xinu a fixed upper bound on # of processes: NPROC
Relative pointer: each pointer occupies 4 bytes (32-bit system), address will be list[n] (continuous memory address) Implicit data structure: queue table queue.h, getitem.c, queue.c (see the codes) CS354-Fall2018

14 /* queue.h - firstid, firstkey, isempty, lastkey, nonempty */
/* Queue structure declarations, constants, and inline functions */ /* Default # of queue entries: 1 per process plus 2 for ready list plus */ /* for sleep list plus 2 per semaphore */ #ifndef NQENT #define NQENT (NPROC NSEM + NSEM) #endif #define EMPTY (-1) /* Null value for qnext or qprev index */ #define MAXKEY 0x7FFFFFFF /* Max key that can be stored in queue */ #define MINKEY 0x /* Min key that can be stored in queue */ struct qentry { /* One per process plus two per list */ int32 qkey; /* Key on which the queue is ordered */ qid16 qnext; /* Index of next process or tail */ qid16 qprev; /* Index of previous process or head */ }; extern struct qentry queuetab[]; /* Inline queue manipulation functions */ #define queuehead(q) (q) #define queuetail(q) ((q) + 1) #define firstid(q) (queuetab[queuehead(q)].qnext) #define lastid(q) (queuetab[queuetail(q)].qprev) #define isempty(q) (firstid(q) >= NPROC) #define nonempty(q) (firstid(q) < NPROC) #define firstkey(q) (queuetab[firstid(q)].qkey) #define lastkey(q) (queuetab[ lastid(q)].qkey) /* Inline to check queue id assumes interrupts are disabled */ #define isbadqid(x) (((int32)(x) < 0) || (int32)(x) >= NQENT-1) CS354-Fall2018

15 /* getitem.c - getfirst, getlast, getitem */ #include <xinu.h>
#include <xinu.h> /* * getfirst - Remove a process from the front of a queue * */ pid32 getfirst( qid16 q /* ID of queue from which to */ ) /* Remove a process (assumed */ /* valid with no check) */ { pid32 head; if (isempty(q)) { return EMPTY; } head = queuehead(q); return getitem(queuetab[head].qnext); /* * getlast - Remove a process from end of queue * */ pid32 getlast( qid16 q /* ID of queue from which to */ ) /* Remove a process (assumed */ /* valid with no check) */ { pid32 tail; if (isempty(q)) { return EMPTY; } tail = queuetail(q); return getitem(queuetab[tail].qprev);  /* * getitem - Remove a process from an arbitrary point in a queue * */ pid32 getitem( pid32 pid /* ID of process to remove */ ) { pid32 prev, next; next = queuetab[pid].qnext; /* Following node in list */ prev = queuetab[pid].qprev; /* Previous node in list */ queuetab[prev].qnext = next; queuetab[next].qprev = prev; return pid; } CS354-Fall2018

16 FIFO Queue Manipulation
First-In-First-Out (FIFO): queue.c enqueue() and dequeue() CS354-Fall2018

17 #include <xinu.h>
struct qentry queuetab[NQENT]; /* Table of process queues */ /* * enqueue - Insert a process at the tail of a queue * */ pid32 enqueue( pid32 pid, /* ID of process to insert */ qid16 q /* ID of queue to use */ ) { int tail, prev; /* Tail & previous node indexes */ if (isbadqid(q) || isbadpid(pid)) { return SYSERR; } tail = queuetail(q); prev = queuetab[tail].qprev; queuetab[pid].qnext = tail; /* Insert just before tail node */ queuetab[pid].qprev = prev; queuetab[prev].qnext = pid; queuetab[tail].qprev = pid; return pid; /* * dequeue - Remove and return the first process on a list * */ pid32 dequeue( qid16 q /* ID queue to use */ ) { pid32 pid; /* ID of process removed */ if (isbadqid(q)) { return SYSERR; } else if (isempty(q)) { return EMPTY; } pid = getfirst(q); queuetab[pid].qprev = EMPTY; queuetab[pid].qnext = EMPTY; return pid; CS354-Fall2018

18 How about Priority Queue?
FIFO is not the sole way Process manager may select from a set of processes the one with highest priority Priority: as a qkey in the list Queue sorted by qkey Delete(): easy (just delete it) Insert(): searches for the one that is just below qkey See insert.c CS354-Fall2018

19 insert.c /* * insert - Insert a process into a queue in descending key order * */ status insert( pid32 pid, /* ID of process to insert */ qid16 q, /* ID of queue to use */ int32 key /* Key for the inserted process */ ) { int16 curr; /* Runs through items in a queue*/ int16 prev; /* Holds previous node index */ …. /* ignored */ curr = firstid(q); while (queuetab[curr].qkey >= key) { curr = queuetab[curr].qnext; } /* Insert process between curr node and previous node */ prev = queuetab[curr].qprev; /* Get index of previous node */ queuetab[pid].qnext = curr; queuetab[pid].qprev = prev; queuetab[pid].qkey = key; queuetab[prev].qnext = pid; queuetab[curr].qprev = pid; return OK; /* insert.c - insert */ #include <xinu.h> /* * insert - Insert a process into a queue in descending key order * */ status insert( pid32 pid, /* ID of process to insert */ qid16 q, /* ID of queue to use */ int32 key /* Key for the inserted process */ ) { int16 curr; /* Runs through items in a queue*/ int16 prev; /* Holds previous node index */ if (isbadqid(q) || isbadpid(pid)) { return SYSERR; } curr = firstid(q); while (queuetab[curr].qkey >= key) { curr = queuetab[curr].qnext; /* Insert process between curr node and previous node */ prev = queuetab[curr].qprev; /* Get index of previous node */ queuetab[pid].qnext = curr; queuetab[pid].qprev = prev; queuetab[pid].qkey = key; queuetab[prev].qnext = pid; queuetab[curr].qprev = pid; return OK; CS354-Fall2018

20 List Initialization? newqueue.c
/* * newqueue - Allocate and initialize a queue in the global queue table * */ qid16 newqueue(void) { static qid16 nextqid=NPROC; /* Next list in queuetab to use */ qid16 q; /* ID of allocated queue */ q = nextqid; if (q > NQENT) { /* Check for table overflow */ return SYSERR; } nextqid += 2; /* Increment index for next call*/ /* Initialize head and tail nodes to form an empty queue */ queuetab[queuehead(q)].qnext = queuetail(q); queuetab[queuehead(q)].qprev = EMPTY; queuetab[queuehead(q)].qkey = MAXKEY; queuetab[queuetail(q)].qnext = EMPTY; queuetab[queuetail(q)].qprev = queuehead(q); queuetab[queuetail(q)].qkey = MINKEY; return q; List Initialization? newqueue.c CS354-Fall2018


Download ppt "Today’s agenda Lab 1 Module 4: Process Management"

Similar presentations


Ads by Google