Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

A3. You are required to make the following changes to the program alarm_mutex.c to produce a program named New_Alarm_Mutex.c. A3.1 Two types of Alarm requests

A3. You are required to make the following changes to the program "alarm_mutex.c" to produce a program named New_Alarm_Mutex.c.

A3.1 Two types of Alarm requests in New_Alarm_Mutex.c

Two types of Alarm requests, Start_Alarm, and Change_Alarm requests, are recognized and handled by New_Alarm_Mutex.c, as follows:

(a) Start_Alarm requests with the following format:

Alarm> Start_Alarm(Alarm_ID): Time Message

  • - Start_Alarm is a keyword.

  • - Alarm_ID is a positive integer.

  • - Time has the same meaning and syntax as in the program alarm_mutex.c.

  • - Message has the same meaning and syntax as in the program alarm_mutex.c.

    For example: Alarm> Start_Alarm(2345) 50 Will meet you at Grandmas house at 6 pm

    (b) Change_Alarm requests with the following format:

    Alarm> Change_Alarm(Alarm_ID)

  • - Change_Alarm is a keyword.

  • - Alarm_ID is a positive integer.

  • - Time has the same meaning and syntax as in the program alarm_mutex.c.

  • - Message has the same meaning and syntax as in the program alarm_mutex.c.

For example: Alarm> Change_Alarm(2345) 80 Will meet you at Grandmas house later at 8 pm

If the user types in something other than one of the above two types of valid alarm requests, then an error message will be displayed, and the invalid request will be discarded.

A3.2. The main thread in New_Alarm_Mutex.c

The main thread in New_Alarm_Mutex.c will first determine whether the format of each alarm request is consistent with the formats specified above; otherwise the alarm request will be rejected with an error message. If a Message exceeds 128 characters, it will be truncated to 128 characters.

A.3.2.1. For each Start_Alarm request received, the main thread will insert the corresponding alarm with the specified Alarm_ID into the alarm list, in which all the alarms are placed in the order of their Alarm_IDs. Then the main thread will print: Alarm( ) Inserted by Main Thread Into Alarm List at :

Note that above, and in each of the messages printed by the various threads below, is the thread identifier>; , , , , , , , , etc., are the actual times at which the corresponding action was performed by each thread; those times are all expressed as the number of seconds from the Unix Epoch Jan 1 1970 00:00;

A.3.2.2. For each Change_Alarm request received, the main thread will use the specified Time and Message values in the Change_Alarm request to replace the Time and Message values in the alarm with the specified Alarm_Id in the alarm list. Then the main thread will print:

Alarm() Changed at :

A.3.3.1. For each newly inserted alarm in the alarm list, the alarm thread will do the following:

If the number of existing display alarm threads is less than 3,

Then: (a) create a new display alarm thread and assign that alarm to the newly created display alarm thread. Then the alarm thread will print: Alarm Thread Created New Display Alarm Thread For Alarm( at :

Else: (b) assign that alarm to an existing display alarm thread which has the smallest number of alarms assigned to it among the 3 existing display alarm threads. Then the alarm thread will print: Alarm Thread Display Alarm Thread Assigned to Display Alarm( at :

A.3.3.2. For each alarm in the alarm list, if the expiry time of that alarm has been reached, then the alarm thread will remove that alarm from the alarm list, and the associated display alarm thread will stop printing the message in that alarm Then the alarm thread will print:

Alarm Thread Removed Alarm( at :

A.3.3.3. For each alarm in the alarm list, if the expiry time of that alarm has been reached and the corresponding display alarm thread does not have any more alarms assigned to it, then terminate that display alarm thread. Then the alarm thread will print: Alarm Thread Terminated Display Thread at .

A3.4. The display alarm_threads in New_Alarm_Mutex.c

A3.4.1. After each display alarm thread in New_Alarm_Mutex.c has been created by the alarm thread, that display alarm thread will periodically print, every 5 seconds, the following:

Alarm () Printed by Alarm Display Thread at :

A.3.4.2. For each newly changed alarm in the alarm list, the display alarm thread associated with that alarm will start periodically printing, every 5 seconds, the new message in that newly changed alarm. When the display alarm thread first starts printing a new changed message it will print:

Display Thread Starts to Print Changed Message at :

B. Platform on Which The Programs Are to be Implemented

The programs should to be implemented using the ANSI C programming language and using the Linux system at York. You should use POSIX system calls or POSIX functions whenever possible.

/*

* alarm_mutex.c

*

* This is an enhancement to the alarm_thread.c program, which

* created an "alarm thread" for each alarm command. This new

* version uses a single alarm thread, which reads the next

* entry in a list. The main thread places new requests onto the

* list, in order of absolute expiration time. The list is

* protected by a mutex, and the alarm thread sleeps for at

* least 1 second, each iteration, to ensure that the main

* thread can lock the mutex to add new work to the list.

*/

#include

#include

#include "errors.h"

/*

* The "alarm" structure now contains the time_t (time since the

* Epoch, in seconds) for each alarm, so that they can be

* sorted. Storing the requested number of seconds would not be

* enough, since the "alarm thread" cannot tell how long it has

* been on the list.

*/

typedef struct alarm_tag {

struct alarm_tag *link;

int seconds;

time_t time; /* seconds from EPOCH */

char message[64];

} alarm_t;

pthread_mutex_t alarm_mutex = PTHREAD_MUTEX_INITIALIZER;

alarm_t *alarm_list = NULL;

/*

* The alarm thread's start routine.

*/

void *alarm_thread (void *arg)

{

alarm_t *alarm;

int sleep_time;

time_t now;

int status;

/*

* Loop forever, processing commands. The alarm thread will

* be disintegrated when the process exits.

*/

while (1) {

status = pthread_mutex_lock (&alarm_mutex);

if (status != 0)

err_abort (status, "Lock mutex");

alarm = alarm_list;

/*

* If the alarm list is empty, wait for one second. This

* allows the main thread to run, and read another

* command. If the list is not empty, remove the first

* item. Compute the number of seconds to wait -- if the

* result is less than 0 (the time has passed), then set

* the sleep_time to 0.

*/

if (alarm == NULL)

sleep_time = 1;

else {

alarm_list = alarm->link;

now = time (NULL);

if (alarm->time <= now)

sleep_time = 0;

else

sleep_time = alarm->time - now;

#ifdef DEBUG

printf ("[waiting: %d(%d)\"%s\"] ", alarm->time,

sleep_time, alarm->message);

#endif

}

/*

* Unlock the mutex before waiting, so that the main

* thread can lock it to insert a new alarm request. If

* the sleep_time is 0, then call sched_yield, giving

* the main thread a chance to run if it has been

* readied by user input, without delaying the message

* if there's no input.

*/

status = pthread_mutex_unlock (&alarm_mutex);

if (status != 0)

err_abort (status, "Unlock mutex");

if (sleep_time > 0)

sleep (sleep_time);

else

sched_yield ();

/*

* If a timer expired, print the message and free the

* structure.

*/

if (alarm != NULL) {

printf ("(%d) %s ", alarm->seconds, alarm->message);

free (alarm);

}

}

}

int main (int argc, char *argv[])

{

int status;

char line[128];

alarm_t *alarm, **last, *next;

pthread_t thread;

status = pthread_create (

&thread, NULL, alarm_thread, NULL);

if (status != 0)

err_abort (status, "Create alarm thread");

while (1) {

printf ("alarm> ");

if (fgets (line, sizeof (line), stdin) == NULL) exit (0);

if (strlen (line) <= 1) continue;

alarm = (alarm_t*)malloc (sizeof (alarm_t));

if (alarm == NULL)

errno_abort ("Allocate alarm");

/*

* Parse input line into seconds (%d) and a message

* (%64[^ ]), consisting of up to 64 characters

* separated from the seconds by whitespace.

*/

if (sscanf (line, "%d %64[^ ]",

&alarm->seconds, alarm->message) < 2) {

fprintf (stderr, "Bad command ");

free (alarm);

} else {

status = pthread_mutex_lock (&alarm_mutex);

if (status != 0)

err_abort (status, "Lock mutex");

alarm->time = time (NULL) + alarm->seconds;

/*

* Insert the new alarm into the list of alarms,

* sorted by expiration time.

*/

last = &alarm_list;

next = *last;

while (next != NULL) {

if (next->time >= alarm->time) {

alarm->link = next;

*last = alarm;

break;

}

last = &next->link;

next = next->link;

}

/*

* If we reached the end of the list, insert the new

* alarm there. ("next" is NULL, and "last" points

* to the link field of the last item, or to the

* list header).

*/

if (next == NULL) {

*last = alarm;

alarm->link = NULL;

}

#ifdef DEBUG

printf ("[list: ");

for (next = alarm_list; next != NULL; next = next->link)

printf ("%d(%d)[\"%s\"] ", next->time,

next->time - time (NULL), next->message);

printf ("] ");

#endif

status = pthread_mutex_unlock (&alarm_mutex);

if (status != 0)

err_abort (status, "Unlock mutex");

}

}

}

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Database Concepts

Authors: David Kroenke, David Auer, Scott Vandenberg, Robert Yoder

9th Edition

0135188148, 978-0135188149, 9781642087611

More Books

Students also viewed these Databases questions