Question

In: Computer Science

C Language - The function 'make_enzyme_threads' has a memory bug. Fix this by simply re-ordering the...

C Language - The function 'make_enzyme_threads' has a memory bug. Fix this by simply re-ordering the lines in this function. It is simple fix but may take a while for you to find it. As a hint, you may want to pay attention to the addresses of the pointers that are passed to the individual enzymes.

//enzyme.h contents

//Note I could not use tag openers in the includes.

#define _GNU_SOURCE
#include (pthread.h)
#include (stdio.h)
#include (sys/types.h)
#include (string.h)
#include (stdlib.h)
#include (unistd.h)

#define MAX 100

typedef struct {
char *string; // keep testing and swap contents if necessary so that string[0] < string[1]
int swapcount; // used later
} thread_info_t;

extern int please_quit;
extern int workperformed;

void *run_enzyme(void *data);
int make_enzyme_threads(pthread_t * enzymes_tid, char *string, void *(*fp)(void *));
int join_on_enzymes(pthread_t *threads_tid, int n);

int smp2_main(int, char**);

// XXX macOS compatibility
#ifdef __APPLE__
#define pthread_yield() sched_yield()
#endif

//enzyme.c contents

#include "enzyme.h"

int please_quit;
int use_yield;
int workperformed;

// The code executed by each enzyme.
void *run_enzyme(void *data) {
//This function should :
//1. Cast the void* pointer to thread_info_t* (defined in enzyme.h)
//2. Initialize the swapcount to zero
  //3. Set the cancel type to PTHREAD_CANCEL_ASYNCHRONOUS (see pthread_setcanceltype)
/*4. If the first letter of the string is a C then call pthread_cancel on this thread.
(see also, pthread_self)
Note, depeneding on your platform (and specifically for macOS) you have
to replace the call to pthread_cancel with
pthread_exit(PTHREAD_CANCELED) in order to make the cancel test
pass.*/
//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 (info->string[0] > info->string[1]) then
- Set workperformed = 1
- Increment swapcount for this thread
- Swap the two characters around*/
//7. If "use_yield" is nonzero then call pthread_yield at the end of the loop.
//8. Return a pointer to the updated structure.

while(0) {
pthread_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\n", 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;

// Just to make the code compile. You will need to replace every usage of
// this variable in the code below. When you are done, placeholder can be
// deleted.

int holder = 0;

for(i = 0; i < n; i++) {
void *status;
int rv = pthread_join(threads[i], &status);

if (holder) {
fprintf(stderr,"Can't join thread %d:%s.\n",i,strerror(rv));
continue;
}

if ((void*)holder == PTHREAD_CANCELED) {
continue;
} else if (status == NULL) {
printf("Thread %d did not return anything\n",i);
} else {
printf("Thread %d exited normally: ",i);// Don't change this line
int threadswapcount = holder;
// Hint - you will need to cast something.
printf("%d swaps.\n",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) {
pthread_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\n");
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 \n",argv[0]);
exit(1);
}

// Why is this necessary? Why cant we give argv[1] directly to the thread
// functions?
strncpy(string,argv[1],MAX);

please_quit = 0;
use_yield = 1;

printf("Creating threads...\n");
n = make_enzyme_threads(enzymes, string, run_enzyme);
printf("Done creating %d threads.\n",n);

pthread_t sleeperid;
pthread_create(&sleeperid, NULL, sleeper_func, (void*)5);

wait_till_done(string, n);
please_quit = 1;
printf("Joining threads...\n");
totalswap = join_on_enzymes(enzymes, n);
printf("Total: %d swaps\n", totalswap);
printf("Sorted string: %s\n", string);

exit(0);
}

Solutions

Expert Solution

Working code implemented in C and appropriate comments provided for better understanding.

Here I am attaching code for these files:

  • enzyme.c
  • enzyme.h

enzyme.c:

#include "enzyme.h"

int please_quit;
int use_yield;
int workperformed;

// error handler
void handle_error(int error_no, const char * const msg) {
fprintf(stderr, msg, error_no);
exit(EXIT_FAILURE);
}

// The code each enzyme executes.
void* run_enzyme(void *data) {
// This function should :
// 1. cast the void* pointer to thread_info_t*
thread_info_t *thread_data = (thread_info_t *)data;
// 2. initialize the swapcount to zero
thread_data->swapcount = 0;
int result;
// 3. Set the cancel type to PTHREAD_CANCEL_ASYNCHRONOUS
result = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
if (result) {
handle_error(result, "error code %d: pthread_setcanceltype\n");
}
// 4. If the first letter of the string is a C then call pthread_cancel on this thread.
if (thread_data->string[0] == 'C') {
result = pthread_cancel(pthread_self());
if (result) {
handle_error(result, "error code %d: pthread_cancel\n");
}
}
// 5. Create a while loop that only exits when please_quit is nonzero
while (please_quit == 0) {
// 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 (thread_data->string[0] > thread_data->string[1]) {
// printf("thead %d before swap: %c, %c\n", pthread_self(), thread_data->string[0], thread_data->string[1]);
workperformed = 1;
thread_data->swapcount++;
// swap characters
thread_data->string[0] ^= thread_data->string[1];
thread_data->string[1] ^= thread_data->string[0];
thread_data->string[0] ^= thread_data->string[1];
// printf("thead %d after swap: %c, %c\n", pthread_self(), thread_data->string[0], thread_data->string[1]);
// If "use_yield" is nonzero then call pthread_yield at the end of the loop.
if (use_yield) {
result = pthread_yield();
if (result) {
handle_error(result, "error code %d: pthread_yield\n");
}
}
}
}
  
// 7. Return a pointer to the updated structure.
return thread_data;
}

// 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);

for (i = 0; i < len - 1; i++) {
info = (thread_info_t *)malloc(sizeof(thread_info_t));
info->string = string + i;
rv = pthread_create(enzymes + i, NULL, fp, info);
if (rv) {
fprintf(stderr, "Could not create thread %d : %s\n",
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 (rv) {
fprintf(stderr,"Can't join thread %d:%s.\n",i,strerror(rv));
continue;
}

if ((void*)status == PTHREAD_CANCELED) {
continue;
} else if (status == NULL) {
printf("Thread %d did not return anything\n", i);
} else {
printf("Thread %d exited normally: ", i);// Don't change this line
int threadswapcount = ((thread_info_t *)status)->swapcount;
// Hint - you will need to cast something.
printf("%d swaps.\n",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\n");
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>\n",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");
n = make_enzyme_threads(enzymes, string, run_enzyme);
printf("Done creating %d threads.\n",n);
  
pthread_t sleeperid;
pthread_create(&sleeperid, NULL, sleeper_func, (void*)5);

wait_till_done(string, n);
please_quit = 1;
printf("Joining threads...\n");
totalswap = join_on_enzymes(enzymes, n);
printf("Total: %d swaps\n", totalswap);
printf("Sorted string: %s\n", string);
  
exit(0);
}

enzyme.h:

#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#define MAX 100

typedef struct {
char *string; // keep testing and swap contents if necessary so that string[0] < string[1]
int swapcount; // used later
} thread_info_t;

extern int please_quit;

extern int workperformed;

void *run_enzyme(void *data);

int make_enzyme_threads(pthread_t * enzymes_tid, char *string, void *(*fp)(void *));

int join_on_enzymes(pthread_t *threads_tid, int n);

int smp2_main(int, char**);


Related Solutions

The function 'make_enzyme_threads' has a memory bug. Fix this by simply re-ordering the lines in this...
The function 'make_enzyme_threads' has a memory bug. Fix this by simply re-ordering the lines in this function. It is simple fix but may take a while for you to find it. As a hint, you may want to pay attention to the addresses of the pointers that are passed to the individual enzymes #include "enzyme.h" int please_quit; int use_yield; int workperformed; // The code executed by each enzyme. void *run_enzyme(void *data) { /* This function should : 1. Cast the...
how to accept string from shared memory using c language ?
how to accept string from shared memory using c language ?
In C++, Implement the heapafication operation. Do not re-implement the binary tree class. Simply create a...
In C++, Implement the heapafication operation. Do not re-implement the binary tree class. Simply create a funcntion that takes in a binary tree and heapafies it. Meaning it takes in a pointer to a binary tree and converts it into a heap. (You may choose max or min heap).
use the python language and fix the error code #Write a function called rabbit_hole. rabbit_hole should...
use the python language and fix the error code #Write a function called rabbit_hole. rabbit_hole should have #two parameters: a dictionary and a string. The string may be #a key to the dictionary. The value associated with that key, #in turn, may be another key to the dictionary. # #Keep looking up the keys until you reach a key that has no #associated value. Then, return that key. # #For example, imagine if you had the following dictionary. #This one...
Code in C++ programming language description about read and write data to memory example.
Code in C++ programming language description about read and write data to memory example.
Programming in C language (not C++) Write a runction derinition for a function called SmallNumbers that...
Programming in C language (not C++) Write a runction derinition for a function called SmallNumbers that will use a while loop. The function will prompt the user to enter integers ine by one, until the user enters a negative value to stop. The function will display any integer that is less than 25. Declare and initialize any variables needed. The function takes no arguments and has a void return type.
How to convert Sudo Code to C language? keyboard_process() {//insert a string. //check for shared memory...
How to convert Sudo Code to C language? keyboard_process() {//insert a string. //check for shared memory If(shared memory not full) { //sendthe string to the shared memory //send signal to process; }
C Language - Programming Write a function that takes an array of ints, and the size...
C Language - Programming Write a function that takes an array of ints, and the size of the array – another int. It also returns a double. Call this one ‘average.’ Return a double that is the average of the values in the array. Demonstrate that it works by finding the average of an array with these values {78, 90, 56, 99, 88, 68, 92} Write a function that takes one double parameter, and returns a char. The parameter represents...
C PROGRAMMING 1. Write a C Language inline function that computes the cube of float X,...
C PROGRAMMING 1. Write a C Language inline function that computes the cube of float X, if X is greater than 1 and X is less than 100. Put the inline function in a main program that reads X from the keyboard, calls the function, and then outputs the result. 2. Show an empty statement and detail what it does? 3. A collection of predefined functions is called a Database                    C) Subroutine                       E) None of these Library                       D) Directive 4....
Programming in C language (not C++) Write a function definition called PhoneType that takes one character...
Programming in C language (not C++) Write a function definition called PhoneType that takes one character argument/ parameter called "phone" and returns a double. When the variable argument phone contains the caracter a or A, print the word Apple and return 1099.99. When phone contains the caracter s or S print the word Samsung and return 999.99. When phone contains anything else, return 0.0.
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT