diff options
author | 53hornet <53hornet@gmail.com> | 2019-02-02 22:59:54 -0500 |
---|---|---|
committer | 53hornet <53hornet@gmail.com> | 2019-02-02 22:59:54 -0500 |
commit | 379c2c17e68d5d471a6a9673b7e9cd1fb9d99bbb (patch) | |
tree | eed499da8211a5eece757639331a2d82bce4fa4c /pgm5 | |
download | csci415-master.tar.xz csci415-master.zip |
Diffstat (limited to 'pgm5')
-rw-r--r-- | pgm5/counter.c | 690 | ||||
-rw-r--r-- | pgm5/makefile | 11 | ||||
-rw-r--r-- | pgm5/p5test/file0 | 17 | ||||
-rw-r--r-- | pgm5/p5test/file1 | 2 | ||||
-rw-r--r-- | pgm5/p5test/file2 | 3 | ||||
-rw-r--r-- | pgm5/p5test/file3 | 9 | ||||
-rw-r--r-- | pgm5/p5test/file4 | 5 | ||||
-rw-r--r-- | pgm5/p5test/file5 | 11 | ||||
-rw-r--r-- | pgm5/p5test/file6 | 1 | ||||
-rw-r--r-- | pgm5/prodcons.d/Makefile | 10 | ||||
-rw-r--r-- | pgm5/prodcons.d/README | 2 | ||||
-rw-r--r-- | pgm5/prodcons.d/prodcons.c | 124 | ||||
-rw-r--r-- | pgm5/run.sh | 13 |
13 files changed, 898 insertions, 0 deletions
diff --git a/pgm5/counter.c b/pgm5/counter.c new file mode 100644 index 0000000..26735b4 --- /dev/null +++ b/pgm5/counter.c @@ -0,0 +1,690 @@ +/* + * counter.c + * Adam Carpenter - 2017 - acarpent - acarpenter@email.wm.edu + * Utilizes code from P. Kearns + * Utilizes code from linuxthreads demonstration "prodcons.c" + */ + + +// **** Library inclusions **** +#include<errno.h> +#include<pthread.h> +#include<stdio.h> +#include<stdlib.h> +#include<string.h> +#include<time.h> +#include<unistd.h> + + +// **** Definitions for counter **** +#define FALSE 0 +#define LEN_LINE 2048 +#define LEN_FILENAME 4096 +#define MAX_THREADS 26 +#define TRUE 1 +#define USAGE "counter: usage: counter -b num_lines -t max_counters -d file_delay -D thread_delay [file]...\n" + + +// **** Structure declarations **** +struct prodConBuff { + /* + * struct prodConBuff + */ + pthread_mutex_t bufferLock;// Mutex ensures exclusive access to buffer. + int readPos; // Position for reading. + int writePos; // Position for writing. + pthread_cond_t notEmpty; // Signaled when buffer isn't empty. + pthread_cond_t notFull; // Signaled when buffer isn't full. + // char *lines[]; + char **lines; // Array of strings serves as data container. +}; + +struct NODE { + /* + * struct NODE + */ + char *word; // char *word or word[LEN_LINE] + long count; + struct NODE *next; +}; + +struct linkedList { + /* + * struct linkedList + */ + pthread_mutex_t listLock; // Mutex ensures exclusive access to linked list. + struct NODE *head; // Pointer to first node in list. +}; + + +// **** Global variables **** +static char nextThread; +static int fileDelay; +static int maxCounters; +static int moreStuff; +static int numLines; +static int threadDelay; +static pthread_t threadPool[MAX_THREADS]; // Bad Threadpool. +struct prodConBuff buffer; +struct linkedList evenList; +struct linkedList oddList; + + +// **** Structure initializations **** +static void initBuffer(struct prodConBuff *buffer) { + /* + * initBuffer() initializes the buffer structure to an empty array ready for + * producer-consumer actions. + * The buffer of lines is initialized to NULL. As the program runs, if + * slots are empty they will be malloc'd to fit given lines being inserted + * into the buffer, and freed as they are taken out. + */ + int i; + + pthread_mutex_init(&buffer->bufferLock, NULL); + pthread_cond_init(&buffer->notEmpty, NULL); + pthread_cond_init(&buffer->notFull, NULL); + buffer->readPos = 0; + buffer->writePos = 0; + buffer->lines = (char **) calloc(numLines, LEN_LINE); + + for (i = 0; i < numLines; i++) { + buffer->lines[i] = (char *) calloc(LEN_LINE, sizeof(char)); + } + + if (numLines == 1) { + buffer->lines[0][0] = '\0'; + } +} + +static void initLinkedList(struct linkedList *list) { + /* + * initLinkedList() initializes the linked list structure (its lock and its + * head node.) + */ + pthread_mutex_init(&list->listLock, NULL); + list->head = NULL; +} + + +// **** Modifier and thread functions **** +static void sleeper(const struct timespec *req, struct timespec *rem) { + // Researched methods of maintaining nanosleep times online and + // found an interesting method using recursion that was similar to this. + + struct timespec newRem; + + if (nanosleep(req, rem) < 0) { + sleeper(rem, &newRem); + } + +} + +static void quitThread() { + /* + * quitThread() + */ + #ifdef atcdebug + fprintf(stderr, "counter: thread quit because no more stuff.\n"); + #endif + + nextThread--; + pthread_exit(NULL); +} + +static int putInBuffer(struct prodConBuff *buffer, char *line) { + /* + * putInBuffer() + */ + int newThread; + + newThread = FALSE; + pthread_mutex_lock(&buffer->bufferLock); + + // If buffer is full, spawn a new counter thread. + if ((buffer->writePos + 1) % numLines == buffer->readPos) { + newThread = TRUE; + } + + // Wait until buffer isn't full anymore. + while ((buffer->writePos + 1) % numLines == buffer->readPos) { + pthread_cond_wait(&buffer->notFull, &buffer->bufferLock); + + #ifdef atcdebug + fprintf(stderr, "reader: waiting for space...\n"); + #endif + } + + #ifdef atcdebug + fprintf(stderr, "reader: gonna insert in slot: %d\n", buffer->writePos); + #endif + + // Copy the text into the next slot in the buffer. + strncpy(buffer->lines[buffer->writePos], line, LEN_LINE); + buffer->writePos++; + + if (buffer->writePos >= numLines) { + buffer->writePos = 0; + } + + #ifdef atcdebug + fprintf(stderr, "reader: buffer is now: { "); + int i; + for (i = 0; i < numLines; i++) { + if (i == buffer->writePos) { + fprintf(stderr, "*"); + + } + + fprintf(stderr, "%s ", buffer->lines[i]); + + } + fprintf(stderr, "}\n\n"); + #endif + + // Signal buffer isn't empty anymore and unlock mutex. + pthread_cond_signal(&buffer->notEmpty); + pthread_mutex_unlock(&buffer->bufferLock); + return newThread; +} + +static int putInSingleBuffer(struct prodConBuff *buffer, char *line) { + /* + * putInSingleBuffer(0) + */ + int newThread; + + pthread_mutex_lock(&buffer->bufferLock); + newThread = FALSE; + + // If slot is taken, spawn a new counter thread + if (buffer->lines[0][0] != '\0') { + newThread = TRUE; + } + + // Wait until slot isn't full anymore. + while (buffer->lines[0][0] != '\0') { + pthread_cond_wait(&buffer->notFull, &buffer->bufferLock); + } + + // Insert line into buffer. + strncpy(buffer->lines[buffer->writePos], line, LEN_LINE); + + // Signal buffer slot isn't empty anymore and unlock mutex. + pthread_cond_signal(&buffer->notEmpty); + pthread_mutex_unlock(&buffer->bufferLock); + return newThread; +} + +static void getFromBuffer(struct prodConBuff *buffer, char *line) { + /* + * getFromBuffer() + */ + + pthread_mutex_lock(&buffer->bufferLock); + + // If buffer is 'empty' and nothing more will be written, quit. + if (!moreStuff && buffer->readPos == buffer->writePos) { + quitThread(); + } + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + + // Wait until buffer isn't empty anymore. + while (buffer->readPos == buffer->writePos) { + #ifdef atcdebug + fprintf(stderr, "counter: waiting for stuff...\n"); + #endif + + pthread_cond_wait(&buffer->notEmpty, &buffer->bufferLock); + } + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + + #ifdef atcdebug + fprintf(stderr, "counter: getting from slot: %d\n", buffer->readPos); + #endif + + // Get line from buffer and advance read position. + strncpy(line, buffer->lines[buffer->readPos], LEN_LINE); + buffer->readPos++; + if (buffer->readPos >= numLines) buffer->readPos = 0; + + #ifdef atcdebug + fprintf(stderr, "counter: buffer is now: { "); + int i; + for (i = 0; i < numLines; i++) { + if (i == buffer->readPos) { + fprintf(stderr, "*"); + + } + + fprintf(stderr, "%s ", buffer->lines[i]); + + } + fprintf(stderr, "}\n\n"); + #endif + + // Signal buffer isn't full anymore and unlock mutex. + pthread_cond_signal(&buffer->notFull); + pthread_mutex_unlock(&buffer->bufferLock); +} + +static void getFromSingleBuffer(struct prodConBuff *buffer, char *line) { + /* + * getFromSingleBuffer(); + */ + + pthread_mutex_lock(&buffer->bufferLock); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + + // Wait until buffer isn't empty anymore. + while (buffer->lines[0][0] == '\0') { + + // If buffer slot is empty and nothing more will be written to it, quit. + if ((buffer->lines[0][0] == 0) && !moreStuff) { + quitThread(); + } + + pthread_cond_wait(&buffer->notEmpty, &buffer->bufferLock); + } + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + + // Get line from buffer slot. + strncpy(line, buffer->lines[0], LEN_LINE); + buffer->lines[0][0] = '\0'; + + // Signal buffer slot isn't full anmore and unlock mutex. + pthread_cond_signal(&buffer->notFull); + pthread_mutex_unlock(&buffer->bufferLock); +} + +static void putInList(struct linkedList *list, char *word) { + /* + * putInList() + */ + struct NODE *current; + struct NODE *new; + + pthread_mutex_lock(&list->listLock); + + #ifdef atcdebug + fprintf(stderr, "counter: gonna insert into list\n"); + #endif + + if (list->head == NULL) { + new = (struct NODE *) malloc(sizeof(struct NODE)); + new->word = (char *) malloc(strlen(word)); + strcpy(new->word, word); + new->count = 1; + list->head = new; + } + else { + + for (current = list->head; current != NULL; current = current->next) { + + if (strcmp(current->word, word) == 0) { + // Word already in list; update count. + current->count++; + break; + } + else if (current->next != NULL + && strcmp(word, current->next->word) < 0) { + // Insert in front of next-greatest lexiographical word. + new = (struct NODE *) malloc(sizeof(struct NODE)); + new->word = (char *) malloc(strlen(word)); + strcpy(new->word, word); + new->count = 1; + new->next = current->next; + current->next = new; + break; + } + else if (current->next == NULL) { + // Reached the end; Insert at back of list. + new = (struct NODE *) malloc(sizeof(struct NODE)); + new->word = (char *) malloc(strlen(word)); + strcpy(new->word, word); + new->count = 1; + new->next = NULL; + current->next = new; + break; + } + + } + + } + + #ifdef atcdebug + fprintf(stderr, "counter: list is now: {"); + current = list->head; + while (current != NULL) { + fprintf(stderr, "%s->", current->word); + current = current->next; + } + fprintf(stderr, "}\n\n"); + #endif + + pthread_mutex_unlock(&list->listLock); +} + +static void printList(struct linkedList *list) { + /* + * printList() + */ + struct NODE *current; + + // For debugging purposes and future implementations, lock the list. + pthread_mutex_lock(&list->listLock); + + // Print the word of every node in the list. + for (current = list->head; current != NULL; current = current->next) { + printf("Count: %ld Word: %s\n", current->count, current->word); + } + + pthread_mutex_unlock(&list->listLock); +} + +static void freeList(struct linkedList *list) { + /* + * freeList() + */ + struct NODE *current; + struct NODE *temp; + + // For debugging purposes and future implementations, lock the list. + pthread_mutex_lock(&list->listLock); + + // Free every node in the list. + while (current != NULL) { + temp = current; + current = current->next; + free(temp); + } + + pthread_mutex_unlock(&list->listLock); +} + +static void * counterThread(void * arg) { + /* + * counterThread() + */ + char name; + char line[LEN_LINE]; + char *token; + struct timespec requestedTime; + struct timespec remainingTime; + + name = (char) arg; + requestedTime.tv_sec = threadDelay / 1000; + requestedTime.tv_nsec = threadDelay % 1000 * 1000000; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + + #ifdef atcdebug + fprintf(stderr, "counter: name == %c, numLines == %d, threadDelay == %d\n", name, numLines, threadDelay); + #endif + + while (TRUE) { + + // Sleep for allotted time. + sleeper(&requestedTime, &remainingTime); + + if (numLines == 1) { + getFromSingleBuffer(&buffer, line); + } + else { + getFromBuffer(&buffer, line); + } + + // Get the first word in the line. + token = strtok(line, " "); + + // With each word, see if there are an even or odd number of characters + // and insert the word into the designated list. Then print the name + // of the thread on stdout. + while (token != NULL) { + + if (strlen(token) % 2 == 0) { + putInList(&evenList, token); + + #ifndef atcdebug + printf("%c ", name); + #endif + + } + else { + putInList(&oddList, token); + + #ifndef atcdebug + printf("%c ", name); + #endif + + } + + token = strtok(NULL, " "); + } + + } + + return NULL; +} + +static void createThread() { + /* + * createThread() + */ + + // Would a new thread put us over the maximum allowed? + // If not, create another counter thread as requested. + + if (((nextThread - 'a') < maxCounters)) { + #ifdef atcdebug + fprintf(stderr, "reader: creating thread, name == %c\n", nextThread); + #endif + + pthread_create(&threadPool[nextThread - 'a'], NULL, counterThread, (void *) nextThread); + nextThread++; + } + +} + + +// **** Main **** +int main(int argc, char *argv[]) { + /* + * main() acts as the reader thread, and therefore the producer. + */ + char line[LEN_LINE]; + int i; + FILE *textFile; + struct timespec requestedTime; + struct timespec remainingTime; + + // Get command line args. + if (argc < 10) { + fprintf(stderr, USAGE); + exit(1); + } + + numLines = maxCounters = fileDelay = threadDelay = -1; + i = 1; + errno = 0; + + while (argv[i] && i < 9) { + + // Get numLines. + if (strcmp(argv[i], "-b") == 0) { + i++; + + if (argv[i]) { + numLines = strtol(argv[i], NULL, 10); + + if (errno != 0 || numLines <= 0) { + fprintf(stderr, "counter: num_lines must be a positive, non-zero integer.\n"); + exit(1); + } + + } + else { + fprintf(stderr, USAGE); + exit(1); + } + + } + // Get maxCounters. + else if (strcmp(argv[i], "-t") == 0) { + i++; + + if (argv[i]) { + maxCounters = strtol(argv[i], NULL, 10); + + if (errno != 0 || maxCounters <= 0 || maxCounters > 26) { + fprintf(stderr, "counter: max_counters must be a positive, non-zero integer no greater than 26.\n"); + exit(1); + } + + } + else { + fprintf(stderr, USAGE); + exit(1); + } + + } + // Get fileDelay. + else if (strcmp(argv[i], "-d") == 0) { + i++; + + if (argv[i]) { + fileDelay = strtol(argv[i], NULL, 10); + + if (errno != 0 || fileDelay < 0) { + fprintf(stderr, "counter: file_delay must be a positive integer.\n"); + exit(1); + } + + } + else { + fprintf(stderr, USAGE); + exit(1); + } + + } + // Get threadDelay. + else if (strcmp(argv[i], "-D") == 0) { + i++; + + if (argv[i]) { + threadDelay = strtol(argv[i], NULL, 10); + + if (errno != 0 || threadDelay < 0) { + fprintf(stderr, "counter: thread_delay must be a positive integer.\n"); + exit(1); + } + + } + else { + fprintf(stderr, USAGE); + exit(1); + } + + } + else { + + if (numLines < 0 || maxCounters < 0 + || fileDelay < 0 || threadDelay < 0) { + fprintf(stderr, USAGE); + exit(1); + } + + } + + i++; + } + + #ifdef atcdebug + fprintf(stderr, "reader: numLines = %d, maxCounters = %d, fileDelay = %d, " + "threadDelay = %d\n", numLines, maxCounters, fileDelay, threadDelay); + #endif + + // Set up thread environment. + initBuffer(&buffer); + initLinkedList(&evenList); + initLinkedList(&oddList); + nextThread = 'a'; + moreStuff = TRUE; + + // Start up first counter (consumer) thread. + createThread(); + + // **** Reader (producer) thread **** + textFile = NULL; + requestedTime.tv_sec = threadDelay / 1000; + requestedTime.tv_nsec = threadDelay % 1000 * 1000000; + + while (argv[i]) { + + // Open each file given in argv[]. + if (!(textFile = fopen(argv[i], "r"))) { + fprintf(stderr, "counter: could not open %s\n", argv[i]); + } + else { + + // Read each line in the file and insert it into the buffer. + while (fgets(line, LEN_LINE, textFile)) { + // Strip newline. + line[strcspn(line, "\n")] = '\0'; + + if (numLines == 1) { + + // Attempt to create a new thread if function says + // buffer was full. + if (putInSingleBuffer(&buffer, line) == TRUE) { + createThread(); + } + + } + else { + + // Attempt to create a new thread if put function says + // buffer was full. + if (putInBuffer(&buffer, line) == TRUE) { + createThread(); + } + + } + + // Sleep for allotted time. + while (nanosleep(&requestedTime, &remainingTime) == -1) { + requestedTime = remainingTime; + } + + } + + fclose(textFile); + } + + i++; + } + + // Let counter threads know that there won't be any more input and wait + // for threads to finish before printing and terminating. + moreStuff = FALSE; + + sleep(2); + + for (i = 0; i < MAX_THREADS; i++) { + + if (threadPool[i]) { + pthread_cancel(threadPool[i]); + } + + } + + printf("\n==== Words with an even number of letters ====\n"); + printList(&evenList); + printf("\n==== Words with an odd number of letters ====\n"); + printList(&oddList); + freeList(&evenList); + freeList(&oddList); + exit(0); +} diff --git a/pgm5/makefile b/pgm5/makefile new file mode 100644 index 0000000..4de261f --- /dev/null +++ b/pgm5/makefile @@ -0,0 +1,11 @@ +all: counter + +counter: counter.c + gcc -D_REENTRANT -o counter counter.c -lpthread + +debug: counter.c + gcc -Wall -g -D_REENTRANT -Datcdebug -o counter counter.c -lpthread + +clean: + rm -f counter + gcc -D_REENTRANT -o counter counter.c -lpthread diff --git a/pgm5/p5test/file0 b/pgm5/p5test/file0 new file mode 100644 index 0000000..16d6515 --- /dev/null +++ b/pgm5/p5test/file0 @@ -0,0 +1,17 @@ +a +aa +aaa +aaaa +aaaaa +aaaaaa +aaaaaaa +aaaaaaaa +aaaaaaaaa +aaaaaaaaaa +aaaaaaaaaaa +aaaaaaaaaaaa +aaaaaaaaaaaaa +aaaaaaaaaaaaaa +aaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaa diff --git a/pgm5/p5test/file1 b/pgm5/p5test/file1 new file mode 100644 index 0000000..f9a742d --- /dev/null +++ b/pgm5/p5test/file1 @@ -0,0 +1,2 @@ +a a a a a a +a a a a diff --git a/pgm5/p5test/file2 b/pgm5/p5test/file2 new file mode 100644 index 0000000..0fd6f48 --- /dev/null +++ b/pgm5/p5test/file2 @@ -0,0 +1,3 @@ +aa aa aa aa aa +aa aa aa +aa aa diff --git a/pgm5/p5test/file3 b/pgm5/p5test/file3 new file mode 100644 index 0000000..5234a25 --- /dev/null +++ b/pgm5/p5test/file3 @@ -0,0 +1,9 @@ +aaa aaa aaa aaa aaa +aaa +aaa + +aaa +aaa +aaa + + diff --git a/pgm5/p5test/file4 b/pgm5/p5test/file4 new file mode 100644 index 0000000..29c981d --- /dev/null +++ b/pgm5/p5test/file4 @@ -0,0 +1,5 @@ +aaaa aaaa +aaaa aaaa +aaaa aaaa +aaaa aaaa +aaaa aaaa diff --git a/pgm5/p5test/file5 b/pgm5/p5test/file5 new file mode 100644 index 0000000..6976d6b --- /dev/null +++ b/pgm5/p5test/file5 @@ -0,0 +1,11 @@ +aaaaa +aaaaa +aaaaa +aaaaa +aaaaa +aaaaa +aaaaa +aaaaa +aaaaa +aaaaa + diff --git a/pgm5/p5test/file6 b/pgm5/p5test/file6 new file mode 100644 index 0000000..abc805a --- /dev/null +++ b/pgm5/p5test/file6 @@ -0,0 +1 @@ +aaaaaa aaaaaa aaaaaa aaaaaa aaaaaa aaaaaa aaaaaa aaaaaa aaaaaa aaaaaa diff --git a/pgm5/prodcons.d/Makefile b/pgm5/prodcons.d/Makefile new file mode 100644 index 0000000..174975d --- /dev/null +++ b/pgm5/prodcons.d/Makefile @@ -0,0 +1,10 @@ +CC=gcc +CFLAGS=-g -Wall -D_REENTRANT +LIBS=-lpthread + +prodcons: prodcons.c + $(CC) $(CFLAGS) -o prodcons prodcons.c $(LIBS) + +clean: + rm -f prodcons core.* + diff --git a/pgm5/prodcons.d/README b/pgm5/prodcons.d/README new file mode 100644 index 0000000..3c85ac4 --- /dev/null +++ b/pgm5/prodcons.d/README @@ -0,0 +1,2 @@ +Producer/Consumer with a bounded buffer. From the +linuxthreads demos. diff --git a/pgm5/prodcons.d/prodcons.c b/pgm5/prodcons.d/prodcons.c new file mode 100644 index 0000000..665c744 --- /dev/null +++ b/pgm5/prodcons.d/prodcons.c @@ -0,0 +1,124 @@ +/* The classic producer-consumer example. + Illustrates mutexes and conditions. + All integers between 0 and 9999 should be printed exactly twice, + once to the right of the arrow and once to the left. */ + +#include <stdio.h> +#include <pthread.h> + +#define BUFFER_SIZE 16 + +/* Circular buffer of integers. */ + +struct prodcons +{ + int buffer[BUFFER_SIZE]; /* the actual data */ + pthread_mutex_t lock; /* mutex ensuring exclusive access to buffer */ + int readpos, writepos; /* positions for reading and writing */ + pthread_cond_t notempty; /* signaled when buffer is not empty */ + pthread_cond_t notfull; /* signaled when buffer is not full */ +}; + +/* Initialize a buffer */ +static void +init (struct prodcons *b) +{ + pthread_mutex_init (&b->lock, NULL); + pthread_cond_init (&b->notempty, NULL); + pthread_cond_init (&b->notfull, NULL); + b->readpos = 0; + b->writepos = 0; +} + +/* Store an integer in the buffer */ +static void +put (struct prodcons *b, int data) +{ + pthread_mutex_lock (&b->lock); + /* Wait until buffer is not full */ + while ((b->writepos + 1) % BUFFER_SIZE == b->readpos) + { + pthread_cond_wait (&b->notfull, &b->lock); + /* pthread_cond_wait reacquired b->lock before returning */ + } + /* Write the data and advance write pointer */ + b->buffer[b->writepos] = data; + b->writepos++; + if (b->writepos >= BUFFER_SIZE) + b->writepos = 0; + /* Signal that the buffer is now not empty */ + pthread_cond_signal (&b->notempty); + pthread_mutex_unlock (&b->lock); +} + +/* Read and remove an integer from the buffer */ +static int +get (struct prodcons *b) +{ + int data; + pthread_mutex_lock (&b->lock); + /* Wait until buffer is not empty */ + while (b->writepos == b->readpos) + { + pthread_cond_wait (&b->notempty, &b->lock); + } + /* Read the data and advance read pointer */ + data = b->buffer[b->readpos]; + b->readpos++; + if (b->readpos >= BUFFER_SIZE) + b->readpos = 0; + /* Signal that the buffer is now not full */ + pthread_cond_signal (&b->notfull); + pthread_mutex_unlock (&b->lock); + return data; +} + +/* A test program: one thread inserts integers from 1 to 10000, + the other reads them and prints them. */ + +#define OVER (-1) + +struct prodcons buffer; + +static void * +producer (void *data) +{ + int n; + for (n = 0; n < 10000; n++) + { + printf ("%d --->\n", n); + put (&buffer, n); + } + put (&buffer, OVER); + return NULL; +} + +static void * +consumer (void *data) +{ + int d; + while (1) + { + d = get (&buffer); + if (d == OVER) + break; + printf ("---> %d\n", d); + } + return NULL; +} + +int +main (void) +{ + pthread_t th_a, th_b; + void *retval; + + init (&buffer); + /* Create the threads */ + pthread_create (&th_a, NULL, producer, 0); + pthread_create (&th_b, NULL, consumer, 0); + /* Wait until producer and consumer finish. */ + pthread_join (th_a, &retval); + pthread_join (th_b, &retval); + return 0; +} diff --git a/pgm5/run.sh b/pgm5/run.sh new file mode 100644 index 0000000..7d75216 --- /dev/null +++ b/pgm5/run.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +make +cp -f counter p5test/counter +cd p5test + +./counter -b 4 -t 1 -d 0 -D 0 file0 +./counter -b 2 -t 2 -d 1000 -D 1000 file0 +./counter -b 10 -t 1 -d 0 -D 0 /usr/share/fortune/linuxcookie +./counter -b 2 -t 26 -d 0 -D 0 /usr/share/fortune/linuxcookie +./counter -b 2 -t 10 -d 0 -D 0 /usr/share/fortune/linuxcookie +./counter -b 2 -t 10 -d 0 -D 0 file{1,2,3,4,5,6} +./counter -b 1 -t 1 -d 0 -D 0 /usr/share/fortune/linuxcookie |