#define _GNU_SOURCE #include #include #include #include #define BUFFERLENGTH 80 #define MAX_THREADS 1000 #define LOGFILE "/home/exr/tmp/logfile.txt" pthread_cond_t input_cond; pthread_mutex_t print_mutex; pthread_mutex_t mutex; pthread_cond_t cond; char *buffer; int currentReaders = 0; int writersExecuting = 0; int returnValue; /* not used; need something to keep compiler happy */ FILE *outfile; int mainProcessMayInput = 1; /* creates a new thread with default arguments*/ void create_thread(void * (*start_routine)(void*), void *args) { pthread_t *newThread; int result; newThread = malloc (sizeof (pthread_t)); if (!newThread) { fprintf (stderr, "Couldn't allocate memory for thread!\n"); exit (1); } result = pthread_create (newThread, NULL, start_routine, args); if (result != 0) { fprintf (stderr, "Thread creation failed!\n"); exit (1); } } /* the readers */ void *readersThread (void *args) { char command[5]; /* obtain the arguments (for controlling the connection ) */ int *intArgs = (int *) args; int pipefd = intArgs[0]; int threadNo = intArgs[1]; pthread_mutex_lock (&mutex); fprintf (outfile, "Reader No. %d is executing, currentReaders = %d, writersExecuting = %d\n" , threadNo, currentReaders, writersExecuting); fflush (outfile); pthread_mutex_unlock (&mutex); pthread_mutex_lock (&mutex); while (writersExecuting > 0) { fprintf (outfile, "Reader No. %d is blocked, currentReaders = %d, writersExecuting = %d\n" , threadNo, currentReaders, writersExecuting); fflush (outfile); pthread_cond_wait (&cond, &mutex); } currentReaders ++; pthread_mutex_unlock (&mutex); /* now do the reading */ fprintf (outfile, "Reader No. %d is executing \n", threadNo); fflush (outfile); read (pipefd, command, 5); fprintf (outfile, "Thread no %d has read data %s\n", threadNo, buffer); fflush (outfile); pthread_mutex_lock (&print_mutex); mainProcessMayInput = 1; /* to signal main process */ pthread_cond_broadcast (&input_cond); /* to signal main process */ pthread_mutex_unlock (&print_mutex); pthread_mutex_lock (&mutex); currentReaders --; pthread_cond_broadcast (&cond); pthread_mutex_unlock (&mutex); return (&returnValue); } /* the writers */ void *writersThread (void *args) { char command[5]; /* obtain the arguments (for controlling the connection ) */ int *intArgs = (int *) args; int pipefd = intArgs[0]; int threadNo = intArgs[1]; /* size_t size;*/ pthread_mutex_lock (&mutex); fprintf (outfile, "Writer No. %d is executing, currentReaders = %d, writersExecuting = %d\n" , threadNo, currentReaders, writersExecuting); fflush (outfile); pthread_mutex_unlock (&mutex); pthread_mutex_lock (&mutex); while ((writersExecuting > 0) || (currentReaders > 0)) { fprintf (outfile, "Writer No. %d is blocked, currentReaders = %d, writersExecuting = %d\n" , threadNo, currentReaders, writersExecuting); fflush (outfile); pthread_cond_wait (&cond, &mutex); } writersExecuting ++; pthread_mutex_unlock (&mutex); /* now do the writing */ fprintf (outfile, "Writer No. %d was not blocked, currentReaders = %d, writersExecuting = %d\n" , threadNo, currentReaders, writersExecuting); fflush (outfile); read (pipefd, command, 5); fprintf (outfile, "Writer %d: Enter the text for the buffer\n", threadNo); fflush (outfile); buffer = fgets (buffer, BUFFERLENGTH -1, stdin); fprintf (outfile, "The entered text is %s", buffer); fflush (outfile); pthread_mutex_lock (&print_mutex); mainProcessMayInput = 1; /* to signal main process */ pthread_cond_broadcast (&input_cond); /* to signal main process */ pthread_mutex_unlock (&print_mutex); /* and release the lock */ pthread_mutex_lock (&mutex); writersExecuting --; pthread_cond_broadcast (&cond); pthread_mutex_unlock (&mutex); return (&returnValue); } int main () { char *command; int threadPipe[MAX_THREADS + 1]; int threadNo = 0; char *ok = "OK"; int threadindex; pthread_mutex_init (&mutex, NULL); pthread_mutex_init (&print_mutex, NULL); outfile = fopen (LOGFILE, "w"); if (!outfile) { fprintf (stderr, "Couldn't open logfile \n"); exit (1); } buffer = malloc (BUFFERLENGTH); if (!buffer) { fprintf (stderr, "Memory allocation failed!\n"); exit (1); } while (1) { int args[2]; int pfd[2]; if (threadNo > MAX_THREADS) { fprintf (stderr, "Number of threads exceeded, exiting!\n"); exit (0); } command = malloc (BUFFERLENGTH); if (!command) { fprintf (stderr, "Memory allocation failed!\n"); exit (1); } command = fgets (command, BUFFERLENGTH -1, stdin); switch (command[0]) { case 'W': threadNo ++; printf ("creating writers task with thread number %d\n", threadNo); args[1] = threadNo; if (pipe (pfd) == -1) { fprintf (stderr, "Pipe creation failed!\n"); exit (1); } args[0] = pfd[0]; threadPipe[threadNo] = pfd[1]; pthread_mutex_lock (&print_mutex); mainProcessMayInput = 0; create_thread (writersThread, (void *) args); pthread_mutex_unlock (&print_mutex); break; case 'R': threadNo ++; printf ("creating readers task with thread number %d\n", threadNo); args[1] = threadNo; if (pipe (pfd) == -1) { fprintf (stderr, "Pipe creation failed!\n"); exit (1); } args[0] = pfd[0]; threadPipe[threadNo] = pfd[1]; pthread_mutex_lock (&print_mutex); mainProcessMayInput = 0; create_thread (readersThread, (void *) args); pthread_mutex_unlock (&print_mutex); break; default: threadindex = atoi (command); if ((threadindex == 0) || (threadindex > threadNo)) { fprintf (stderr, "Wrong command %s detected, ignoring!\n", command); break; } write (threadPipe[threadindex], ok, 3); pthread_mutex_lock (&print_mutex); while (!mainProcessMayInput) { pthread_cond_wait (&input_cond, &print_mutex); } pthread_mutex_unlock (&print_mutex); } } }