program in C reader-writer using semaphore - c

I have been trying to execute this program in C.
I used the following commands to compile and run the code:
gcc -o rw rw.c -lpthread
./rw ricr ricb roocr roocb wicr wicb woocr woocb nr nw
I am getting the following warning on the following command gcc -o rw rw.c -lpthread:
I am getting the following output from this command
./rw ricr ricb roocr roocb wicr wicb woocr woocb nr nw:
The above picture shows the output which is incorrect.
Required output:
enter the number of readers : (user entering some number)
enter the number of writers : (user entering some number of writers)
and output.
I have not been getting the desired output and hence need some help.
Thank you in advance.
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#define RANGE 1000000000
#define BASE 500000000
int rICrange = RANGE;
int rICbase = BASE;
int rOOCrange = RANGE;
int rOOCbase = BASE;
int wICrange = RANGE;
int wICbase = BASE;
int wOOCrange = RANGE;
int wOOCbase = BASE;
int keepgoing = 1;
int totalReads = 0;
int totalWrites = 0;
int read_count = 0;
sem_t mutex, rw_mutex;
void threadSleep(int range, int base) {
struct timespec t;
t.tv_sec = 0;
t.tv_nsec = (rand() % range) + base;
nanosleep(&t, 0);
}
void *readers(void *args) {
int id = *((int *) args);
threadSleep(rOOCrange, rOOCbase);
while (keepgoing) {
sem_wait(&mutex);
totalReads++;
read_count++;
if(read_count == 1)
sem_wait(&rw_mutex);
sem_post(&mutex);
printf("Reader %d starting to read\n", id);
threadSleep(rICrange, rICbase);
printf("Reader %d finishing reading\n", id);
sem_wait(&mutex);
read_count--;
if(read_count == 0)
sem_post(&rw_mutex);
sem_post(&mutex);
threadSleep(rOOCrange, rOOCbase);
}
printf("Reader %d quitting\n", id);
}
void *writers(void *args) {
int id = *((int *) args);
threadSleep(wOOCrange, wOOCbase);
while (keepgoing) {
sem_wait(&rw_mutex);
totalWrites++;
printf("Writer %d starting to write\n", id);
threadSleep(wICrange, wICbase);
printf("Writer %d finishing writing\n", id);
sem_post(&rw_mutex);
threadSleep(wOOCrange, wOOCbase);
}
printf("Writer %d quitting\n", id);
}
int main(int argc, char **argv) {
int numRThreads = 0;
int numWThreads = 0;
if (argc == 11) {
rICrange = atoi(argv[1]);
rICbase = atoi(argv[2]);
rOOCrange = atoi(argv[3]);
rOOCbase = atoi(argv[4]);
wICrange = atoi(argv[5]);
wICbase = atoi(argv[6]);
wOOCrange = atoi(argv[7]);
wOOCbase = atoi(argv[8]);
numRThreads = atoi(argv[9]);
numWThreads = atoi(argv[10]);
}
else {
printf("Usage: %s <reader in critical section sleep range> <reader in critical section sleep base> \n\t <reader out of critical section sleep range> <reader out of critical section sleep base> \n\t <writer in critical section sleep range> <writer in critical section sleep base> \n\t <writer out of critical section sleep range> <writer out of critical section sleep base> \n\t <number of readers> <number of writers>\n", argv[0]);
exit(-1);
}
pthread_t RThreads[numRThreads];
pthread_t WThreads[numWThreads];
int R_id[numRThreads];
int W_id[numWThreads];
sem_init(&mutex, 0, 1);
sem_init(&rw_mutex, 0, 1);
int i;
for(i = 0; i < numRThreads; i++) {
R_id[i] = i + 1;
pthread_create(&RThreads[i], 0, readers, &R_id[i]);
}
for(i = 0; i < numWThreads; i++) {
W_id[i] = i + 1;
pthread_create(&WThreads[i], 0, writers, &W_id[i]);
}
char buf[256];
scanf("%s", &buf);
keepgoing = 0;
for(i = 0; i < numRThreads; i++)
pthread_join(RThreads[i], 0);
for(i = 0; i < numWThreads; i++)
pthread_join(WThreads[i], 0);
printf("Total number of reads: %d\nTotal number of writes: %d\n",
totalReads, totalWrites);
}

Related

Multithreading : busy waiting in producer-consumer problem

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <wait.h>
#include <pthread.h>
int item_to_produce, curr_buf_size;
int total_items, max_buf_size, num_workers, num_masters;
int consumed_items;
int *buffer;
pthread_mutex_t mutex;
pthread_cond_t has_data;
pthread_cond_t has_space;
void print_produced(int num, int master) {
printf("Produced %d by master %d\n", num, master);
}
void print_consumed(int num, int worker) {
printf("Consumed %d by worker %d\n", num, worker);
}
//consume items in buffer
void *consume_requests_loop(void *data)
{
int thread_id = *((int *)data);
while(1)
{
pthread_mutex_lock(&mutex); // mutex lock for consume
if(consumed_items == total_items) {
pthread_mutex_unlock(&mutex);
break;
}
while(curr_buf_size == 0) {
pthread_cond_wait(&has_data, &mutex);
}
print_consumed(buffer[(curr_buf_size--)-1], thread_id);
consumed_items++;
pthread_cond_signal(&has_space);
pthread_mutex_unlock(&mutex);
}
return 0;
}
//produce items and place in buffer
//modify code below to synchronize correctly
void *generate_requests_loop(void *data)
{
int thread_id = *((int *)data);
while(1) {
pthread_mutex_lock(&mutex); // mutex lock for consume
//all of items are produced
//master threads need to join
if(item_to_produce == total_items) {
pthread_mutex_unlock(&mutex);
break;
}
//there is no item to read
while (curr_buf_size == max_buf_size) {
pthread_cond_wait(&has_space, &mutex);
}
buffer[curr_buf_size++] = item_to_produce;
print_produced(item_to_produce, thread_id);
item_to_produce++;
pthread_cond_signal(&has_data);
pthread_mutex_unlock(&mutex); // mutex_produce unlock
}
return 0;
}
//write function to be run by worker threads
//ensure that the workers call the function print_consumed when they consume an item
int main(int argc, char *argv[])
{
int *master_thread_id; // array of master_thread_id
int *worker_thread_id; // array of worker_thread_id
pthread_t *master_thread; // array of master_thread
pthread_t *worker_thread; // array of worker_thread
item_to_produce = 0; // item will be produced by master_thread at next time
curr_buf_size = 0; // index of item will be saved in
consumed_items = 0;
int i;
if (argc < 5) {
printf("./master-worker #total_items #max_buf_size #num_workers #masters e.g. ./exe 10000 1000 4 3\n");
exit(1);
}
else {
num_masters = atoi(argv[4]);
num_workers = atoi(argv[3]);
total_items = atoi(argv[1]);
max_buf_size = atoi(argv[2]);
}
buffer = (int *)malloc (sizeof(int) * max_buf_size);
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&has_space, NULL);
pthread_cond_init(&has_data, NULL);
//create master producer threads
master_thread_id = (int *)malloc(sizeof(int) * num_masters);
master_thread = (pthread_t *)malloc(sizeof(pthread_t) * num_masters);
for (i = 0; i < num_masters; i++)
master_thread_id[i] = i;
for (i = 0; i < num_masters; i++)
pthread_create(&master_thread[i], NULL, generate_requests_loop, (void *)&master_thread_id[i]);
//create worker consumer threads
worker_thread_id = (int *)malloc(sizeof(int) * num_workers);
worker_thread = (pthread_t *)malloc(sizeof(pthread_t) * num_workers);
for (i = 0; i < num_workers; i++)
worker_thread_id[i] = i;
for (i = 0 ; i < num_workers; i++)
pthread_create(&worker_thread[i], NULL, consume_requests_loop, (void *)&worker_thread_id[i]);
//wait for all threads to complete
for (i = 0; i < num_masters; i++)
{
pthread_join(master_thread[i], NULL);
printf("master %d joined\n", i);
}
for (i = 0; i < num_workers; i++)
{
pthread_join(worker_thread[i], NULL);
printf("worker %d joined\n", i);
}
/*----Deallocating Buffers---------------------*/
free(buffer);
free(master_thread_id);
free(master_thread);
free(worker_thread_id);
free(worker_thread);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&has_data);
pthread_cond_destroy(&has_space);
return 0;
}
This code produces a number in the range of given numbers through the argument and consumes it.
But producer produces a number outside the range and doesn't join if it matches the condition. The consumer is too.
e.g when I give range of number like 0~39(total_item = 500), buff size 30(max_buf_size), num_workers 5, num_master 3, it doesn't produce and consume number only 0~39.
It produces and consumes numbers over 40.
In that way the thread is in a loop. To put the thread in sleep you can use, for example, the condition variables. (You can read this for more info https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_wait.html)

Using WinSCP/Putty and getting nonsense output file after running main.c

I have 3 files, a main.c, a makefile, and a h2o.h. I am using WinSCP for transferring files to an SSH, and using Putty for running the makefile. Everything compiles and outputs to a file I've called main.txt. However, that output is a bunch of nonsense characters.
For example:
ÿÿ1íI‰Ñ^H‰âHƒäðPTIÇÀà#
When it should output something like:
Thread 6 Oxygen has entered, waiting_H: 0, waiting_H: 0
Thread 7 Hydrogen has entered, waiting_H: 0, waiting_H: 0
Is there some sort of unencryption I have to write in to make my output readable?
I have included my code for all three files below.
Thanks
h2o.h:
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#ifndef NUM_THREADS
#define NUM_THREADS 10
#endif
extern const unsigned int RAND_RANGE;
typedef struct _thread_data_t {
int tid;//thread id
int waiting_O;//waiting Oxygen
int waiting_H;//waiting Hydrogen
} thread_data_t;
makefile:
all: main.c h2o.h
gcc -Wall -pthread -std=c99 -o main.txt main.c
chmod 755 main
clean:
-rm main
main.c
#include "h2o.h"
//the range of return values for getRandom() function is
//[-RAND_RANGE/2, RAND_RANGE/2]
const unsigned int RAND_RANGE = RAND_MAX>>10;
int waiting_O = 0;//number of oxygen waiting
int waiting_H = 0;//number of hydrogen waiting
sem_t a, b, mutex;
time_t t;
char debug = 0;//used to debug
int getRand();//returns a random int
void *oxygen(void *arg);//thread function for oxygen
void *hydrogen(void *arg);//thread function for hydrogen
void semwait(sem_t *sem);//error-checked semaphore wait
void semsignal(sem_t *sem);//error-checked semaphore signal
int main(int argc, char const *argv[]) {
pthread_t threads[NUM_THREADS];
thread_data_t thread_data[NUM_THREADS];
int errorCheck;//used to error check thread creation
//seed the random number generator
srand((unsigned int)time(&t));
//initialize semaphores
if (sem_init(&mutex, 0, (unsigned int)1) < 0
|| sem_init(&a, 0, (unsigned int)0) < 0
|| sem_init(&b, 0, (unsigned int)0) < 0) {
perror("sem_init");
exit(EXIT_FAILURE);
}
if (debug) {
/*
* debug mode:
* oxygen 1
* hydrogen 1
* hydrogen 1
*/
thread_data[0].tid = 0;
thread_data[0].waiting_O = 1;
pthread_create(&threads[0], NULL, oxygen, &thread_data[0]);
thread_data[1].tid = 1;
thread_data[1].waiting_H = 1;
pthread_create(&threads[1], NULL, hydrogen, &thread_data[1]);
thread_data[2].tid = 2;
thread_data[2].waiting_H = 1;
pthread_create(&threads[2], NULL, hydrogen, &thread_data[2]);
pthread_join(threads[0], NULL);
pthread_join(threads[1], NULL);
pthread_join(threads[2], NULL);
} else {
for (int i = 0; i < NUM_THREADS; i++) {
void *thread_func;//the function to call
thread_data[i].tid = i;//set thread id to current i value
if (rand()%2 == 0) {//if random amount < 0
thread_func = hydrogen;//make Oxygen
} else {//else amount > 0
thread_func = oxygen;//make hydrogen
}
if ((errorCheck = pthread_create(&threads[i], NULL, thread_func, &thread_data[i]))) {
fprintf(stderr, "error: pthread_create, %d\n", errorCheck);
return EXIT_FAILURE;
}
}
sleep(1);
for (int i = 0; i < NUM_THREADS; ++i) {
if ((errorCheck = pthread_join(threads[i], NULL))) {
fprintf(stderr, "error: pthread_join, %d\n", errorCheck);
}
}
/*
if ((errorCheck = pthread_join(finalThread, NULL))) {
fprintf(stderr, "error: pthread_join, %d\n", errorCheck);
}
*/
}
printf("All molecules crossed barrier...CLEANING UP!\n");
return EXIT_SUCCESS;
}
int getRand() {
return ((rand() % RAND_RANGE) - RAND_RANGE/2);
}
void *oxygen(void *arg) {
thread_data_t *data = (thread_data_t *)arg;
semwait(&mutex);
//waiting_O = waiting_O + data->amount;
fflush(stdout);
printf("Thread: %d oxygen proccess made\twaiting hydrogen: %d waiting oxygen: %d \n ", data->tid, data->waiting_H, data->waiting_O);
if (data->waiting_H >= 2) {
for(int i = 0; i<2; i++){
semsignal(&b);
printf("Thread %d oxygen released\n", data->tid); //if 2 hydrogen, release oxygen
fflush(stdout);
}
data->waiting_H -=2;//decrease hydrogen count by 2
semsignal(&mutex);
}
else {
data->waiting_O += 1;//if no 2 hydrogen, increase oxygen count by 1
semsignal(&mutex);
semwait(&a);
printf("Thread %d oxygen Waits\n", data->tid);
}
printf("Thread %d oxygen complete \n", data->tid);
pthread_exit(NULL);
}
void *hydrogen(void *arg) {
thread_data_t *data = (thread_data_t *)arg;
semwait(&mutex);
fflush(stdout);
printf("Thread %d hydrogen process made, waiting hydrogen: %d waiting oxygen: %d \n", data->tid, data->waiting_H, data->waiting_O);
if (data->waiting_H >= 1 && data->waiting_O >=1) { //if hydrogen 1 and oxygen 1, then can make h20
for(int i =0; i<2 ;i++){
semsignal(&b); //signals hydrogen
printf("Thread %d Hydrogen Released\n", data->tid);
fflush(stdout);
}
data->waiting_H -= 1;
semsignal(&a);
data->waiting_O -= 1;
semsignal(&mutex);
}
else {
data->waiting_H += 1;
semsignal(&mutex);
semwait(&b);
printf("Thread %d Hydrogen Waits \n", data->tid);
}
pthread_exit(NULL);
}
/*
* Error-checked semaphore wait.
*/
void semwait(sem_t *sem) {
if (sem_wait(sem) < 0) {
perror("sem_wait");
exit(EXIT_FAILURE);
}
}
/*
* Error-checked semaphore signal.
*/
void semsignal(sem_t *sem) {
if (sem_post(sem) < 0) {
perror("sem_post");
exit(EXIT_FAILURE);
}
}
the -o flag is for the output executable, not the output after the executable runs. The garbage you're seeing is the result of your text editor/cat attempting to interpret the compiled code as printable characters :)
Try this;
all: main.c h2o.h
gcc -Wall -pthread -std=c99 -o main main.c
chmod 755 main
clean:
-rm main
Then, in your Putty terminal;
> make all
> ./main > main.txt
Then your program's output should be in main.txt.

C: Using functions from a separate file

Trying to use a bounded buffer from a separate file that I've coded and it seems like that's where the code goes all crazy. Fairly new to C, and I was wondering if I am using the buffer the right way. The concept of instantiation isn't here, so if I just call one of the functions such as bbuff_blocking_insert will the array get initialized? How do I make the appropriate calls in order to get this working?
candy.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include "bbuff.h"
#include <stdbool.h>
#include <time.h>
_Bool stop_thread = false;
typedef struct {
int source_thread;
double time_stamp_in_ms;
} candy_t;
double current_time_in_ms (void) {
struct timespec now;
clock_gettime(CLOCK_REALTIME, &now);
return now.tv_sec * 1000.0 + now.tv_nsec/1000000.0;
}
void* createCandy(void* arg) {
int r;
int factoryNumber = *(int*)arg;
while(!stop_thread) {
r = rand() % 4;
printf("Random Number: %d\n", r);
printf("\tFactory %d ship candy & wait %ds\n", factoryNumber, r);
candy_t *candy = (candy_t*)malloc(sizeof(candy_t));
candy->source_thread = factoryNumber;
candy->time_stamp_in_ms = current_time_in_ms();
bbuff_blocking_insert((void *)candy);
sleep(r);
}
printf("Candy-factory %d done\n", factoryNumber);
return 0;
}
void* extractCandy(void* arg) {
int r;
candy_t* candy;
while(true) {
candy = (candy_t*)bbuff_blocking_extract();
printf("Candy Source Thread: %d\n", candy->source_thread);
r = rand() % 2;
sleep(r);
}
return 0;
}
int main(int argc, char* argv[]) {
//Extract Arguments
if (argc <= 1) {
printf("Insufficient Arguments\n");
exit(-1);
}
int NO_FACTORIES = atoi(argv[1]);
int NO_KIDS = atoi(argv[2]);
int NO_SECONDS = atoi(argv[3]);
bbuff_init();
//Spawn Factory Threads
pthread_t ftids[NO_FACTORIES];
int factoryNumber[NO_FACTORIES];
for (int i = 0; i < NO_FACTORIES; i++) {
factoryNumber[i] = i;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&ftids[i], &attr, createCandy, &factoryNumber[i]);
}
//Spawn Kid Threads
pthread_t ktids [NO_KIDS];
for (int i = 0; i < NO_KIDS; i++) {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&ktids[i], &attr, extractCandy, NULL);
}
//Wait for Requested Time
for (int i = 0; i < NO_SECONDS; i++) {
sleep(1);
printf("Time %ds\n", i+1);
}
//Stop Factory Threads
stop_thread = true;
for (int i = 0; i < NO_FACTORIES; i++) {
pthread_join(ftids[i], NULL);
}
//Wait until no more candy
while(bbuff_is_data_available()) {
printf("Waiting for all candy to be consumed");
sleep(1);
}
//Stop kid Threads
for (int i = 0; i < NO_KIDS; i++) {
pthread_cancel(ktids[i]);
pthread_join(ktids[i], NULL);
}
//Print Statistics
//Clean up any allocated memory
return 0;
}
bbuff.h
#ifndef BBUFF_H
#define BBUFF_H
#define QUEUE_SIZE 10
void bbuff_init(void);
void bbuff_blocking_insert(void* item);
void* bbuff_blocking_extract(void);
_Bool bbuff_is_data_available(void);
#endif
bbuff.c
#include "bbuff.h"
pthread_mutex_t mutex;
sem_t empty;
sem_t full;
int in = 0;
int out = 0;
int counter = 0;
void* buffer[QUEUE_SIZE];
void bbuff_init(void){
pthread_mutex_init(&mutex, NULL);
sem_init( &empty, 0, QUEUE_SIZE);
sem_init( &full, 0, 0);
}
void bbuff_blocking_insert(void* item) {
sem_wait(&empty);
pthread_mutex_lock(&mutex);
counter++;
buffer[in] = item;
in = (in+1) % QUEUE_SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&full);
}
void* bbuff_blocking_extract(void) {
void* extractedItem;
sem_wait(&full);
pthread_mutex_lock(&mutex);
counter--;
extractedItem = buffer[out];
buffer[out] = NULL;
out = out % QUEUE_SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&empty);
return extractedItem;
}
Output
$ ./candykids 1 1 10
Random Number: 3
Factory 0 ship candy & wait 3s
Candy Source Thread: 0
Time 1s
Time 2s
Random Number: 1
Factory 0 ship candy & wait 1s
Time 3s
Segmentation fault (core dumped)
In bbuff_blocking_extract(),
out = out % QUEUE_SIZE;
Should be:
out = (out+1) % QUEUE_SIZE;

fork()- multiple files accessed by parent & child processes

For educational purposes, I wrote a program that forks a process and ...
the child continuously reads 3 files, prints the contents, sleeps for 10ms.
the parent keeps a counter for each file. each file also has a delay time associated with it.
each time a file's timer expires, the counter is incremented and the file is overwritten with the
new counter value. Each delay value is different, so all 3 files get updated at different rates.
The problem is, the counters only increment for a short time, and everything freezes after a few seconds. Can anyone give a good explanation of what is happening here?
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#define CHAN1WAIT 100000
#define CHAN2WAIT 750000
#define CHAN3WAIT 1000000
#define NCHAN 3
FILE *chanfiles[NCHAN] = {NULL, NULL, NULL}; //file pointers for fake 'devices'
char *filenames[NCHAN] = {"_chan1tmpfile_", "_chan2tmpfile_", "_chan3tmpfile_"};
int chanwait[NCHAN] = {CHAN1WAIT, CHAN2WAIT, CHAN3WAIT}; //time it takes for each 'device' to be updated with a new value
int chancount[NCHAN] = {0, 0, 0}; //value for each device
int clrcount = NCHAN * 8;
uint8_t chan1;
int read_chan (int chan)
{
char buf[4];
char c;
int i, ret;
short count = 0;
uint8_t set = 0;
char * retstr;
while (! set)
{
if (chanfiles[chan] == NULL) //if file is not in use
{
if ((chanfiles[chan] = fopen(filenames[chan], "r")) == NULL)
{
printf("Error opening file %s for reading.\n%s\n", filenames[chan], strerror(errno));
exit(-1);
}
while ((c = fgetc(chanfiles[chan])) != EOF)
{
buf[count] = c;
count++;
}
fclose(chanfiles[chan]);
chanfiles[chan] = NULL;
retstr = malloc(count + 1);
for (i = 0; i < count; i++) retstr[i] = buf[i];
ret = atoi(retstr);
free(retstr);
set = 1;
}
}
return ret;
}
void write_chan (int chan)
{
uint8_t set = 0;
while (! set)
{
if (chanfiles[chan] == NULL) //if file is not in use
{
if ((chanfiles[chan] = fopen(filenames[chan], "w")) == 0)
{
printf("Error opening file %s for writing.\n%s\n", filenames[chan], strerror(errno));
exit(-1);
}
if (fprintf(chanfiles[chan], "%d", chancount[chan]) < 0)
{
printf("Error writing to file %s:\n%s\n", filenames[chan], strerror(errno));
exit(-1);
}
fclose(chanfiles[chan]);
chanfiles[chan] = NULL;
set = 1;
}
}
}
time_t get_usecs()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec + tv.tv_usec;
}
int main (int argc, char * argv[])
{
pid_t pid;
time_t curtime;
int i;
for (i = 0; i < NCHAN; i++) write_chan(i);
printf("\nChannel:");
for (i = 0; i < NCHAN; i++) printf("%8d", i);
printf("\n Value:");
pid = fork();
// This process reads all 3 files, prints the values,
// then sleeps for 10ms, in an infinite loop.
if (pid == 0)
{
int j;
while (1)
{
uint8_t set;
for (j = 0; j < NCHAN; j++)
{
int value;
set = 0;
value = read_chan(j);
printf("%8d", value);
}
fflush(stdout);
usleep(10000);
for (j = 0; j < clrcount; j++) printf("\b"); fflush(stdout);
}
}
// This process updates the values of all 3 files at
// different rates, based on the value in chanwait[]
// for each file.
else
{
time_t timers[NCHAN];
int i;
for (i = 0; i < NCHAN; i++) timers[i] = get_usecs();
while (1)
{
for (i = 0; i < NCHAN; i++)
{
if ((get_usecs() - timers[i]) >= chanwait[i])
{
chancount[i]++;
write_chan(i);
timers[i] = get_usecs();
}
}
}
}
}
I am not sure this is your only problem, but your get_usecs function is suspect. You probably meant this
return tv.tv_sec * 1000000 + tv.tv_usec;
Rather than
return tv.tv_sec + tv.tv_usec;
Although, note that time_t is only guaranteed to be large enough for the time in seconds, not the number of microseconds as you have used it.

Implementing basic semaphore to simple multi-threads program

Please help the Synchronization
I have to make this program to performe sequentially manner using
in threads( ex) thread1 performe and thread2 perforem and so on)
But it should be implemented only with Semaphore. I put in the wait(), Signal()
function to be act like semaphore(but not working)
You just need to see the pthread_join, and thread_work part
(the main purpose of this program : make 20threads and synchorinize them with semaphore)
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <stdlib.h>
#define num_thread 20
char str[11];
void *thread_work(void *tid); //Main body of Thread working
void generate_str(int n); //Create random character string
void str_sort(void); //Sorting the generated string into alpabet manner
void check_sort(void); //Check about "Is the sorting is right"
void print_time(struct timespec *myclock); //print the time interval of thread work
void print_time_program(struct timespec *myclock);
void wait(void); //I put in these two function to be act like semaphore
void Signal(void); //But it does't work
int S=1;
int main(void)
{
pthread_t tid[num_thread];
int rc;
int t;
struct timespec myclock[4];
srand(time(NULL));
clock_gettime(CLOCK_REALTIME, &myclock[2]);
for(t=0; t<num_thread; t++)
pthread_create(&tid[t], NULL, thread_work, (void *)&t);
for(t=0; t<num_thread; t++)
pthread_join(tid[t], NULL);
clock_gettime(CLOCK_REALTIME, &myclock[3]);
print_time_program(myclock);
return 0;
}
void *thread_work(void *t)
{
do
{
wait(); //Entry Section
//CRITICAL SECTION START
struct timespec myclock[2];
clock_gettime(CLOCK_REALTIME, &myclock[0]);
int n = *((int *)t);
printf("########## Thread #%d starting ########## \n", n);
generate_str(n);
str_sort();
check_sort();
printf("########## Thread #%d exiting ##########\n", n);
clock_gettime(CLOCK_REALTIME, &myclock[1]);
print_time(myclock);
//CRITICAL SECTION END
Signal();
pthread_exit(NULL);
}while (1);
}
void str_sort(void)
{
int temp;
int i, j;
for(i=0; i<9; i++)
for(j=0; j<9-i; j++)
{
if(str[j]>str[j+1])
{
temp=str[j];
str[j]=str[j+1];
str[j+1]=temp;
}
}
printf("Sorted string : %s ", str);
}
void generate_str(int n)
{
int i;
int num;
srand(n);
for(i=0; i<10; i++)
{
num = (97+rand()%26);
str[i]=num;
}
str[10]='\0';
printf("Initialized string : %s \n", str);
}
void check_sort(void)
{
int i;
int count=0;
for(i=0; i<9; i++)
{
if(str[i]>str[i+1])
count++;
}
if(count != 0)
printf("[X] FALSE \n");
else
printf("[O] TRUE \n");
}
void print_time(struct timespec *myclock)
{
long delay, temp, temp_n, sec;
sec = myclock[0].tv_sec % 60;
printf("Thread Starting Time : %ld.%ld second\n", sec, myclock[0].tv_nsec);
sec = myclock[1].tv_sec % 60;
printf("Thread Exiting Time : %ld.%ld second\n", sec, myclock[1].tv_nsec);
if (myclock[1].tv_nsec >= myclock[0].tv_nsec)
{
temp = myclock[1].tv_sec - myclock[0].tv_sec;
temp_n = myclock[1].tv_nsec - myclock[0].tv_nsec;
delay = 1000000000 * temp + temp_n;
}
else
{
temp = myclock[1].tv_sec - myclock[0].tv_sec - 1;
temp_n = 1000000000 + myclock[1].tv_nsec - myclock[0].tv_nsec;
delay = 1000000000 * temp + temp_n;
}
printf("Thread Working Time : %ld nano second", delay);
delay = delay / 1000000;
printf("(%ld ms)\n\n\n", delay);
return ;
}
void print_time_program(struct timespec *myclock)
{
long delay, temp, temp_n, sec;
sec = myclock[2].tv_sec % 60;
printf("Program Starting Time : %ld.%ld second\n", sec, myclock[2].tv_nsec);
sec = myclock[3].tv_sec % 60;
printf("Program Exiting Time : %ld.%ld second\n", sec, myclock[3].tv_nsec);
if (myclock[3].tv_nsec >= myclock[2].tv_nsec)
{
temp = myclock[3].tv_sec - myclock[2].tv_sec;
temp_n = myclock[3].tv_nsec - myclock[2].tv_nsec;
delay = 1000000000 * temp + temp_n;
}
else
{
temp = myclock[3].tv_sec - myclock[2].tv_sec - 1;
temp_n = 1000000000 + myclock[3].tv_nsec - myclock[2].tv_nsec;
delay = 1000000000 * temp + temp_n;
}
printf("Program Total Working Time : %ld nano second", delay);
delay = delay / 1000000;
printf("(%ld ms)\n\n\n", delay);
return ;
}
void wait(void)
{
while( S <= 0);
S--;
}
void Signal(void)
{
S++;
}
Here is a working example of how to make threads execute one after another using a semaphore (Linux/Cygwin pthreads):
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define NUM_THREADS 5
/* global thread exit control flag */
volatile uint32_t g_ExitFlag = 0;
/* global thread execution control semaphore */
sem_t g_Sem;
/* the thread function */
void *ThreadFunc(void *pContext)
{
uint32_t tid = (uint32_t)pContext;
/* main thread loop */
while (g_ExitFlag == 0)
{
/* wait for semaphore to be signalled */
sem_wait(&g_Sem);
printf("Thread %d running.\n", tid);
}
printf("Thread %d exiting.\n", tid);
return NULL;
}
int main(int argc, char *argv[])
{
uint32_t i = 0;
pthread_t th;
/* suppress warnings */
(void)argc;
(void)argv;
/* initialize the semaphore */
sem_init(&g_Sem, 0, 0);
/* create and detach several threads */
for (i = 0; i < NUM_THREADS; ++i)
{
pthread_create(&th, NULL, ThreadFunc, (void *)i);
pthread_detach(th);
}
/* run each thread four times and exit */
for (i = 0; i < (NUM_THREADS * 4); ++i)
{
if (i == 15)
{
g_ExitFlag = 1;
}
/* release a thread to execute */
sem_post(&g_Sem);
sleep(1);
}
return 0;
}
It should be straightforward for you to integrate that kind of functionality into your program.

Resources