I am learning the concept of multithreading and i encountered a problem using semaphore mutexes.
Here is my code snippet:
void *thread1_funct(void * myfileptr)
{
static int count;
printf("\nThread1 ID:%u\n",(unsigned int) pthread_self());
printf("\nThread1 function, file pointer received:0x%x\n", (FILE*)myfileptr);
for (;;)
{
count++;
sem_wait(&mutex);
fprintf(myfileptr, "%d\n", count);
sem_post(&mutex);
}
return NULL;
}
void *thread2_funct(void *myfileptr)
{
static int count=0;
printf("\nThread2 ID:%u\n",(unsigned int) pthread_self());
printf("\nThread2 function, file pointer received:0x%x\n", (FILE*)myfileptr);
for (;;)
{sem_wait(&mutex);
fscanf(myfileptr, "%d\n", &count);
printf("\n......%d......\n", count);
sem_post(&mutex);
}
return NULL;
}
The two threads i have created. One will write dfata to a file and the other will read the latest data.
Here is my main method:
int main(int argc, char **argv)
{
FILE *fileptr = fopen(*(argv+1), "a+");
sem_init(&mutex, 0x00, 0x01);
if ( (thread1_ret = pthread_create(&thread1, NULL, thread1_funct, (void*)fileptr)) == 0)
printf("\nThread1 created successfully....\n");
else
printf("\nFailed to create Thread1\n");
if ( (thread2_ret = pthread_create(&thread2, NULL, thread2_funct, (void*)fileptr)) == 0)
printf("\nThread2 created successfully....\n");
else
printf("\nFailed to create Thread2\n");
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
fclose(fileptr);
sem_destroy(&mutex);
pthread_exit(NULL);
return 0;
}
The expected output is :
........1........
........2........
........3........
and so on...... till the program is interrupted manually.
But my output is all 0s:
........0.......
........0.......
........0.......
........0.......
and so on....
Please help me. Where am i going wrong?
Thread 1 writes to the file, and advances the file pointer - to the end of the file. Thread 2 reads from the file pointer, which is pointing at the end of the file, and so you get nothing.
You could use fseek, or rewind in thread 2 to get your data.
Related
I have this code that reads in two int numbers from a file. And stores it in a buffer[] to be taken in a second function to be used. I'm not sure if my stopping conditions in the first function are correct. It looks fine but when running the code it stops at the second function.
static int count = 0;
int buffer[5];
int requestNum = 1;
FILE* f;
int main(int argc, char** argv)
{
/*THREAD IDs*/
pthread_t liftR, lift1;
/*OPEN FILE*/
f = fopen("sim_input.txt", "r");
/*CREATE THREAD*/
pthread_create(&liftR, NULL, request, NULL);
pthread_create(&lift1, NULL, lift, NULL);
/*RUNS TILL THREADS FINISHED*/
pthread_join(liftR, NULL);
pthread_join(lift1, NULL);
/*CLEAN UP*/
fclose(f);
return 0;
}
void* request(void* data1)
{
int req1, req2, eof;
/*NOT EOF*/
while(eof != -1)
{
/*READ ONE REQUEST*/
eof = fscanf(f, "%d %d", &req1, &req2);
/*CHECK IF BUFFER FULLL*/
if(count < 5)
{
/*ADD REQUEST TO BUFFER*/
buffer[count] = req1;
buffer[count + 1] = req2;
count = count + 2;
printf("COUNT: %d\n", count);
/*PRINTING*/
printf("-------------------------------------------\n");
printf("From Buffer -> Item1: %d, Item2: %d\n", req1, req2);
printf("Request No: %d\n", requestNum);
printf("-------------------------------------------\n");
requestNum++;
}
}
return NULL;
}
void* lift(void* data2)
{
while(count > 0)
{
sleep(1);
printf("================\n");
printf("COUNT: %d\n", count);
printf("REMOVE ITEM FROM BUFFER - DO STUFF WITH IT\n");
printf("================\n");
count = count - 2;
}
return NULL;
}
OUTPUT:
Shows count 2, 4, 6. Only 3 request shown, In file it goes up to 10 request
There are multiple bugs in your program:
Reading uninitialized eof variable:
int int req1, req2, eof; // What is the value of eof? It could be -1 (or anything else).
/*NOT EOF*/
while(eof != -1)
You throw away the data you read:
if(count < 5)
{
/*ADD REQUEST TO BUFFER*/
}
If the first thread runs for a while before the second thread starts, then it will store the first two requests into the buffer, and throw away the rest.
To fix this, you need to wait for the second thread to drain the buffer when it is full.
You access count without any locking, which is a data race and undefined behavior. You must protect reading and writing shared (between threads) globals with a mutex.
Trying to implement the critical section of this program to actually swap between both threads correctly as stated later in the description.
I am trying to do a problem for my Operating Systems course. The problem is that I need to input two files, one of each are put into their separate threads, they will read through the file till they hit a line with the number "0". Then the other thread is supposed to run by the same rules.
This program is supposed to take two file input and figure out the message by concatenating both of the inputs from the files in a specific order and then printing out the output after it has deciphered it.
The inputs of these two files as shown below
Person1 Person2
--------- ----------
t 0
0 h
i 0
s 0
0 i
0 s
0 a
t 0
e 0
0 s
t 0
the above inputs should result in a string with this output
Example: “thisisatest”
Currently what is going wrong with the assignment is that it is not swapping correctly between the two threads and sitting in infinite loops.
Like I said above I am trying to solve this assignment by use of Mutexes and Pthreads
Below is the current implementation of my code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static char *charArray[1000];
void *threadPerson1(void *value){
FILE *fPTR;
char buffer[2];
char *fileName = "Person1.txt";
fPTR = fopen(fileName, "r");
if (fPTR == NULL){
printf("was unable to open: %s\n", fileName);
return NULL;
}
while(1){
//Entering the critical section
pthread_mutex_lock(&mutex);
fscanf(fPTR, "%s", buffer);
printf("This is Person1: %s\n", buffer);
if(buffer != "0"){
charArray[count] = buffer;
count++;
}
if(buffer == "0"){
pthread_mutex_unlock(&mutex);
}
//exiting the critical section
}
}
void *threadPerson2(void *value){
FILE *fPTR;
char buffer[2];
char *fileName = "Person2.txt";
fPTR = fopen(fileName, "r");
if (fPTR == NULL){
printf("was unable to open: %s\n", fileName);
return NULL;
}
while(1){
//entering the critical section
pthread_mutex_lock(&mutex);
fscanf(fPTR, "%s", buffer);
printf("This is Person2: %s\n", buffer);
if(buffer != "0"){
charArray[count] = buffer;
count++;
}
if(feof(fPTR)){
printf("read end of file of: Person2\n");
fclose(fPTR);
return NULL;
}
if(buffer == "0"){
pthread_mutex_unlock(&mutex);
}
//exiting the critical section
}
}
int main(int argc, char **argv){
pthread_t thread1;
pthread_t thread2;
pthread_create(&thread1, NULL, threadPerson1, NULL);
pthread_create(&thread2, NULL, threadPerson2, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
for(int x = 0; x < 1000; x++){
if(charArray[x] == NULL){
printf("\n");
break;
}else{
printf("%s", charArray[x]);
}
}
return 0;
}
At least two things are incorrect in your program. First of all, if one thread releases the mutex, you are not guaranteed that the scheduler will allow the other thread will run, the releasing thread may very well go on and reacquire the mutex right away. Use a condition variable, read its manpages. Also, here are some examples, in particular 4-8: Multithreaded programming guide
Two, when you reach end of file, you need to release the mutex to clean up. Easiest way to do it is what we call RAII in C++, i.e. use a resource handle that releases the mutex when the handle object goes out of scope. You can do similar things in C e.g. by registering a cleanup function, or a 'goto' to end of function with cleanup code called from there.
i m trying to implement the producer - consumer with threads.In my code below is working well except of the point where i try to print into 2 files.(one for prod and one for cons).I use fclose(stdout) . when i delete it inside producer then the print in producer file is ok but consumers no.when i deleted at all then all of the data printed into the consumer file.My question is what i should try to make the prints correctly( i need consumer to print in cons.out.txt and producer in prod_out.txt) .Also i didnt include check for threads to make it simple but it works well.
#include "head.h"
circular_buffer cb;
pthread_mutex_t lock;
pthread_cond_t cond;
char * data[6]; //is the data taken from cmd(argv[0-6]) first one is the program the other are parameters
int main(int argc , char *argv[]) {
validate(argv,argc); //if command arguments are valid go on
for(int i=0; i < argc; i++){
data[i]=argv[i]; //copy argv array to data array
}
cb_init(&cb,10,sizeof(int)); //initialization of circular buffer for 10 nodes + size of int each node
pthread_t cons, prod;
void *consumer(), *producer();
int rc = pthread_mutex_init(&lock, NULL);
rc = pthread_cond_init(&cond, NULL);
int id[]={1,2}; //prod id is 1 and cons 2
rc = pthread_create(&prod, NULL, producer, &id[0]);
rc = pthread_create(&cons, NULL, consumer, &id[1]);
rc=pthread_join(prod, NULL);
rc=pthread_join(cons, NULL);
rc = pthread_mutex_destroy(&lock);
rc = pthread_cond_destroy(&cond);
cb_free(&cb); //free allocated memory which is alocated in head
return 1;
}
void *consumer(void * id){
int thread_id= *((int*)id); //cast to (int)
int file;
FILE * fp2 = fopen("./cons_out.txt","wb"); //creates new file with "cons_out.txt" name
int i =10;
while(i > 0){
i--;
pthread_mutex_lock(&lock);
while(isEmpty(&cb)){
int rc = pthread_cond_wait(&cond,&lock);
}//end while
int item=0; // item that will be consumed
cb_pop_front(&cb,&item);
file = open("./cons_out.txt", O_APPEND | O_WRONLY, 0777 );//open file as new
if( file == -1 ) {//fail to open file
perror("./cons_out.txt");
return EXIT_FAILURE;
}
fclose(stdout);
dup2( file, STDOUT_FILENO); //change redirections
printf("Consumer %d : %d\n",thread_id,item); //print output to file
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
} //end while
return NULL;
} //end consumer()
void *producer(void * id){
int thread_id= *((int*)id); //cast to (*int)
int file1;
FILE * fp1 = fopen("./prod_in.txt","wb"); //creates new file with "prod_in.txt" name
for(int i=0; i<10; i++){ //it produce 10 numbers
pthread_mutex_lock(&lock);
while(isFull(&cb)){
int rc = pthread_cond_wait(&cond,&lock);
}//end while
int seed=1;
int item=rand(); // item of this producer
cb_push_back(&cb,&item);
file1 = open("./prod_in.txt", O_APPEND | O_WRONLY, 0777 );//open file as new
if( file1 == -1 ) {//fail to open file
perror("./prod_in.txt");
return EXIT_FAILURE;
}
fclose(stdout);
dup2( file1, STDOUT_FILENO); //change output
printf("Producer %i : %i\n",thread_id,item); //print output to file
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
} //end for
return NULL;
} //end Producer();
There is only one open file table for your whole process, shared by all threads in it. There is one entry in that table for the standard output, and your producer and consumer are contending for it. It's not clear why.
I'm inclined to think that the immediate reason for your troubles is that fclose()ing the stdout stream releases the stream-level resources, especially the buffer and state-tracking details. open()ing a file descriptor does not provide those, nor does dup2()ing a file descriptor into a FILE object representing a closed stream.
But it baffles me why you are making it so hard. Why in the world muck with duping file descriptors? Your producer and consumer already fopen() the wanted output files, thereby each obtaining its own stream connected with the appropriate file (fp1 and fp2). It seems to me that all you need to do, then, is to write to those streams via fprintf(), etc., instead of going to a lot of trouble to be able to use printf() instead.
That would be more efficient, too, since you oughtn't to need to keep opening and closing the files. Open each once, at the beginning, as you already do, and close each once, at the end, which you presently fail to do.
I am using multiple threads to access various random files using threads. However, I get an error [Thread 0x7ffff7007700 (LWP 16256) exited]. Also, info threads shows that only 2 threads are created. However, I am trying to create 100 of them. Also, do I have to use the pthread_join() function in my case? The code:
#define NTHREADS 100
void *encrypt(void *args)
{
int count = *((int*) args);
AES_KEY enc_key;
AES_set_encrypt_key(key, 128, &enc_key);
int i;
for(i=1;i<=count;i++){
char *ifile;
char *ofile;
long length;
size_t result;
char * buffer;
sprintf(ifile,"random_files/random_%d.txt",i);
FILE *ifp = fopen(ifile,"rb");
if (ifp==NULL) {fputs ("File error",stderr); exit (1);}
fseek(ifp,0, SEEK_END);
length = ftell(ifp);
fseek (ifp,0, SEEK_SET);
buffer = (char*) malloc (sizeof(char)*length);
if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}
result = fread (buffer, 1, length, ifp);
if (result != length) {fputs ("Reading error",stderr); exit (3);}
printf("%s",buffer);
fclose (ifp);
free(buffer);
}
}
int main(){
int i,j,count =0;
pthread_t threads[NTHREADS];
for (i=0; i<NTHREADS; i++){
count = count +20;
int *count_ptr = &count;
if(pthread_create(&threads[i], NULL, encrypt, count_ptr)!=0){
fprintf(stderr, "error: Cannot create thread # %d\n", i);
break;
}
}
printf("After Thread\n");
exit(0);
}
Yes, you should join your threads, as none were created detached (and you're probably not deep enough in learning pthreads to deal with that anyway).
That said, you have a significant logic problem in your thread parameters. They're all getting the address of the same count variable in main. Probably the fastest way to change that with no modifications to your thread-proc is simply stand up a side-by-side array of int counts[NTHREADS] matching your threads, using each element as the corresponding thread's data param:
int main()
{
pthread_t threads[NTHREADS];
int counts[NTHREADS]; // HERE
int i,j,count =0;
for (i=0; i<NTHREADS; i++)
{
counts[i] = (count += 20);
if(pthread_create(&threads[i], NULL, encrypt, counts+i)!=0) // LAST PARAM
{
fprintf(stderr, "error: Cannot create thread # %d\n", i);
break;
}
}
for (i=0; i<NTHREADS; ++i)
pthread_join(threads[i], NULL));
return EXIT_SUCCESS;
}
Alternatively, you could do some dynamic allocation hoops, or send the value via intptr_t, cast to void*, but the method shown above has the advantage of requiring no changes on your thread-proc, a target I was aiming for.
I've left any issues in your thread proc to you to solve, but that should get you up and running on your thread stack, at least.
There are missing things in the code, first, in your encrypt function you need to close the threads at the end and also in the main function BUT, before you do so, after your for loop you need to join them all, then they are going to be processed and closed correctly.
The flow will go like this:
(void) pthread_join(th1, NULL);
(void) pthread_join(th2, NULL);
You can put them all in a for to join them by tid.
Another update: There is not really anything "random" going on, I would just start open the files according to its tid, and then add other big implementations, your as is will try to open files like crazy, it should work anyways but, just saying.
I learn threads. I have read that thread terminates after it is out of a function (that is passed as parameter to pthread_create function).
So I create threads in the loop, they are executed and afterwards they are terminated.
(sorry for some long code)
But when I call a function pthread_create, new threads get the same ids. Why?
struct data {
FILE *f;
};
void *read_line_of_file(void *gdata) {
pthread_mutex_lock(&g_count_mutex); // only one thread can work with file,
//doing so we block other threads from accessing it
data *ldata = (data *) gdata;
char line[80];
int ret_val =fscanf(ldata->f,"%s",line);
pthread_mutex_unlock(&g_count_mutex); // allow other threads to access it
if (ret_val != EOF)
printf("%s %lu\n ", line, pthread_self());
// some time consuming operations, while they are being executed by one thread,
// other threads are not influenced by it (if there are executed on different cores)
volatile int a=8;
for (int i=0;i <10000;i++ )
for (int i=0;i <10000;i++ ) {
a=a/7+i;
}
if (ret_val == EOF) // here thread ends
pthread_exit((void *)1);
pthread_exit((void *)0);
}
int main() {
int kNumber_of_threads=3, val=0;
pthread_t threads[kNumber_of_threads];
int ret_val_from_thread=0;
data mydata;
mydata.f = fopen("data.txt","r");
if ( mydata.f == NULL) {
printf("file is not found\n");
return 0;
}
for( ; val != 1 ;) {
// THIS IS THAT PLACE, IDs are the same (according to the number of processes),
// I expected them to be changing..
for(int i=0; i<kNumber_of_threads; i++) {
pthread_create(&threads[i],NULL,read_line_of_file, &mydata);
}
for(int i=0; i<kNumber_of_threads; i++) {
pthread_join(threads[i], (void **) &ret_val_from_thread);
if (ret_val_from_thread != 0)
val = ret_val_from_thread;
}
printf(" next %d\n",val);
}
printf("work is finished\n");
fclose(mydata.f);
return 0;
}
as result, I see that id of threads are not being changed:
I wonder, are new threads really created?
Thanks in advance!
Thread IDs are only guaranteed to be different among currently running threads. If you destroy a thread and create a new one, it may well be created with a previously used thread ID.