/* OpSys sample thread code. This program has two threads: 1. reads from standard input and places whatever it reads into a buffer. 2. looks for stuff in the buffer and writes it to standard output. The result is simply a program that prints out whatever you type in... IMPORTANT NOTE: This is a very good bad example! (a good example of the wrong way to use threads). The busy waiting is the problem, this is as bad as it gets.... Check threadecho2.c for the better version! */ #include #include #include #include #include #include /*==========================================================*/ /* Global variables shared by the threads msgbuf is a circular buffer that holds whatever has been read from standard input by the reading thread. The writing thread grabs stuff from here and writes it to stdout. in, out are indicies of the last character put in and the last char that was removed (respectively). if in == out, this means there is nothing in the buffer that hasn't been removed. */ #define BUFSIZE 100 char msgbuf[BUFSIZE]; int in = 0; int out = 0; /* mutex used to restrict access to shared data structure */ pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; /* functions to grab and release the mutex any error is fatal here... */ void grablock() { /* grab the lock */ if (pthread_mutex_lock(&mtx)!=0) { printf("error getting mutex lock\n"); exit(1); } } void releaselock() { /* release the lock */ if (pthread_mutex_unlock(&mtx)!=0) { printf("error releasing mutex lock\n"); exit(1); } } /* add character to the circular buffer. waits until this is possible ! */ void put_a_char(char c) { int spot_avail; /* BUSY WAITING!!!!! */ do { grablock(); // check to see if there is room for another char spot_avail = ((in+1)%BUFSIZE!=out); releaselock(); } while (! spot_avail); grablock(); in = (in+1)%BUFSIZE; msgbuf[in]=c; releaselock(); } /* get next char from buffer - waits until there is a byte available */ char get_a_char() { int char_avail; char c; /* BUSY WAITING !!!!! */ do { grablock(); // check to see if there is a char available char_avail = (in != out); releaselock(); } while (! char_avail); grablock(); out = (out+1)%BUFSIZE; c = msgbuf[out]; releaselock(); return(c); } /* reader reads from standard input (one byte at a time) and places into the shared buffer */ void *reader(void *arg) { int nbytes; char c; while (1) { /* attempt to read as much as we can */ if (read(STDIN_FILENO,&c,1)!=1) { /* Either EOF or an error , in either case just quit */ write(STDOUT_FILENO,"\nAll Done\n",10); exit(1); } put_a_char(c); } } void *writer(void *arg) { char c; while (1) { c = get_a_char(); if (1!= write(STDOUT_FILENO,&c,1)) { /* write error ? punt... */ exit(1); } } } int main() { int i; pthread_t pt; /* start up the reader */ pthread_create(&pt,NULL,reader,NULL); // reader(NULL); /* become the writer */ writer(NULL); }