Using semaphore for multithreading in C - c

The Idea here is to create a file to be written to. I'm trying to create ten threads and have them print to the file 10 times each. Using a semaphore to stop multiple threads from writing to the file at once. Everything compiles and I don't get an error exit, however I can't understand why running the program numerous times: 1)It doesn't print 100 lines to the file, infact it's far less 2) The number of lines printed to the file vary each time.
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define READ "r"
#define NEW "w"
#define ADD "a"
#define NL "\n"
#define TAB "\t"
#define FNAME "PROCTAB.txt"
#define MAX_STRING_LEN 80
#define NUMBER_OF_THREADS 10
FILE *fp;
sem_t mutex;
int counter;
FILE *makeTextFile(char *fname, char mode){
FILE *localFP;
localFP = fopen(fname, &mode);
return (localFP);
}
void *print_message(void *tid){
int i;
for (i = 0; i < 10; i++){
sem_wait(&mutex);
fp = fopen(FNAME, ADD);
fprintf(fp, "Thread %d is running.\n", tid);
fclose(fp);
sem_post(&mutex);
}
}
int threads(){
const char *fName = "PROCTAB.txt";
int status;
pthread_t threads[NUMBER_OF_THREADS];
fp = makeTextFile(FNAME, 'w');
fprintf(fp, "Process ID: %ld\n", (long)getpid());
fclose(fp);
int i;
for (i =0; i < NUMBER_OF_THREADS; i++){
status = pthread_create(&threads[i], NULL, &print_message, (void *)i);
if (status != 0){
printf("pthread_create returned error code %d\n", status);
exit(-1);
}
}
return 0;
}
My main function is contained in a separate file.

You need to wait for all thread to finish before you exit the program.
if you add trace you will see which thread is finish.
void *print_message(void *tid){
int i;
for (i = 0; i < 10; i++){
sem_wait(&mutex);
fp = fopen(FNAME, ADD);
fprintf(fp, "Thread %d is running.\n", tid);
fclose(fp);
sem_post(&mutex);
printf ( "Thread %d has finished.\n", tid);
}
}
This is how you wait for all threads to finish
/* Wait for Threads to Finish */
for (i=0; i<NUMTHREADS; i++) {
pthread_join(thread[i], NULL);
}

Related

Only three of my five threads are executing, synchronizing using mutexes

I am doing an academic exercise for an OS class where we synchronize five detached threads using ONLY mutex locks and unlocks. We "CANNOT force the threads into any serial execution. Once spawned they must be free from external influences (other than the mutexes). The parent should NOT employ a pthread_join."
I am spawning 5 threads, detaching them and then using each threads to read in data and update a global variable. Currently my code spawns the 5 threads but only three of them output their ID's and none of them get into the while loop. Any help/advice here would be appreciated!
Output:
thread: 6156515168
thread: 6156515192
thread: 6156515176
There is a sleep in main which if uncommented provides the expected output, but this would be forcing a serial execution..
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <pthread.h>
pthread_mutex_t mutex_lock = PTHREAD_MUTEX_INITIALIZER; // declaring mutex
int FileNameHelper=1;
int balance=0;
void* detatchedThread(void *param){
long tid = (long)param;
char* base = "data";
char filename[256];
char buf[100];
sprintf(filename, "%s%d.in", base, FileNameHelper); //creates data1.in, data2.in...
FileNameHelper ++;
FILE *inputFile = fopen(filename, "r");
printf ("thread: %ld\n", tid);
// critical sec line
if(fgets(buf, sizeof buf, inputFile) == NULL)
return NULL; // could not read first line
sleep(1); // make sure each thread runs long enough to get the random update behavior required.
pthread_mutex_lock(&mutex_lock); //we are in the critical section, lock mutex
while(fgets(buf, sizeof buf, inputFile) != NULL) {
int val;
if(sscanf(buf, "%d", &val) != 1){
break;
}
printf("%d\n", val);
balance += val;
printf ("Account balance after thread %ld is $%d\n", tid, balance);
}
pthread_mutex_unlock(&mutex_lock);
if(buf[0] != 'W')
return NULL;// last line data was invalid
pthread_exit(NULL);
}
int main(){
pthread_t th[5];
//initialize the mutex
if(pthread_mutex_init(&mutex_lock, NULL) != 0){
printf("\nmutex init has failed\n");
return 1;
}
//call the 5 threads, Detach the threads once they are created.
for (int i = 0; i < 5; i++){
pthread_create(&th[i], NULL, detatchedThread, (void *)&th[i]);
pthread_detach(th[i]);
//sleep(1); uncommenting this line gives me the expected behavior
}
pthread_mutex_destroy(&mutex_lock);
return 0;
}

getting free(): invalid size when executing code

compiling with gcc hw2.c -o x -lpthread
free(): invalid size
free(): invalid size
free(): invalid size
nano infile.txt
I'm assuming it has something to do with the file pointer maybe? the semaphores have been commented out to fix this issue first. All answers point to the pointer but switching things up isn't much help. I've tried compiling differently that doesn't help either.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>
//sem_t X;
void process(){
//sem_open("X", O_CREAT,0777,0);
int ret;
int N = 1;
pid_t pid;
FILE* infile = fopen ("infile.txt", "r");
for(int i = 0; i< 50; i++){
fscanf (infile, "%d", &N);
fclose (infile);
printf("N: %d Process ID: %d",N,pid);
infile = fopen("infile.txt", "w");
N++;
//sem_post(&X);
fprintf(infile,"%d",N);
fflush(infile);
fclose(infile);
}
printf("\n");
int c;
//sem_getvalue(&X,&c);
printf(" \n \n \n%d",c);
}
int main(){
int pid, pid1, pid2;
pid = fork();
if(pid == 0){
//child1, Last
printf("Starting Process C: ");
process();
}
else{
pid1 = fork();
if(pid1 == 0){
//child2, Middle
printf("Starting Process B: ");
process();
}
else{
pid2 = fork();
if(pid2 == 0){
//child 3, First
printf("Starting Process A: ");
process();
}
else{
}
}
}
//sem_close(&X);
//sem_unlink(&X);
}
The most obvious problem is in your loop. I've removed everything but the fopen and fclose calls:
FILE* infile = fopen ("infile.txt", "r");
for(int i = 0; i< 50; i++){
fclose (infile);
infile = fopen("infile.txt", "w");
fclose(infile);
}
As you probably now see, when i is 1, you try to fclose(infile) - but that isn't open, hence the errors you get.
You need to move the first fopen into the loop - and check that opening the file and reading from it succeeds too:
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
void process() {
int N = 1;
for(int i = 0; i < 50; i++) {
FILE* infile = fopen("infile.txt", "r");
if(infile) {
bool readok = fscanf(infile, "%d", &N) == 1;
fclose(infile);
if(readok) { /* only do this if a value was read from the file ok */
printf("N: %d Process ID: %d", N, getpid());
infile = fopen("infile.txt", "w");
if(infile) {
N++;
fprintf(infile, "%d", N);
fflush(infile);
fclose(infile);
}
}
}
}
printf("\n");
exit(0); /* terminate this sub process */
}
int main() {
const size_t kPids = 3;
pid_t pids[kPids]; /* simplify keeping a number of background processes */
for(size_t i = 0; i < kPids; ++i) {
pids[i] = fork();
if(pids[i] == 0) {
printf("Starting Process %c:\n", (char)('A' + i));
process();
}
}
/* wait for children to finish */
pid_t pid;
int wstatus;
while((pid = wait(&wstatus)) != -1) {
printf("pid %d is done with status %d\n", pid, wstatus);
}
}
Your loop is problematic
FILE* infile = fopen ("infile.txt", "r"); //1
for(int i = 0; i< 50; i++){
fscanf (infile, "%d", &N);
fclose (infile); //2
printf("N: %d Process ID: %d",N,pid);
infile = fopen("infile.txt", "w"); //3
N++;
//sem_post(&X);
fprintf(infile,"%d",N);
fflush(infile);
fclose(infile); //4
}
You open the file at 1, then enter the loop, close it at 2, re-open it at 3 and re-close it at 4. In the next iteration, when you attempt to close at 2, you would hit into a double-free as it's already been closed at 4.

Synchronization between Semaphore/Mutex and Printf

I'm working on an exercise (see bold text below) on semaphores and synchronization for my Operative System course. The text of the exercise is this:
Pthread semaphores and mutexes
The C program gen_binary_numbers.c receives on the command line an integer n, and uses recursion to generate and display all binary numbers of n bits.Transform the recursive program into a concurrent one, replacing the recursive procedure with the generation of an appropriate number of processes that display the binary numbers (in any order).
This is my code, actually:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
int num, r, c;
pthread_mutex_t mutex;
void *genBin(void *arg);
int main (int argc, char **argv) {
if (argc != 2) {
fprintf(stdout, "\nUSAGE: %s <n>\n\n", argv[0]);
exit(EXIT_FAILURE);
}
int i;
num = atoi(argv[1]);
c = num;
r = 2;
for (i=1; i<num; i++) {
r=r*2;
}
pthread_mutex_init(&mutex, NULL);
pthread_t* p;
p = malloc(r*sizeof(pthread_t));
for (i=0;i<r;i++) {
if (pthread_create(&p[i], NULL, genBin, &i)) {
fprintf(stderr, "Error creating thread.\n");
exit(EXIT_FAILURE);
}
}
pthread_exit(0);
}
void *genBin (void *arg) {
int x;
int i=0;
x = *((int*)arg);
pthread_mutex_lock(&mutex);
while (i<num) {
if(x!=0) {
fprintf(stdout, "%d", x%2);
}
else {
fprintf(stdout, "0");
}
i++;
x/=2;
}
fprintf(stdout, "\n");
pthread_mutex_unlock(&mutex);
pthread_exit(0);
}
I think that the code should return the right solution, but sometimes the output doesn't return the correct number.
Example of correct output:
./genBin 3
100
101
010
110
001
011
111
000
Example of wrong output (because of duplicates):
./genBin 3
110
110
110
001
011
111
111
000
I think that the problem is in the synchronization between the mutex and the printf.
Is there an alternative solution to avoid confusing results?
Your code contains a race condition. In main, you pass the address of your iteration variable, i, as the thread function's argument. Each new thread then races with the main thread to read the value of i (via the provided pointer) before the main thread increments it. One way you could address that problem would be to use a semaphore to make the main thread wait after creating each thread until that thread has dereferenced its argument.
Also, I don't think you need to use a mutex in genBin(). The only shared data it accesses is stdout, via fprintf(), and that function operates as if it locks an exclusive lock associated with the specified stream. Moreover, with the mutex you get essentially no actual concurrency because each thread holds the mutex locked for almost the complete duration of its execution.
The problem is in this part:
for (i=0;i<r;i++) {
if (pthread_create(&p[i], NULL, genBin, &i)) {
fprintf(stderr, "Error creating thread.\n");
exit(EXIT_FAILURE);
}
}
There's data race because you are passing the address of i to all threads. You could use an temp array to pass the individual number to each thread.
Thanks to everyone! You solved my problem. This is the corrected code:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
int num, r, c;
pthread_mutex_t mutex;
void *genBin(void *arg);
int main (int argc, char **argv) {
if (argc != 2) {
fprintf(stdout, "\nUSAGE: %s <n>\n\n", argv[0]);
exit(EXIT_FAILURE);
}
int i;
int *temp;
num = atoi(argv[1]);
c = num;
r = 2;
for (i=1; i<num; i++) {
r=r*2;
}
temp = malloc(r*sizeof(int));
pthread_mutex_init(&mutex, NULL);
pthread_t* p;
p = malloc(r*sizeof(pthread_t));
for (i=0;i<r;i++) {
temp[i] = i;
}
for (i=0;i<r;i++) {
if (pthread_create(&p[i], NULL, genBin, &temp[i])) {
fprintf(stderr, "Error creating thread.\n");
exit(EXIT_FAILURE);
}
}
for (i=0;i<r;i++) {
if (pthread_join(p[i], NULL)) {
fprintf(stderr, "Error creating thread.\n");
exit(EXIT_FAILURE);
}
}
pthread_mutex_destroy(&mutex);
free(temp);
free(p);
pthread_exit(0);
}
void *genBin (void *arg) {
int x;
int i=0;
int *v;
v = malloc(num*sizeof(int));
x = *((int*)arg);
for (i=0; i<num; i++) {
v[i] = x%2;
x/=2;
}
pthread_mutex_lock(&mutex);
for (i=0; i<num; i++) {
fprintf(stdout, "%d", v[i]);
}
fprintf(stdout, "\n");
pthread_mutex_unlock(&mutex);
free(v);
pthread_exit(0);
}

critical sections with eventfd and threads

I have bit of a problem which I can't seem to wrap my head around. I am trying to implement a program (for a uni class) which will have n numbers of trains and m numbers of train sations. However, since my number of stations can be less than the trains that are trying to access them, I would like to add a semaphore like mechanism to critical sections (which would be my train stations) but instead of using semaphores, we have to use eventfd in our os class.
Now the problem with my code (so far) seems to be that none of my train threads actually enters a station.
My code would be:
//Task 1 - sync via eventfd
//train example : 6 trains and just 3 alleys in a critical section -> train station
// threads = trains will stay = sleep in trainstation and print their current state
#include <sys/eventfd.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdint.h> //needed for our in-kernel counter
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/shm.h>
//eventfd: read with EFD_SEMAPHORE will decrease counter by 1 and return 1
// int eventfd(unsigned int initval, int flags);
// without just the previous value and resets to zero
// if eventfd counter is at zero when trying to read, it will block until it turns nonzero again (only if fd is not nonblocking!)
// ssize_t read(int fd, void *buf, size_t count); returns no of bytes if it succeeds
// write adds a number to our 64 bit in-kernel counter
// ssize_t write(int fd, const void *buf, size_t count);
// fd is readable to select, poll, epoll if the counter is non zero
// select - monitors multiple fds until one or more turn "ready"
// poll - waits for an event on a fd
// epoll - similar to poll - monitors multiple fds to see if i/o is possible (great for large numbers of fds)
// close - required to release the fd - if all fds get closed = resources will be freed by the kernel
// return value = fd used to refer to the eventfd object; unsuccessful = -1
#define fail(msg) {printf(msg); return EXIT_FAILURE;}
struct stationStruct{
int stations[3];
uint64_t sem[3];
};
void threadfunction(void* station){
int n = 3;
struct stationStruct *st = station;
int stillWaiting = 1;
//reads eventfd to check wether train can enter or not
while(stillWaiting != 0){
for(int i = 0; i < n && stillWaiting != 0; i++){
if(read(st->stations[i], (void*) st->sem[i], sizeof(uint64_t)) > 0){
stillWaiting = 0;
printf("\n\ntrain no %ld has arrived at train station no %d \n", (long) pthread_self(), i);
sleep(1);
printf("train no %ld is ready for departure\n", (long) pthread_self());
sleep(2);
printf("train no %ld has left the train station %d\n", (long) pthread_self(), i);
//writes in order to release the locked eventfd
write(st->stations[i], (void*) st->sem[i], sizeof(uint64_t));
break;
}
//else{
//sleep(3);
//printf("train %ld has failed to enter station %d\n", (long) pthread_self(), i);
//}
}
}
pthread_exit((void*)pthread_self);
}
int main(int argc, char const *argv[])
{
int n = 3;
int m = 4;
struct stationStruct station;
//eventfd creation
for(int i = 0; i < n; i ++){
if((station.stations[i] = eventfd(1, EFD_SEMAPHORE)) > 0){
printf("Station %d is open\n", i);
}
else{
fail("could not initialize eventfd for station A\n");
}
}
pthread_t threads[m];
int returnedValues[m];
printf("Train Stations 0 - %d are open \n", n);
for(int i = 0; i < m; i++){
sleep(1);
if(pthread_create(&threads[i], NULL, (void*) &threadfunction, (void*)&station) != 0){
fail("trains did not arrive\n");
}
}
for(int i = 0; i < m; i++){
pthread_join(threads[i], (void*) &returnedValues[i]);
printf("Traind %ld left for good\n", (long) threads[i]);
}
printf("Train stations are closing now...\n");
for(int i = 0; i < n; i++){
printf("sation %d has been closed\n", i);
close(station.stations[i]);
}
printf("Main station has been closed\n");
return EXIT_SUCCESS;
}
#define _XOPEN_SOURCE
thank you very much for your time and help!
Seems to be a small pointer error?
if(read(st->stations[i], (void*) st->sem[i], sizeof(uint64_t)) > 0){
...
write(st->stations[i], (void*) st->sem[i], sizeof(uint64_t));
Should be
if(read(st->stations[i], &st->sem[i], sizeof(uint64_t)) > 0){
...
write(st->stations[i], &st->sem[i], sizeof(uint64_t));

Sum of words using threads

Problem: Implement a program that gets as arguments a file name followed by words. For each word, create a separate thread that counts its appearances in the given file.Print out the sum of the appearances of all words.
Below I did a code but I receive : Segmentaion Fault (core dumped) when I run it.
PS: I do not know if the code is correct and does the requirement succesfully
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t mtx;
int sum = 0;
char filename[10];
char word[10];
void * voidCount(void* p){
char cmd[100], appearences[100];
FILE *f;
sprintf(cmd, "echo %s | grep -o %s | wc -l", filename, word);
f = popen(cmd, "r");
fgets(appearences, sizeof(int), f);
pthread_mutex_lock(&mtx);
sum += *((int*)appearences);
pthread_mutex_unlock(&mtx);
return NULL;
}
int main(int argc, char *argv[]){
pthread_mutex_init(&mtx, NULL);
pthread_t threads[argc-1];
int i = 0;
for ( i = 1; i < argc-1; i++){
strcpy(filename, argv[1]);
strcpy(word, argv[i]);
pthread_create(&threads[i], NULL, voidCount, NULL);
}
for (i = 0; i < argc-1; ++i){
pthread_join(threads[i], NULL);
}
printf("Total appearences: %d", sum);
pthread_mutex_destroy(&mtx);
return 0;
}
The program has to complete few tasks in order to solve the problem:
set the number of threads depending on the number of words to search for
properly allocate and initialize thread arguments
pass each individual word as individual thread argument
protect shared variables during computation
get the results
Here's a minimal functional demo rework of your code with few essential comments. Word search is case sensitive.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t mtx;
int sum = 0;
char filename[10]; //declared global for simplicity
//we search all the words in the same file
void * voidCount(void* p){
char *word, cmd[100], appearences[100];
int num;
FILE *f;
word = ((char*)p);
printf ("word : %s\n",word);
sprintf(cmd, "more %s | grep -o %s | wc -l", filename, word);//echo didn't work
printf ("%s\n",cmd); //debug print
pthread_mutex_lock(&mtx);
f = popen(cmd, "r");
if(fgets(appearences, sizeof(appearences), f) == NULL)
printf("Pipe error\n"); //better error handling is welcome...
printf("Appearances of \"%s\": %s\n", word, appearences);
num = atoi(appearances); //convert string to int
sum += num;
pclose(f); //close pipe
pthread_mutex_unlock(&mtx);
return NULL;
}
int main(int argc, char *argv[])
{
pthread_mutex_init(&mtx, NULL);
pthread_t threads[argc-1];
char **data = calloc(argc,sizeof(char*)); // initialize thread data
int i = 0;
strcpy(filename, argv[1]);
for ( i = 2; i < argc; i++){
data[i-2] = calloc(33, sizeof(char));//let's allow for somewhat longer words
strcpy(data[i-2], argv[i]);
strcat(data[i-2], "\0");
pthread_create(&threads[i-2], NULL, voidCount, data[i-2]);//each word a thread arg
}
for (i = 0; i < argc-1; ++i){;
pthread_join(threads[i], NULL);
}
printf("Total appearences: %d\n", sum);
pthread_mutex_destroy(&mtx);
for (i = 0; i < argc; i++)//free thread data
free (data[i]);
free (data);
return 0;
}
Hope this can help.

Resources