#include "alarm.h" void main() { struct delta *addwork, *temp, *temp2; /* addwork - a delta linked list for the additional work section. temp/temp2 - temporary delta variables */ char input[1025], ragu[27]; /* input - the input string ragu - a string which keeps a list of the process in the global delta list. */ int loo, loop, numevents=0; /* loo, loop - dummy looping variable numevents - variable which keeps track of the number of events. */ unsigned int tempvec=0; /* tempvec - a temporary copy of the procstatus bit vector */ time_t timetemp; /* timetemp - variable to handle the ctime call */ /* Initialize the addwork list */ addwork=(struct delta *)malloc(sizeof(struct delta)); if (addwork==(struct delta *)NULL) die("Malloc call failed for the addwork delta list.\n"); addwork->next=(struct delta *)NULL; /* Initially, there is nothing on the delta list ... */ strcpy(ragu,""); if (Init()==-1) /* Initialize the delta list, create the semaphore, etc. */ die("There was an error in the initialization routine!\n"); while(1) /* The loop will break out when finished ... */ { if (fgets(input,1024,stdin)==NULL) /* Error or EOF (probably EOF) */ { printf("\n"); break; } loo=0; /* Compress the input to a simple 'X#####' string */ for(loop=0; loop<=strlen(input); loop++) { if (isalnum(input[loop])||input[loop]=='\0') input[loo++]=input[loop]; } if (islower(input[0])) /* Lower case */ input[0]-=32; /* Convert to lower case */ loop=atoi(input+1); /* Convert anything past the first character into the # of seconds for the alarm... */ if (isupper(input[0])&&loop) /* Don't accept a process name that that isn't an uppercase character, and the alarm time must be a positive integer. */ { if (strchr(ragu,input[0])==NULL) /* The process hasn't scheduled any alarms as of yet...*/ { AddAlarm(input[0],loop); /* Add the alarm */ numevents++; /* Yet another event to deal with ... */ sprintf(ragu,"%s%c",ragu,input[0]); /* Add to the ragu string */ } else /* It *IS* in there ... Unlike Prego ... (ie: this process has already scheduled an alarm. Hold it in the temp list for now.) */ { temp=(struct delta *)malloc(sizeof(struct delta)); temp->next=addwork->next; temp->proc=input[0]; temp->count=loop; addwork->next=temp; } } else printf("Error!\n"); /* In case the input line isn't exactly what we wanted... 8| */ } signal(SIGALRM,handler); /* Set the handler */ clockpid=CreateProcess(myclock,getpid()); /* Start the clock process */ if (clockpid==-1) die("Creation of the clock process failed!\n"); while(numevents) /* Loop until we're done */ { if(swait(salarm)==-1) /* Wait until the alarm signals us with process alarms */ die("Semaphore wait failed!\n"); tempvec=procstatus; /* Get a copy of the procstatus bit vector */ procstatus=0; /* Reset the actual procstatus bit vector... If we get alarmed for some reason while in this loop, the output won't be confused. */ for(loop=0;loop<26;loop++) /* Loop through all posibilities */ { if (tempvec&1<next; temp2=addwork; while(temp!=NULL) /* Go through */ { if (temp->proc==loop+'A') /* Another one! */ { AddAlarm(temp->proc,temp->count); numevents++; temp=temp->next; free(temp2->next); temp2->next=temp; break; } else /* Keep going */ { temp=temp->next; temp2=temp2->next; } } } } } free(addwork); /* Clean up - The addwork list should be empty at the end. (unless I didn't code this right.) 8| */ if (Cleanup()==-1) /* Cleanup other various things. */ die("Cleanup routine failed!\n"); return; /* Exit! */ } /* * CreateProcess - 96/09/09 * * CreateProcess will now take two parameters, and pass the second to the * forked child. - Originally written for OS-1 Project #2. * * Input : function pointer, initial variable to pass to function * Output: PID of child process if success, -1 if failure. * */ int CreateProcess(int (*pFunc)(),int dvalue) { int pid; if ((pid = fork()) == 0) /* We're the child */ { (*pFunc)(dvalue); /* Call function with value */ exit(0); /* If function doesn't quit, we'll die implicitly */ } return(pid); /* Return fork() value to the parent (-1 for error, PID otherwise) */ } /* * Init - 96/10/08 * * Initializes the global delta list variable. Also creates the alarm * semaphore for main function alarm processing. * * Input : None * Output: 0 if success, -1 if failure * */ int Init() { /* Create the delta list */ dlist=(struct delta *)malloc(sizeof(struct delta)); if (dlist==(struct delta *)NULL) return(-1); dlist->next=(struct delta *)NULL; salarm=screate(0); /* Create the semaphore */ if (salarm==-1) return(-1); return(0); } /* * Cleanup - 96/10/08 * * Clears up the global delta list, removes the alarm semaphore, and kills * the clock child process. * * Input : None * Output: 0 if success, -1 if failure * */ int Cleanup() { struct delta *temp; while(dlist!=(struct delta *)NULL) /* Remove all the delta list entries */ { temp=dlist->next; free(dlist); dlist=temp; } if (kill(clockpid,SIGINT)==-1) /* Kill the clock process */ return(-1); if (sdelete(salarm)==-1) /* Delete the semaphore */ return(-1); return(0); } /* * AddAlarm - 96/10/08 * * Adds the passed in parameters to the global alarm delta list. * * Input : Process Character (A-Z), Number of seconds until the alarm is to * go off. * Output: 0 on success, -1 on failure. * */ int AddAlarm(char proc,int num) { struct delta *temp=dlist->next, *temp2, *temp3=dlist; if (temp==(struct delta *)NULL) /* Blank List, insert the first entry */ { dlist->next=(struct delta *)malloc(sizeof(struct delta)); if (dlist->next==(struct delta *)NULL) return(-1); temp=dlist->next; temp->next=(struct delta *)NULL; temp->count=num; temp->proc=proc; return(0); } else if (temp->count>num) /* This one should go in as the first node ... */ { temp2=(struct delta *)malloc(sizeof(struct delta)); if (temp2==(struct delta *)NULL) return(-1); temp2->next=dlist->next; dlist->next->count-=num; temp2->count=num; temp2->proc=proc; dlist->next=temp2; return(0); } /* Or else we're somewhere else in the list... */ while(temp!=(struct delta *)NULL && num>=temp->count) { num-=temp->count; temp=temp->next; temp3=temp3->next; } temp2=(struct delta *)malloc(sizeof(struct delta)); if (temp2==(struct delta *)NULL) return(-1); temp2->next=temp3->next; if (temp!=(struct delta *)NULL) temp2->next->count-=num; temp2->count=num; temp2->proc=proc; temp3->next=temp2; return(0); } /* * Printd - 96/10/08 * * Goes through a delta list and prints out all of the nodes. Only good for * debugging in this project. * * Input : Pointer to the delta list to print out. * Output: None * */ void Printd(struct delta *temp) { struct delta *temp2; if (temp->next==(struct delta *)NULL) /* If it's a null list, print a null response. */ printf("[]"); else { temp2=temp->next; while(temp2!=(struct delta *)NULL) { printf("[%c%d]",temp2->proc,temp2->count); temp2=temp2->next; } } printf("\n"); return; } /* * handler - 96/10/08 * * The signal handler for the SIGALRM signal. * * Input : None * Output: None * */ void handler() { struct delta *temp=dlist->next; if (temp!=(struct delta *)NULL) /* If the list has at least 1 entry */ { temp->count--; /* Decrement the count */ if (temp->count<1) /* If the count of the first alarm is 0 ... */ { while(temp!=(struct delta *)NULL && temp->count==0) /* Set off any alarms that go off at this time. */ { procstatus=procstatus|1<<(temp->proc-'A'); temp=temp->next; free(dlist->next); dlist->next=temp; } if (ssignal(salarm)==-1) /* Signal the semaphore so that the main process will put the alarm through. */ die("ssignal call failed in SIGALRM handler!!!\n"); } } signal(SIGALRM,handler); /* Needed under Linux to reset the signal handler after this run through the routine. */ } /* * die - 96/10/10 * * Routine to handle failures... Prints the error and terminates the current * process. * * Input : Error character string. * Output: None * */ void die(char *in) { printf("%s",in); exit(1); }