Question
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(
Note that above, and in each of the messages printed by the various threads below,
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(
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
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
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(
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
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 (
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
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
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