In: Computer Science
Please SOLVE EXERCISE 4.20
Programming Exercise 3.20 required you to design a PID manager that allocated a unique process identifier to each process.
Exercise 4.20 requires you to modify your solution from Exercise 3.20 by writing a program that creates a number of threads that requested and released process identifiers. Modify your solution to Exercise 4.20 by ensuring that the data structure used to represent the availability of process identifiers is safe from race conditions. Use Pthreads mutex locks.
Please SOLVE EXERCISE 4.20
My Programming Exercise 3.20)
package com.company;
import java.util.HashMap;
/*
dip manager manages process identifiers, which are unique.
Several active processes can not have same pid.
It creates unique pid, which is assigned to ti.
When process completes execution pid is returned to pdd manager.
pdd manager reassigns this pid.
--first method:
creates and initializes the map in order to maintain the list of available pids.
--second method:
finds next avialable pid and assigns them to active processes
--third method:
releases old identifiers by making them available again for new processes.
*/
public class PID_MAP {
/*
Variables that will specify the range of pid values
basically it says that process identifiers are constant
integers (final key word) between 300 and 500.
*/
public static final Integer MIN_PID = 300;
public static final Integer MAX_PID = 5000;
/*
variables that identify availability of a particular process identifier
with 0 being available and 1 being currently in use
*/
public Integer available = 0;
public Integer notAvailable = 1;
/*
I decided to use hash map data structure named PID_map to represent the availability of process identifiers with Key/Value principle
*/
public HashMap PID_map;
/*
int allocate_map(void) - Creates and initializes a data structure for representing pids; returns -1 if unsuccessful and 1 if successful
This method allocates a hash map of possible pid-s.
The map has Key/Value principle.
Key is an Integer, Value is "available (0) /not available (1)" for allocation to an active process.
*/
public int allocate_map(){
//allocated map for certain capacity
PID_map = new HashMap(MAX_PID - MIN_PID + 1); //checks if system has enough resources to allocate a map of the capacity mentioned above
if(true) {
for (int i = MIN_PID; i <= MAX_PID; i++) {
PID_map.put(i, available); //values for all the keys are set to 0, because non of the process will be active if I do not allocate the map first.
}
}
else {
return -1; //if returns integer "-1" means hash map did not created, initialized and allocated successfully.
}
return 1; //if returns integer "1" means hash map successfully created, initialized and allocated.
}
/*Process Synchronization means sharing system resources by processes in a such a way that, Concurrent access to shared data is handled thereby minimizing
the chance of inconsistent data. Thats why we use key word Synchronized.
*/
/*
int allocate_pid(void) - Allocates and returns a pid; returns -1 if if unable to allocate a pid (all pids are in use)
*/
public int allocate_pid(){
for (Integer i = MIN_PID; i <= MAX_PID; i++){ //traverses through the map to find available pid
if (PID_map.get(i).equals(available)){ //once the available process identifier is found
PID_map.put(i,notAvailable); //the process identifier is updated from avialeble to unavialable
return i; //returns the "new unavailable pid"
}
}
return -1; //returs -1 if all process identifiers are in use.
}
/*
void release_pid(int_pid) - Releases a pid.
*/
public void release_pid(Integer k){ // method releases used process identifier which is passes as parameter-Integer K
if(k > MAX_PID || k < MIN_PID){ //double checks if Pid is valid
System.out.println("Error! not valid identifier"); //if not system notifies that its invalid process identifier
}
PID_map.put(k,available); //if it is valid pid, it becomes released and the pid can be used by another process. It is set to available (0)
}
}
/*
DELETED key word SYNCHRONIZED for acllocate_pid() and release_pid() functions
*/
*****make sure you are running it on linux machine compile as >gcc pid.c -o pid -lpthread run as >./pid *****/ #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<time.h> #include<pthread.h> #include<semaphore.h> #define MIN_PID 300 #define MAX_PID 5000 #define NUM_THREADS 100 #define YES 0 #define NO 1 sem_t SEM; struct PidTable{ int PID; int isAvailable; }*pId; int allocate_map(){ int i; pId=(struct PidTable *)calloc((MAX_PID-MIN_PID+1),sizeof(struct PidTable)); if(pId==NULL) return -1; pId[0].PID=MIN_PID; pId[0].isAvailable=YES; for( i=1;i<MAX_PID-MIN_PID+1;i++){ pId[i].PID=pId[i-1].PID+1; pId[i].isAvailable=YES; } return 1; } int allocate_pid(){ int i ; for( i=0;i<MAX_PID-MIN_PID+1;i++){ if(pId[i].isAvailable==YES){ pId[i].isAvailable=NO; return pId[i].PID; } } return -1; } void release_pid(int pid){ pId[pid-MIN_PID].isAvailable=YES; } void *processStart(void *id){ //long tid=(long)id; int pid,executionTime; sem_wait(&SEM); pid=allocate_pid(); usleep(10000); sem_post(&SEM); if(pid!=-1){ //printf("Thread %ld runnning....\n",tid); printf("New Process Allocated Pid= %d \n",pid); executionTime=rand()%10; sleep(executionTime); printf("Process %d releasing pid \n",pid); release_pid(pid); } pthread_exit(NULL); } int main(){ allocate_map(); srand(time(NULL)); void *status;int i; int ret=0;pthread_t thread[100]; sem_init(&SEM,0,1); for(i=0;i<NUM_THREADS;i++){ ret=pthread_create(&thread[i],NULL,processStart,(void *)(i+1)); if(ret){printf("Error creating thread\n");exit(1);} } for(i=0; i<NUM_THREADS; i++) { ret = pthread_join(thread[i], &status); if (ret) { printf("ERROR; return code from pthread_join() is %d\n", ret); exit(-1); } } return 0; } OUTPUT: