Question
/* * alarm_mutex.c * * This is an enhancement to the alarm_thread.c program, which * created an alarm thread for each alarm command. This new
/* * 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
/* * 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 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)
/* * 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) 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"); } } }
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 Iwo tvpes of "Alarm requests" in "New Alarm Mutex.c" Two types of "Alarm requests", "Start_Alarm", and "Cancel _Alarm" requests, are recognized and handled by "New_Alarm Mutex.c", as follows (a) "Start Alarm" requests with the following format: Alam> 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 "alam mutexc For example: Alarm> Start_Alarm(2345) 5 Will meet you at Grandma's house at 6 pm (b) "Cancel Alarm" requests with the following format: Alarm> Cancel_Alarm(Alarm ID) Cancel Alarm:" is a keyword. "Alarm_ID" is a positive integer. For example: Alarm> Cancel_Alarm(2345) 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 AlarmID 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(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