Why does the program use sched_yield? What happens if this is not used? Will the
ID: 3805642 • Letter: W
Question
Why does the program use sched_yield? What happens if this is not used? Will the swap counts always be identical? (see code below)
#include "enzyme.h"
int please_quit;
int use_yield;
int workperformed;
// The code each enzyme executes.
void *run_enzyme(void *data) {
/* This function should :
1. cast the void* pointer to thread_info_t*
2. initialize the swapcount to zero
3. Set the cancel type to PTHREAD_CANCEL_ASYNCHRONOUS
4. If the first letter of the string is a C then call pthread_cancel on this thread.
5. Create a while loop that only exits when please_quit is nonzero
6. Within this loop: if the first character of the string has an ascii value greater than the second (s[0] >s[1]) then -
Set workperformed=1, increment swapcount for this thread, then swap the two characters around
If "use_yield" is nonzero then call pthread_yield at the end of the loop.
7. Return a pointer to the updated structure.
*/
while(0) {
sched_yield();
};
return NULL;
}
// Make threads to sort string.
// Returns the number of threads created.
// There is a memory bug in this function.
int make_enzyme_threads(pthread_t * enzymes, char *string, void *(*fp)(void *)) {
int i,rv,len;
thread_info_t *info;
len = strlen(string);
info = (thread_info_t *)malloc(sizeof(thread_info_t));
for(i=0;i<len-1;i++) {
info->string = string+i;
rv = pthread_create(enzymes+i,NULL,fp,info);
if (rv) {
fprintf(stderr,"Could not create thread %d : %s ",
i,strerror(rv));
exit(1);
}
}
return len-1;
}
// Join all threads at the end.
// Returns the total number of swaps.
int join_on_enzymes(pthread_t *threads, int n) {
int i;
int totalswapcount = 0;
int whatgoeshere=0; // just to make the code compile
// you will need to edit the code below
for(i=0;i<n;i++) {
void *status;
int rv = pthread_join(threads[i],&status);
if(whatgoeshere) {
fprintf(stderr,"Can't join thread %d:%s. ",i,strerror(rv));
continue;
}
if ((void*)whatgoeshere == PTHREAD_CANCELED) {
continue;
} else if (status == NULL) {
printf("Thread %d did not return anything ",i);
} else {
printf("Thread %d exited normally: ",i);// Don't change this line
int threadswapcount = whatgoeshere;
// Hint - you will need to cast something.
printf("%d swaps. ",threadswapcount); // Don't change this line
totalswapcount += threadswapcount;// Don't change this line
}
}
return totalswapcount;
}
/* Wait until the string is in order. Note, we need the workperformed flag just in case a thread is in the middle of swapping characters
so that the string temporarily is in order because the swap is not complete.
*/
void wait_till_done(char *string, int n) {
int i;
while(1) {
sched_yield();
workperformed=0;
for(i=0;i<n;i++)
if (string[i] > string[i+1]) {
workperformed=1;
}
if(workperformed==0) break;
}
}
void * sleeper_func(void *p) {
sleep( (int) p);
// Actually this may return before p seconds because of signals.
// See man sleep for more information
printf("sleeper func woke up - exiting the program ");
exit(1);
}
int smp2_main(int argc, char **argv) {
pthread_t enzymes[MAX];
int n,totalswap;
char string[MAX];
if (argc <= 1) {
fprintf(stderr,"Usage: %s <word> ",argv[0]);
exit(1);
}
strncpy(string,argv[1],MAX); // Why is this necessary? Why cant we give argv[1] directly to the thread functions?
please_quit = 0;
use_yield =1;
printf("Creating threads... ");
n = make_enzyme_threads(enzymes,string,run_enzyme);
printf("Done creating %d threads. ",n);
pthread_t sleeperid;
pthread_create(&sleeperid,NULL,sleeper_func,(void*)5);
wait_till_done(string,n);
please_quit = 1;
printf("Joining threads... ");
totalswap = join_on_enzymes(enzymes, n);
printf("Total: %d swaps ",totalswap);
printf("Sorted string: %s ",string);
exit(0);
}
Explanation / Answer
sched_yield();
The sched_yield() function checks to see if other threads, at the same priority as that of the calling thread, are READY to run. If so, the calling thread yields to them and places itself at the end of the READY thread queue. The sched_yield() function never yields to a lower-priority thread.
A higher-priority thread always forces a lower-priority thread to yield (that is, preempt) the instant the higher-priority thread becomes ready to run, without the need for the lower-priority thread to give up the processor by calling the sched_yield() or SchedYield() functions.
The sched_yield() function calls the kernel function SchedYield(), and may be more portable across realtime POSIX systems.
=>You should avoid designing programs that contain busy wait loops. If you can't avoid them, you can use sched_yield() to reduce the system load at a given priority level. Note that a thread that calls sched_yield() in a tight loop will spend a great deal of time in the kernel, which will have a small effect on interrupt latency.
=> the swap counts always change according to the increment of the values.
I hpoe it will help you to understand.
Thanks
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.