C

A process scheduling algorithms in C


Requirement:

In the system, all the processes are grouped into six priority classes, ranged from 1 to 6, according to their membership status. A larger priority number indicates a higher priority. To maximize the system service performance, you are required to implement a scheduling algorithm using multi-level queue strategy with three queues: : a high priority Queue 1 (processes with priority number 6 and 5), a medium priority Queue 2 (priority number 4 and 3) and a low priority Queue 3 (priority number 2 and 1). Queue 1 has absolute priority over Queue 2 and Queue 3, and Queue 2 has absolute priority over Queue 3. In other words, process requests in Queue 2 will be processed only if there is no process in Queue 1, and process requests in Queue 3 will be processed only if no process is in Queue 1 and Queue 2. There are two thresholds (=5, 3) that are used to determine whether a process should remain in Queue 1 (priority ≥ 5), in Queue 2 (3 ≥ priority < 5) and Queue 3 (priority < 3), respectively.

Detailed actions in these three queues are listed below:

Queue 1:

This is the high priority queue. processes in this queue are treated in the way of combined Highest Priority First (HPF) and Round Robin. That is, select the highest priority process (processes with the same priority are selected in their arrival order), and process this process’s request for a time quantum of 5 time units non-preemptively, then move this process to the end of a sub-queue (in same priority) of Queue 1. The priority of a process in this queue is decreased by one every 5 runs of this process, i.e. once having been serviced 25 time units overall in Queue 1.

Queue 2 and Queue 3:

These are the medium/low priority queue. processes in these queues are handled in Round Robin. That is, select the process with First Come First Serve, and process this process’s request for a time quantum of 10 time units for Queue 2 and 20 time units for Queue 3 preemptively as described below, then move this process to the end of its queue. If the priority of a process in these queues reaches the threshold (5 in Queue 2 and 3 in Queue 3) by the following Aging mechanism, that process is promoted from Queue 2 to Queue 1 (or from Queue 3 to Queue 2).

There’s one more thing need to be noted:

The priority of a process in Queue 2 is decreased by one every 2 runs of this process, i.e. once having been serviced 20 time units overall.

Preemption:

Once a running process in Queue 2 (or Queue 3) is interrupted by a new arrival process from Queue 1 (or from Queue 2), this process will leave its time quantum immediately and moved to the end of its queue.

Aging:

Because Queue 1 has priority over Queue 2 and Queue 3, and the HPF strategy is applied, starvation may occur. That is, some processes in Queue 2 and Queue 3 may never get to run because there is always a process with higher priority in Queue 1. To solve the starvation issue, you must implement a mechanism which ages each process. This need not be done every time a process run as this will slow the system down, but say once after every 7 process runs. That is, if a process has waited 7 runs of other processes since its last run, its priority number will be increased by one. In this way, the priority of each process in Queue 2 and Queue 3 increases gradually in proportion to the waiting time since the last run.

Note:

If at time t, there are three processes with the same priority: a new arrival process A to Queue 2, a process B moved to the end of Queue 2, a promoted process C from Queue 2 to Queue 2, and a Process D degrade to Queue2, their order will be A →D→ B → C. Same rule applies to Queue 1 and 3 regardless of the priority.

Input

Each customer is identified by a line in the input file. The line describes the customer ID, arrival time, priority, age and the total time units required. For example s1 3 1 0 50 describes a customer s1 who arrived at time 3 with priority 1 and age 0, and requires 50 time units.

Output

The output provides information of each customer execution. The line starts with the customer ID, priority, arrival and termination times, ready time (the first time the system processes its request) and durations of running and waiting.


Sample input 1:

a0 0 3 0 10
a1 0 6 0 9
a2 0 5 0 10
a3 0 4 0 8
a4 0 1 0 30
a5 0 6 0 6

Expected output 1:

Index Priority Arrival End Ready CPU_Time Waiting
a1 6 0 14 0 9 5
a5 6 0 15 5 6 4
a2 5 0 25 15 10 0
a0 3 0 35 25 10 0
a3 4 0 43 35 8 0
a4 2 0 73 43 30 0


Sample input 2:

b0 0 3 0 10
b1 0 6 0 16
b2 0 5 0 14
b3 0 6 0 20
b4 0 1 0 20
b5 5 3 0 10
b6 0 2 0 20
b7 0 4 0 19
b8 0 3 0 20
b9 10 6 0 18
b10 15 2 0 9

Expected output 2:

Index Priority Arrival End Ready CPU_Time Waiting
b1 6 0 41 0 16 25
b3 6 0 51 5 20 26
b9 6 10 54 15 18 21
b2 5 0 78 54 14 10
b7 5 0 102 59 19 24
b0 5 0 107 83 10 14
b5 5 5 117 93 10 14
b8 5 0 132 88 20 24
b10 5 15 151 137 9 5
b6 5 0 156 122 20 14
b4 5 0 176 156 20 0


Sample input 3:

c1 28 6 0 1
c2 0 3 0 25
c3 0 5 0 26
c5 0 3 0 10

Expected output 3:

Index Priority Arrival End Ready CPU_Time Waiting
c1 6 28 29 28 1 0
c5 3 0 39 29 10 0
c3 4 0 40 0 26 14
c2 2 0 62 25 25 12


Sample input 4:

d0 0 4 0 10
d1 0 3 0 20
d2 0 5 0 100
d3 20 5 0 30
d4 20 4 0 20
d5 40 3 0 15
d6 40 6 0 40
d7 80 2 0 80
d8 160 1 0 10

Expected output 4:

Index Priority Arrival End Ready CPU_Time Waiting
d0 5 0 100 70 10 20
d6 5 40 135 40 40 55
d4 5 20 150 75 20 55
d3 5 20 160 20 30 110
d1 5 0 175 105 20 50
d5 5 40 185 140 15 30
d8 2 160 275 265 10 0
d2 2 0 305 0 100 205
d7 2 80 325 185 80 60


Sample input 5:

s0 0 3 0 10
s1 0 6 0 20
s2 0 5 0 11
s3 0 6 0 20
s4 67 2 0 25
s5 5 4 0 1
s6 0 2 0 5
s7 0 4 0 28
s8 0 3 0 20
s9 45 5 0 6
s10 103 3 0 2

Expected output 5:

Index Priority Arrival End Ready CPU_Time Waiting
s1 6 0 35 0 20 15
s3 6 0 40 5 20 15
s5 5 5 61 60 1 0
s9 5 45 67 50 6 11
s2 5 0 68 40 11 17
s0 5 0 93 73 10 10
s8 5 0 113 78 20 15
s6 5 0 118 113 5 0
s10 3 103 120 118 2 0
s7 4 0 123 45 28 50
s4 2 67 148 123 25 0


Detailed Debug:  https://levyhsu.com/wp-content/uploads/2018/09/detailed_ouputs.zip


Main.C

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

//A larger priority number indicates a higher priority.
/*
For status:
5 : new joined (just arrived)
4 : being downgraded
3 : normal operating status
2 : being upgraded
*/

typedef struct Processes
{
    char firstchar;
    int realindex;
    int original_arrival_time;
    int arrival_time;
    int priority;
    int age;
    int total_time_units_required;
    int time_executed;
    int time_executed_in_Q1;
    int time_executed_in_Q2;
    int time_executed_in_Q3;
    int time_waited;
    int first_time;
    int first_time_flag;
    int end_time;
    int status;
} Process;

struct Node
{
    int index;
    struct Node *next;
    struct Node *prev;
};

/* Given a reference (pointer to pointer) to the head of a list
   and an int, inserts a new node on the front of the list. */
void Push_Head(struct Node **head_ref, int new_data)
{
    /* 1. allocate node */
    struct Node *new_node = (struct Node *)malloc(sizeof(struct Node));

    /* 2. put in the data  */
    new_node->index = new_data;

    /* 3. Make next of new node as head and previous as NULL */
    new_node->next = (*head_ref);
    new_node->prev = NULL;

    /* 4. change prev of head node to new node */
    if ((*head_ref) != NULL)
        (*head_ref)->prev = new_node;

    /* 5. move the head to point to the new node */
    (*head_ref) = new_node;
}

/* Given a reference (pointer to pointer) to the head
   of a DLL and an int, appends a new node at the end  */
void Push_Back(struct Node **head_ref, int new_data)
{
    /* 1. allocate node */
    struct Node *new_node = (struct Node *)malloc(sizeof(struct Node));

    struct Node *last = *head_ref; /* used in step 5*/

    /* 2. put in the data  */
    new_node->index = new_data;

    /* 3. This new node is going to be the last node, so make next of it as NULL*/
    new_node->next = NULL;

    /* 4. If the Linked List is empty, then make the new node as head */
    if (*head_ref == NULL)
    {
        new_node->prev = NULL;
        *head_ref = new_node;
        return;
    }

    /* 5. Else traverse till the last node */
    while (last->next != NULL)
        last = last->next;

    /* 6. Change the next of last node */
    last->next = new_node;

    /* 7. Make last node as previous of new node */
    new_node->prev = last;

    return;
}

void Remove_Process(struct Node **head_ref, struct Node *del)
{

    /* base case */
    if (*head_ref == NULL || del == NULL)
        return;

    /* If node to be deleted is head node */
    if (*head_ref == del)
        *head_ref = del->next;

    /* Change next only if node to be deleted is NOT the last node */
    if (del->next != NULL)
        del->next->prev = del->prev;

    /* Change prev only if node to be deleted is NOT the first node */
    if (del->prev != NULL)
        del->prev->next = del->next;

    /* Finally, free the memory occupied by del*/
    free(del);
}

/* Function to delete the node at the given position
   in the doubly linked list */
void Remove_Process_At_Given_Pos(struct Node **head_ref, int n)
{
    /* if list in NULL or invalid position is given */
    if (*head_ref == NULL || n < 0)
        return;

    if (n == 0)
    {
        Remove_Process(head_ref, *head_ref);
        return;
    }

    struct Node *current = *head_ref;
    int i;

    /* traverse up to the node at position 'n' from the beginning */
    for (int i = 1; current != NULL && i < n; i++)
        current = current->next;

    /* if 'n' is greater than the number of nodes in the doubly linked list */
    if (current == NULL)
        return;

    /* delete the node pointed to by 'current' */
    Remove_Process(head_ref, current);
}

//Always move Process with P6 ahead of process with P5
void Queue1_HPF(struct Node **Queue1, Process *Process[1000])
{
    struct Node *temp1 = *Queue1;
    int length = 0;
    while (temp1 != NULL)
    {
        length++;
        temp1 = temp1->next;
    }

    for (int i = 0; i < length; i++)
    {
        struct Node *temp2 = *Queue1;
        while (temp2->next != NULL)
        {
            if (Process[temp2->index]->priority == 5 && Process[temp2->next->index]->priority == 6)
            {
                int temp = temp2->index;
                temp2->index = temp2->next->index;
                temp2->next->index = temp;
            }
            temp2 = temp2->next;
        }
    }
}

// This function prints contents of linked list starting from the given node
void PrintQueue_Debug(struct Node **Queue1, struct Node **Queue2, struct Node **Queue3, Process *Process[1000], int timeline)
{

    printf("***************************\nThe last moment of Time(%d):\n", timeline + 1);

    puts("This is Queue 1:");
    printf("Index Arrival Prio   age  CPU_Time  T_E  T_W\n");
    struct Node *temp1 = *Queue1;
    while (temp1 != NULL)
    {
        printf("s%d", Process[temp1->index]->realindex);
        printf("%8d", Process[temp1->index]->arrival_time);
        printf("%6d", Process[temp1->index]->priority);
        printf("%7d", Process[temp1->index]->age);
        printf("%9d", Process[temp1->index]->total_time_units_required);
        printf("%6d", Process[temp1->index]->time_executed);
        printf("%6d\n", Process[temp1->index]->time_waited);
        temp1 = temp1->next;
    }

    puts("This is Queue 2:");
    printf("Index Arrival Prio   age  CPU_Time  T_E  T_W\n");
    struct Node *temp2 = *Queue2;
    while (temp2 != NULL)
    {
        printf("s%d", Process[temp2->index]->realindex);
        printf("%8d", Process[temp2->index]->arrival_time);
        printf("%6d", Process[temp2->index]->priority);
        printf("%7d", Process[temp2->index]->age);
        printf("%9d", Process[temp2->index]->total_time_units_required);
        printf("%6d", Process[temp2->index]->time_executed);
        printf("%6d\n", Process[temp2->index]->time_waited);
        temp2 = temp2->next;
    }

    puts("This is Queue 3:");
    printf("Index Arrival Prio   age  CPU_Time  T_E  T_W\n");
    struct Node *temp3 = *Queue3;
    while (temp3 != NULL)
    {
        printf("s%d", Process[temp3->index]->realindex);
        printf("%8d", Process[temp3->index]->arrival_time);
        printf("%6d", Process[temp3->index]->priority);
        printf("%7d", Process[temp3->index]->age);
        printf("%9d", Process[temp3->index]->total_time_units_required);
        printf("%6d", Process[temp3->index]->time_executed);
        printf("%6d\n", Process[temp3->index]->time_waited);
        temp3 = temp3->next;
    }
}

void PrintQueue_Final(struct Node **Queue_ENDED, Process *Process[1000])
{
    struct Node *temp = *Queue_ENDED;
    puts("Index	Priority	Arrival	End	Ready	CPU_Time	Waiting");
    while (temp != NULL)
    {
        printf("%c", Process[temp->index]->firstchar);
        printf("%d	", Process[temp->index]->realindex);
        printf("%d	", Process[temp->index]->priority);
        printf("%d	", Process[temp->index]->original_arrival_time);
        printf("%d	", Process[temp->index]->end_time);
        printf("%d	", Process[temp->index]->first_time);
        printf("%d	", Process[temp->index]->total_time_units_required);
        printf("%d	\n", Process[temp->index]->end_time - Process[temp->index]->first_time - Process[temp->index]->total_time_units_required);
        temp = temp->next;
    }
}

//If Process in Queue, return position, return -1 if not exist.
int Process_in_queue(struct Node **Queue, int pro_index)
{
    int position = 0;
    struct Node *temp = *Queue;
    while (temp != NULL)
    {
        if (pro_index == temp->index)
            return position;
        temp = temp->next;
        position++;
    }
    //Not Exist
    return -1;
}

void add_to_queue_1(struct Node **Queue, Process *Process[1000], int timeline, int Process_index, int priority)
{

    for (int i = 0; i < Process_index; i++)
    {
        if (Process[i]->arrival_time == timeline && Process[i]->priority == priority && Process[i]->status == 5 && Process_in_queue(Queue, i) == -1)
            Push_Back(Queue, i);
    }
    for (int i = 0; i < Process_index; i++)
    {
        if (Process[i]->arrival_time == timeline && Process[i]->priority == priority && Process[i]->status == 4 && Process_in_queue(Queue, i) == -1)
            Push_Back(Queue, i);
    }
    for (int i = 0; i < Process_index; i++)
    {
        if (Process[i]->arrival_time == timeline && Process[i]->priority == priority && Process[i]->status == 3 && Process_in_queue(Queue, i) == -1)
            Push_Back(Queue, i);
    }
    for (int i = 0; i < Process_index; i++)
    {
        if (Process[i]->arrival_time == timeline && Process[i]->priority == priority && Process[i]->status == 2 && Process_in_queue(Queue, i) == -1)
            Push_Back(Queue, i);
    }
}

void add_to_queue_23(struct Node **Queue, Process *Process[1000], int timeline, int Process_index, int priority)
{
    for (int i = 0; i < Process_index; i++)
    {
        if (Process[i]->arrival_time == timeline && (Process[i]->priority == priority || Process[i]->priority == priority + 1) && Process[i]->status == 5 && Process_in_queue(Queue, i) == -1)
            Push_Back(Queue, i);
    }
    for (int i = 0; i < Process_index; i++)
    {
        if (Process[i]->arrival_time == timeline && (Process[i]->priority == priority || Process[i]->priority == priority + 1) && Process[i]->status == 4 && Process_in_queue(Queue, i) == -1)
            Push_Back(Queue, i);
    }
    for (int i = 0; i < Process_index; i++)
    {
        if (Process[i]->arrival_time == timeline && (Process[i]->priority == priority || Process[i]->priority == priority + 1) && Process[i]->status == 3 && Process_in_queue(Queue, i) == -1)
            Push_Back(Queue, i);
    }
    for (int i = 0; i < Process_index; i++)
    {
        if (Process[i]->arrival_time == timeline && (Process[i]->priority == priority || Process[i]->priority == priority + 1) && Process[i]->status == 2 && Process_in_queue(Queue, i) == -1)
            Push_Back(Queue, i);
    }
}

//Give right order in each Queue
void Sort(struct Node **Queue1, struct Node **Queue2, struct Node **Queue3, Process *Process[1000], int timeline, int Process_index)
{
    add_to_queue_1(Queue1, Process, timeline, Process_index, 6);
    add_to_queue_1(Queue1, Process, timeline, Process_index, 5);
    add_to_queue_23(Queue2, Process, timeline, Process_index, 3);
    add_to_queue_23(Queue3, Process, timeline, Process_index, 1);
    Queue1_HPF(Queue1, Process);
}

//Add time_waited for non-executed Process
void Aging(struct Node **Queue_ENDED, Process *Process[1000], int Process_index, int running_Process, int timeline)
{
    for (int i = 0; i < Process_index; i++)
    {
        if (i != running_Process && Process[i]->time_executed < Process[i]->total_time_units_required && Process[i]->original_arrival_time < timeline && Process_in_queue(Queue_ENDED, i) == -1)
        {
            Process[i]->time_waited++;
        }
    }
}

//If one process finished execution, all other process Age +1
//Use after current head has been removed.
void reset_age_and_time_waited(struct Node **Queue2, struct Node **Queue3, Process *Process[1000], int timeline, int Process_index)
{
    struct Node *temp2 = *Queue2;
    while (temp2 != NULL)
    {
        Process[temp2->index]->age++;
        if (Process[temp2->index]->age == 8)
        {
            Process[temp2->index]->age = 0;
            Process[temp2->index]->priority++;
            Process[temp2->index]->arrival_time = timeline + 1;
            if (Process[temp2->index]->priority == 5)
            {
                Process[temp2->index]->status = 2;
                Remove_Process_At_Given_Pos(Queue2, Process_in_queue(Queue2, temp2->index) + 1);
            }
        }
        temp2 = temp2->next;
    }

    struct Node *temp3 = *Queue3;
    while (temp3 != NULL)
    {
        Process[temp3->index]->age++;
        if (Process[temp3->index]->age == 8)
        {
            Process[temp3->index]->age = 0;
            Process[temp3->index]->priority++;
            Process[temp3->index]->arrival_time = timeline + 1;
            if (Process[temp3->index]->priority == 3)
            {
                Process[temp3->index]->status = 2;
                Remove_Process_At_Given_Pos(Queue3, Process_in_queue(Queue3, temp3->index) + 1);
            }
        }
        temp3 = temp3->next;
    }
}

/*
Note:
Process[temp->index]->arrival_time = timeline + 1
remove the Process and pretend it arrive at next second
As for the order for new arrivals, use Process[temp->index]->status to rank.
*/

void Execution(struct Node **Queue1, struct Node **Queue2, struct Node **Queue3, struct Node **Queue_ENDED, Process *Process[1000], int timeline, int Process_index)
{

    //If Queue 1 not empty, then handle first element in Q1 first.
    if (*Queue1 != NULL)
    {
        struct Node *temp1 = *Queue1;
        if (Process[temp1->index]->first_time_flag == 0)
        {
            Process[temp1->index]->first_time_flag = 1;
            Process[temp1->index]->first_time = timeline;
        }

        //if Q1's new arrival interrupt Q2
        if (*Queue2 != NULL)
        {
            struct Node *temp2 = *Queue2;
            if (Process[temp2->index]->time_executed > 0 && Process[temp1->index]->status == 5)
            {
                Push_Back(Queue2, temp2->index);
                Process[temp2->index]->age--;
                Process[temp2->index]->arrival_time = timeline + 1;
                Remove_Process(Queue2, *Queue2);
                reset_age_and_time_waited(Queue2, Queue3, Process, timeline, Process_index);
            }
        }

        //Execution
        Process[temp1->index]->time_executed++;
        Process[temp1->index]->time_executed_in_Q1++;
        Aging(Queue_ENDED, Process, Process_index, temp1->index, timeline);
        Process[temp1->index]->age = 0;
        Process[temp1->index]->time_waited = 0;
        Process[temp1->index]->status = 3;

        //finished
        if (Process[temp1->index]->time_executed == Process[temp1->index]->total_time_units_required)
        {
            Process[temp1->index]->end_time = timeline + 1;
            Process[temp1->index]->arrival_time = 0;
            Push_Back(Queue_ENDED, temp1->index);
            Remove_Process(Queue1, *Queue1);
            reset_age_and_time_waited(Queue2, Queue3, Process, timeline, Process_index);
            return;
        }

        //unfinished
        //Finish 5 time units cycle, move to end of queue.
        else if (Process[temp1->index]->time_executed % 5 == 0 && Process[temp1->index]->time_executed > 0)
        {
            //Finish 5 runs , priority - 1.
            if (Process[temp1->index]->time_executed % 25 == 0)
            {
                if (Process[temp1->index]->priority > 4)
                {
                    Process[temp1->index]->priority--;
                    Process[temp1->index]->status = 4;
                    Process[temp1->index]->arrival_time = timeline + 1;
                    Remove_Process(Queue1, *Queue1);
                    reset_age_and_time_waited(Queue2, Queue3, Process, timeline, Process_index);
                    return;
                }
            }
            Process[temp1->index]->arrival_time = timeline + 1;
            Process[temp1->index]->status = 3;
            Remove_Process(Queue1, *Queue1);
            reset_age_and_time_waited(Queue2, Queue3, Process, timeline, Process_index);
        }
        return;
    }
    //If Queue 1 is empty, Queue 2 not empty, then handle first element in Q2.
    else if (*Queue2 != NULL)
    {
        struct Node *temp2 = *Queue2;
        if (Process[temp2->index]->first_time_flag == 0)
        {
            Process[temp2->index]->first_time_flag = 1;
            Process[temp2->index]->first_time = timeline;
        }

        //Execution
        Process[temp2->index]->time_executed++;
        Process[temp2->index]->time_executed_in_Q2++;
        Aging(Queue_ENDED, Process, Process_index, temp2->index, timeline);
        Process[temp2->index]->time_waited = 0;
        Process[temp2->index]->age = 0;
        Process[temp2->index]->status = 3;

        //finished
        if (Process[temp2->index]->time_executed == Process[temp2->index]->total_time_units_required)
        {
            Process[temp2->index]->end_time = timeline + 1;
            Process[temp2->index]->arrival_time = 0;
            Push_Back(Queue_ENDED, temp2->index);
            Remove_Process(Queue2, *Queue2);
            reset_age_and_time_waited(Queue2, Queue3, Process, timeline, Process_index);
            return;
        }

        //unfinished
        //Finish 10 time units cycle, move to end of queue.
        else if (Process[temp2->index]->time_executed % 10 == 0 && Process[temp2->index]->time_executed > 0)
        {
            if (Process[temp2->index]->time_executed_in_Q2 % 20 == 0 && Process[temp2->index]->time_executed_in_Q2 > 0)
            {
                if (Process[temp2->index]->priority > 2 && Process[temp2->index]->priority < 5)
                {
                    Process[temp2->index]->priority--;
                    Process[temp2->index]->status = 4;
                    Process[temp2->index]->arrival_time = timeline + 1;
                    Remove_Process(Queue2, *Queue2);
                    reset_age_and_time_waited(Queue2, Queue3, Process, timeline, Process_index);
                    return;
                }
            }
            Process[temp2->index]->arrival_time = timeline + 1;
            Process[temp2->index]->status = 3;
            Remove_Process(Queue2, *Queue2);
            reset_age_and_time_waited(Queue2, Queue3, Process, timeline, Process_index);
        }
        return;
    }
    //If Queue 1&2 is empty, Queue 3 not empty, then handle first element in Q3.
    else if (*Queue3 != NULL)
    {
        struct Node *temp3 = *Queue3;
        if (Process[temp3->index]->first_time_flag == 0)
        {
            Process[temp3->index]->first_time_flag = 1;
            Process[temp3->index]->first_time = timeline;
        }

        //Execution
        Process[temp3->index]->time_executed++;
        Process[temp3->index]->time_executed_in_Q3++;
        Aging(Queue_ENDED, Process, Process_index, temp3->index, timeline);
        Process[temp3->index]->time_waited = 0;
        Process[temp3->index]->age = 0;
        Process[temp3->index]->status = 3;

        //finished
        if (Process[temp3->index]->time_executed == Process[temp3->index]->total_time_units_required)
        {
            Process[temp3->index]->end_time = timeline + 1;
            Process[temp3->index]->arrival_time = 0;
            Push_Back(Queue_ENDED, temp3->index);
            Remove_Process(Queue3, *Queue3);
            reset_age_and_time_waited(Queue2, Queue3, Process, timeline, Process_index);
            return;
        }

        //unfinished
        //Finish 20 time units cycle, move to end of queue.
        else if (Process[temp3->index]->time_executed_in_Q3 % 20 == 0 && Process[temp3->index]->time_executed_in_Q3 > 0)
        {

            Process[temp3->index]->arrival_time = timeline + 1;
            Remove_Process(Queue3, *Queue3);
            reset_age_and_time_waited(Queue2, Queue3, Process, timeline, Process_index);
            return;
        }
    }
    return;
}

int main(int argC, char *argV[])
{
    FILE *fp;
    char line[128];

    Process *Process[1000];

    int Process_index = 0;
    int total_time_all;

    fp = fopen(argV[1], "r");

    if (fp == NULL)
    {
        printf("Error: No inputfile found. Exiting...\n");
        return 1;
    }

    //Read file line by line
    while (fgets(line, 128, fp))
    {
        Process[Process_index] = malloc(sizeof(Process));
        strcpy(&Process[Process_index]->firstchar, &line[0]);
        memmove(&line[0], &line[1], strlen(line) - 0);
        Process[Process_index]->realindex = atoi(strtok(line, " "));
        Process[Process_index]->arrival_time = atoi(strtok(NULL, " "));
        Process[Process_index]->original_arrival_time = Process[Process_index]->arrival_time;
        Process[Process_index]->priority = atoi(strtok(NULL, " "));
        Process[Process_index]->age = atoi(strtok(NULL, " "));
        Process[Process_index]->total_time_units_required = atoi(strtok(NULL, " "));
        Process[Process_index]->time_executed = 0;
        Process[Process_index]->status = 5;
        Process[Process_index]->time_waited = 0;
        Process[Process_index]->time_executed_in_Q1 = 0;
        Process[Process_index]->time_executed_in_Q2 = 0;
        Process[Process_index]->time_executed_in_Q3 = 0;
        Process[Process_index]->first_time = 0;
        Process[Process_index]->first_time_flag = 0;
        Process[Process_index]->end_time = 0;
        total_time_all += Process[Process_index]->total_time_units_required;
        Process_index++;
    }
    fclose(fp);

    struct Node *Queue1 = NULL;
    struct Node *Queue2 = NULL;
    struct Node *Queue3 = NULL;
    struct Node *Queue_ENDED = NULL;

    for (int timeline = 0; timeline < total_time_all; timeline++)
    {
        Sort(&Queue1, &Queue2, &Queue3, Process, timeline, Process_index);
        Execution(&Queue1, &Queue2, &Queue3, &Queue_ENDED, Process, timeline, Process_index);
        PrintQueue_Debug(&Queue1, &Queue2, &Queue3, Process, timeline);
    }
    PrintQueue_Final(&Queue_ENDED, Process);

    //Delete
    for (int i = 0; i < Process_index; i++)
    {
        free(Process[i]);
    }

    return 0;
}

Compile:

gcc -std=c11 main.c -o run

Run:

./run input.txt

Leave a Reply

Your email address will not be published. Required fields are marked *