Question
/* -------------------------- loader.c ----------------------- */ /* This is the shell for developing the loader cpu and printer */ /* for csc 389 project */ #include
/* -------------------------- loader.c ----------------------- */
/* This is the shell for developing the loader cpu and printer */
/* for csc 389 project */
#include
#include
#include
#include
#include
#include
#include
#include
#include "semshm.c"
#define NUM_OF_SEMS 8 /* the number of sems to create */
#define OK_TO_LOAD0 0
#define OK_TO_LOAD1 1
#define OK_TO_EXEC0 2
#define OK_TO_EXEC1 3
#define OK_TO_SET_OUTPUT0 4
#define OK_TO_SET_OUTPUT1 5
#define OK_TO_PRINT0 6
#define OK_TO_PRINT1 7
#define HOWMANY_PROCESSES 3
#define HOWMANY_JOBS 2
#define TRUE 1
#define FALSE 0
int my_semid, my_shrmemid; /* semaphore id and shared memory ids */
int my_key; /* key used to get shared memory */
int my_semval;
char *my_shrmemaddr; /* address of shared memory */
typedef struct _pcb
{int start_loc, num_instructions, output_loc;}
pcb_type;
typedef struct _mem
{char operation; int operand1, operand2, result;}
memory_type;
pcb_type *pcbs;
memory_type *memory;
int *load_job, *print_job,size_of_memory, s, i;
/* functions to be invoked later */
void P(); /* acquire semaphore */
void V(); /*release semaphore */
static void semcall(); /* call semop */
void init_sem(); /* initialize semaphores */
void remove_shrmem(); /* remove shared memory */
void remove_sem(); /* remove semaphores */
void driver(); /* driver for forking processes */
void loader();
void cpu();
void printer();
void execute_memory();
void print_memory();
int fill_memory();
main (int argc, char *argv[])
{ /* this program uses semaphores and shared memory. Semaphores are
used to protect the shared memory which serves as a message area
for and sender and receiver process */
int i ;
setbuf(stdout, NULL);
/* get semaphore id and a given number of semaphores */
if ((my_semid = semtran(NUM_OF_SEMS)) != -1)
{
/* initialize the semaphores */
init_sem(my_semid,OK_TO_LOAD0, 1);
init_sem(my_semid,OK_TO_LOAD1, 1);
init_sem(my_semid,OK_TO_EXEC0, 0);
init_sem(my_semid,OK_TO_EXEC1, 0);
init_sem(my_semid,OK_TO_SET_OUTPUT0, 1);
init_sem(my_semid,OK_TO_SET_OUTPUT1, 1);
init_sem(my_semid,OK_TO_PRINT0, 0);
init_sem(my_semid,OK_TO_PRINT1, 0);
}
/* get shared memory segement id and attach it to my_shrmemaddr */
size_of_memory = N*sizeof(*load_job) + 2*sizeof(*print_job) +
4*sizeof(*pcbs) + 40 * sizeof(*memory);
if ((get_attach_shrmem(size_of_memory,&my_shrmemaddr,&my_shrmemid)) != -1)
/* connect to shared memory at my_shrmemaddr */
load_job = (int *) my_shrmemaddr;
print_job = load_job + 2;
pcbs = (pcb_type *) (print_job + 2);
memory = (memory_type *) (pcbs + 4);
/* call driver to do the work of forking senders and receivers */
driver();
/* wait until all processes have completed their work */
for (i = 1; i
printf("The End. ");
remove_sem(my_semid); /* remove the semaphores */
remove_shrmem(my_shrmemid, my_shrmemaddr); /* remove the shared memory */
exit(0);
} /* end of main */
void driver() /* driver to fork processes to handle the work */
{
int pid;
if (( pid = fork() ) == -1) syserr("fork");
if ( pid == 0 )
{
loader();
exit(0);
}
if (( pid = fork() ) == -1) syserr("fork");
if ( pid == 0 )
{
cpu();
exit(0);
}
if (( pid = fork() ) == -1) syserr("fork");
if ( pid == 0 )
{
printer();
exit(0);
}
} /* end of driver */
void loader()
{
FILE *fid;
int memory_to_load, current_job, more_jobs, job_read;
if ((fid = fopen (inputfile, "r")) == 0)
{
puts ("Unable to open file for reading.");
exit(0);
}
more_jobs = 2;
current_job = 0;
while (more_jobs)
{
if (current_job == 0)
{
P(my_semid, OK_TO_LOAD0);
memory_to_load = 0;
pcbs[current_job].start_loc = 0;
pcbs[current_job].output_loc = 20;
pcbs[current_job].num_instructions = 0;
job_read = fill_memory(fid, memory_to_load);
if (job_read != 4)
{
more_jobs = more_jobs - 1;
load_job[current_job] = -1;
}
else
load_job[current_job] = 1;
V(my_semid, OK_TO_EXEC0);
}
else
{
P(my_semid, OK_TO_LOAD1);
memory_to_load = 10;
pcbs[current_job].start_loc = 10;
pcbs[current_job].output_loc = 30;
pcbs[current_job].num_instructions = 0;
job_read = fill_memory(fid, memory_to_load);
if (job_read != 4)
{
more_jobs = more_jobs - 1;
load_job[current_job] = -1;
}
else
load_job[current_job] = 1;
V(my_semid, OK_TO_EXEC1);
}
current_job = (current_job + 1) % 2;
} /* end while more_jobs */
fclose(fid);
return;
} /* end of load */
int fill_memory (FILE *fid, int memory_to_fill)
{
int opcode_ok, end_of_job, bad_instruction, operand1, operand2, elements_read, current_pcb;
char opcode, cr;
if (memory_to_fill == 0)
current_pcb = 0;
else
current_pcb = 1;
elements_read = TRUE;
end_of_job = FALSE;
while (elements_read )
{
elements_read = fscanf (fid, "%c %d %d%c", &opcode, &operand1, &operand2,&cr);
if (elements_read != 4)
{
return(elements_read);
}
else
{
switch (opcode)
{
case '+':
opcode_ok = TRUE;
break;
case '-':
opcode_ok = TRUE;
break;
case '*':
opcode_ok = TRUE;
break;
case '/':
opcode_ok = TRUE;
break;
case '%':
opcode_ok = TRUE;
break;
default :
if (opcode == '?')
{
bad_instruction = FALSE;
end_of_job = TRUE;
}
else
{
end_of_job = FALSE;
opcode_ok = FALSE;
bad_instruction = TRUE;
};
} /* end of switch */
} /* end of else elements read was 4 */
if (end_of_job == TRUE)
return(elements_read);
pcbs[current_pcb].num_instructions = pcbs[current_pcb].num_instructions + 1;
memory[memory_to_fill].operation = opcode;
memory[memory_to_fill].operand1 = operand1;
memory[memory_to_fill].operand2 = operand2;
memory_to_fill = memory_to_fill + 1;
} /* end of while for fill memory */
} /* end of fill memory */
void cpu()
{
int memory_to_execute, current_job, where_to_output, memory_to_output, more_jobs;
current_job = 0;
more_jobs = 2;
while (more_jobs)
{
if (current_job == 0)
{
P(my_semid, OK_TO_EXEC0);
if (load_job[current_job] == -1)
{
more_jobs = more_jobs -1;
P(my_semid, OK_TO_SET_OUTPUT0);
print_job[current_job] = -1;
V(my_semid, OK_TO_LOAD0);
V(my_semid, OK_TO_PRINT0);
}
else
{
execute_memory(current_job);
P(my_semid, OK_TO_SET_OUTPUT0);
pcbs[current_job + 2] = pcbs[current_job];
memory_to_output = pcbs[current_job + 2].start_loc;
where_to_output = pcbs[current_job + 2].output_loc;
for (i = 1; i
{
memory[where_to_output] = memory[memory_to_output];
memory_to_output = memory_to_output + 1;
where_to_output = where_to_output + 1;
}
load_job[current_job] = 0;
print_job[current_job] = 1;
V(my_semid, OK_TO_LOAD0);
V(my_semid, OK_TO_PRINT0);
} /* end for else for load job[current_job] != -1 */
}
else /* current_job != 0 */
{
P(my_semid, OK_TO_EXEC1);
if (load_job[current_job] == -1)
{
more_jobs = more_jobs -1;
P(my_semid, OK_TO_SET_OUTPUT1);
print_job[current_job] = -1;
V(my_semid, OK_TO_LOAD1);
V(my_semid, OK_TO_PRINT1);
}
else
{
execute_memory(current_job);
P(my_semid, OK_TO_SET_OUTPUT1);
pcbs[current_job + 2] = pcbs[1];
memory_to_output = pcbs[current_job + 2].start_loc;
where_to_output = pcbs[current_job + 2].output_loc;
for (i = 1; i
{
memory[where_to_output] = memory[memory_to_output];
memory_to_output = memory_to_output + 1;
where_to_output = where_to_output + 1;
}
load_job[current_job] = 0;
print_job[current_job] = 1;
V(my_semid, OK_TO_LOAD1);
V(my_semid, OK_TO_PRINT1);
} /* end for else for load job[1] != -1 */
}
current_job = (current_job + 1) % HOWMANY_JOBS;
} /* end while more jobs */
} /* end of cpu */
void execute_memory(int current_job)
{
int memory_to_execute, i;
if (current_job == 0)
memory_to_execute = 0;
else
memory_to_execute =10;
for ( i = 1; i
{
switch (memory[memory_to_execute].operation)
{
case '+':
memory[memory_to_execute].result =
memory[memory_to_execute].operand1 +
memory[memory_to_execute].operand2 ;
break;
case '-':
memory[memory_to_execute].result =
memory[memory_to_execute].operand1 -
memory[memory_to_execute].operand2 ;
break;
case '*':
memory[memory_to_execute].result =
memory[memory_to_execute].operand1 *
memory[memory_to_execute].operand2 ;
break;
case '/':
memory[memory_to_execute].result =
memory[memory_to_execute].operand1 /
memory[memory_to_execute].operand2 ;
break;
case '%':
memory[memory_to_execute].result =
memory[memory_to_execute].operand1 %
memory[memory_to_execute].operand2 ;
break;
} /* end of switch */
memory_to_execute = memory_to_execute + 1;
}
} /* end execute_memory */
void printer() /* print jobs */
{ else /* current_job != 0 */
{
P(my_semid, OK_TO_EXEC1);
if (load_job[current_job] == -1)
{
more_jobs = more_jobs -1;
P(my_semid, OK_TO_SET_OUTPUT1);
print_job[current_job] = -1;
V(my_semid, OK_TO_LOAD1);
V(my_semid, OK_TO_PRINT1);
}
else
{
execute_memory(current_job);
P(my_semid, OK_TO_SET_OUTPUT1);
pcbs[current_job + 2] = pcbs[1];
memory_to_output = pcbs[current_job + 2].start_loc;
where_to_output = pcbs[current_job + 2].output_loc;
for (i = 1; i
{
memory[where_to_output] = memory[memory_to_output];
memory_to_output = memory_to_output + 1;
where_to_output = where_to_output + 1;
}
load_job[current_job] = 0;
print_job[current_job] = 1;
V(my_semid, OK_TO_LOAD1);
V(my_semid, OK_TO_PRINT1);
} /* end for else for load job[1] != -1 */
}
current_job = (current_job + 1) % HOWMANY_JOBS;
} /* end while more jobs */
} /* end of cpu */
void execute_memory(int current_job)
{
int memory_to_print, current_print_job, more_print_jobs;
current_print_job = 0;
more_print_jobs = 2;
while (more_print_jobs)
{
if (current_print_job == 0)
{
P(my_semid, OK_TO_PRINT0);
if (print_job[current_print_job] == -1)
{
more_print_jobs = more_print_jobs - 1;
V(my_semid, OK_TO_SET_OUTPUT0);
}
else
{
memory_to_print = 20;
print_memory(current_print_job, memory_to_print);
print_job[current_print_job] = 0;
V(my_semid, OK_TO_SET_OUTPUT0);
}
} /* end for current_print_job == 0 */
else
{
P(my_semid, OK_TO_PRINT1);
if (print_job[current_print_job] == -1)
{
more_print_jobs = more_print_jobs - 1;
V(my_semid, OK_TO_SET_OUTPUT1);
}
else
{
memory_to_print = 30;
print_memory(current_print_job, memory_to_print);
print_job[current_print_job] = 0;
V(my_semid, OK_TO_SET_OUTPUT1);
}
} /* end of else for current_print_job */
current_print_job = (current_print_job + 1) % 2;
} /* end of while */
} /* end of printer */
void print_memory(int current_print_job, int memory_to_print)
{
int i;
printf("output for current job %d ", current_print_job);
for (i = 1; i
{
printf("%c %d %d %d ",
memory[memory_to_print].operation,
memory[memory_to_print].operand1,
memory[memory_to_print].operand2,
memory[memory_to_print].result );
memory_to_print = memory_to_print + 1;
}
printf(" ");
} /* end of print_memory */
~
3. Modify the loader.c" source code to satisfy the following two requirements: i. Use command-line arguments (i.e., main(int argc, char *argv[])) in the format: a.out N inputfile where a.out is the executable filename; N is the number of concurrent jobs, 1 sN S 10; inputfile is the filename of the input file. ii. Use the malloc() and free() functions to dynamically allocate the necessary semaphores and memory locations based on the number of concurrent computation jobs. For example, the following table shows some examples of the necessary semaphore numbers, memory size and location arrangement as the value of N changes. NNumber ofTotal Memory Semaphores Location Sizefor Loading Memory Location Arrangement 4 8 20 40 0-9 for job0 0-19 for Printing 10 19 for job0 20- 39 0-9 for job0 10 - 19 for job1 20 29 for job0 30 - 39 for job1 3 12 60 0- 29 30- 59 0-9 for job0 10 - 19 for job1 20- 29 for job2 30 - 39 for job0 40 - 49 for job1 50 -59 for job2Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started