Commit e5aea0c1 authored by cdf009's avatar cdf009

is this working?

parent b3773772
Create a file called answers.txt in which you explain why rand_r is thread safe.
Rand_r() will return a psuedo-random intger from 0 to the preset max. The rand_r will take in a unsigned integer which is named the seed. The argument is a pointer to the seed for the sequence of random numbers. When you call the rand_r with the same seed value you will recieve the same sequence. The rand_r does not change or read in anything other than the arguments. The rand_r will ensure that different threads use different seed arguments.
/*
* Copyright (c) 2013 Bucknell University
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: L. Felipe Perrone (perrone@bucknell.edu)
*/
#ifndef _CIRCULAR_LIST_H_
#define _CIRCULAR_LIST_H_
#include <semaphore.h>
#include <pthread.h>
typedef double item;
/** Circular list ADT. This circular list is implemented as a
* bounded buffer for use in multi-threaded applications.
*/
struct circular_list {
int start; /// index of the first occupied position in buffer
int end; /// index of the last occupied position in buffer
int elems; /// number of elements currently held in buffer
int size; /// capacity of the buffer
item *buffer; /// array of buffer items
pthread_mutex_t lock;
sem_t full;
sem_t empty;
};
/**
* Create a circular list with a pre-defined buffer size.
* @param l pointer to a circular list ADT
* @param size number of items to allocate in circular list
* @return 0 if successful, -1 if any error condition is found
*/
int circular_list_create(struct circular_list *l, int size);
/**
* Insert item into the circular list.
* @param l pointer to a circular list ADT
* @param i item to copy into a position of the circular list
* @return 0 if successful, -1 if any error condition is found
*/
int circular_list_insert(struct circular_list *l, item i);
/**
* Remove item from the circular list.
* @param l pointer to a circular list ADT
* @param i pointer to an item onto which the removed item is copied
* @return 0 if successful, -1 if any error condition is found
*/
int circular_list_remove(struct circular_list *l, item *i);
#endif /* _CIRCULAR_LIST_H_ */
......@@ -18,48 +18,95 @@
*/
#include <stdlib.h>
#include "circular-list.h"
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <semaphore.h>
#include "circular-list.h"
int circular_list_create(struct circular_list *l, int size) {
// mutex initialization
pthread_mutex_init(&l->lock, NULL);
//semaphores
sem_init(&l->empty, 0, size);
sem_init(&l->full, 0, 0);
l->buffer = calloc(size, sizeof(item));
l->start = 0;
l->end = 0;
l->start = -1;
l->end = -1;
l->elems = 0;
l->size = size;
return 0;
}
int circular_list_insert(struct circular_list *l, item i) {
//semaphore
sem_wait(&l->empty);
//mutex
pthread_mutex_lock(&l->lock);
if(l->elems == l->size ){ //
return -1;
}
else {
}
if (l->elems == 0){
l->end = 0;
}
l->start += 1;
if (l->start == l->size){
l->start = 0;
}
//int len = l->size;
l->buffer[l->end] = i;
l->buffer[l->start] = i;
//l->end += 1;
l->end = (l->end+1) % l->size;
//l->end = (l->end+1) % l->size;
l->elems += 1;
//mutex
pthread_mutex_unlock(&l->lock);
//semaphore
sem_post(&l->full);
return 0;
}
}
int circular_list_remove(struct circular_list *l, item *i) {
if(l->end == 0){
//semaphore
sem_wait(&l->full);
//mutex
pthread_mutex_lock(&l->lock);
if(l->elems == 0){
printf("Empty List!!!");
return -1;
}
l->elems -= 1;
// else{
*i = l->buffer[l->start];
*i = l->buffer[l->end];
//l->start += 1;
l->start = (l->start+1) % l->size;
l->elems -= 1;
l->buffer[l->end] = -1;
l->end += 1;
if(l->end == l->size){
l->end = 0;
}
return 0;
//}
//mutex
pthread_mutex_unlock(&l->lock);
//semaphore
sem_post(&l->empty);
return *i;
}
/*
* Copyright (c) 2013 Bucknell University
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: L. Felipe Perrone (perrone@bucknell.edu)
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include "circular-list.h"
/* SCALE_FACTOR is a constant for you to experiment with:
* if you choose a very large SCALE_FACTOR, your threads
* might spend a long time sleeping. If you choose it to be
* too small, your threads will not sleep at all. Note
* that in the producer and consumer functions, the sleep
* time is computed as the INTEGER DIVISION below:
*
* usleep(SCALE_FACTOR * rand_r(&seed) / RAND_MAX
*
* where RAND_MAX is the largest random numver returned
* by rand_r. If the numerator is smaller than RAND_MAX,
* the quotient of the integer division is ZERO!
*/
#define SCALE_FACTOR 1000
// global variables -----------------------
struct circular_list mylist;
// end of global variables ----------------
void *producer (void *param) {
item i;
unsigned int *seed = (unsigned int *) param;
while (true) {
// sleep for random period of time
usleep(SCALE_FACTOR * (rand_r(seed)) / RAND_MAX);
// generate a random number
i = (item) (((double) (rand_r(seed))) / RAND_MAX);
if (circular_list_insert(&mylist, i) == -1) {
printf("PRODUCER: error condition\n");
} else {
printf("PRODUCER: produced value %lf\n", i);
}
}
}
void *consumer (void *param) {
item i;
//unsigned int seed = 999;
unsigned int *seed = (unsigned int *) param;
while (true) {
// sleep for random period of time
usleep(SCALE_FACTOR * (rand_r(seed)) / RAND_MAX);
if (circular_list_remove(&mylist, &i) == -1) {
printf("CONSUMER: error condition\n");
} else {
printf("CONSUMER: consumed value %lf\n", i);
}
}
}
int main (int argc, char *argv[]) {
// get command line arguments
//strcopy(producer, argv[1]);
//strcopy(consumer, argv[2]);
//strcopy(usleep, argv[3]);
int num_producers = atoi(argv[1]);
int num_consumers = atoi(argv[2]);
int sleep_time = atoi(argv[3]);
// if error in command line argument usage, terminate with helpful
// message
if (argc < 4){
printf("Not enough arugments!!! Format: prodcons num_prod num_cons sleep_time");
exit(-1);
}
// initialize buffer
circular_list_create(&mylist, 20);
// create producer thread(s)
int prodt;
pthread_t prod_tid[num_producers];
int prod_seed[num_producers];
for (prodt = 0; prodt < num_producers; prodt++) {
prod_seed[prodt] = prodt + 400;
pthread_create(&prod_tid[prodt], NULL, producer, &prod_seed[prodt]);
}
// create consumer thread(s)
pthread_t con_tid[num_consumers];
int cont_seed[num_consumers];
for (prodt = 0; prodt < num_consumers; prodt++) {
cont_seed[prodt] = prodt + 400;
pthread_create(&con_tid[prodt], NULL, consumer, &cont_seed[prodt]);
}
// sleep to give time for threads to run
sleep(sleep_time);
// exit
return (0);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment