memory synchronization - c

I have the function display.c :
/* DO NOT EDIT THIS FILE!!! */
#include <stdio.h>
#include <unistd.h>
#include "display.h"
void display(char *str)
{
char *p;
for (p=str; *p; p++)
{
write(1, p, 1);
usleep(100);
}
}
and display.h is:
/* DO NOT EDIT THIS FILE!!! */
#ifndef __CEID_OS_DISPLAY_H__
#define __CEID_OS_DISPLAY_H__
void display(char *);
#endif
My task is to use pthreads in order to have the following output:
abcd
abcd
abcd
..
..
Note that I must not edit the file display.c or the file display.c. I have to use mutexes in order to succeed the output that is shown above.
The following block of code is my closest attempt to finally reach the result I want:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include <pthread.h>
#include "display.h"
pthread_t mythread1;
pthread_t mythread2;
pthread_mutex_t m1, m2;
void *ab(void *arg)
{
pthread_mutex_lock(&m1);
display("ab");
pthread_mutex_unlock(&m1);
}
void *cd(void *arg)
{
pthread_mutex_lock(&m1);
display("cd\n");
pthread_mutex_unlock(&m1);
}
int main(int argc, char *argv[])
{
pthread_mutex_init(&m1, NULL);
pthread_mutex_init(&m2, NULL);
int i;
for(i=0;i<10;i++)
{
pthread_create(&mythread1, NULL, ab, NULL);
pthread_create(&mythread2, NULL, cd, NULL);
}
pthread_join(mythread1, NULL);
pthread_join(mythread2, NULL);
pthread_mutex_destroy(&m1);
pthread_mutex_destroy(&m2);
return EXIT_SUCCESS;
}
The output of the code above is something like this:
abcd
abcd
abcd
abcd
ababcd
cd
abcd
abcd
abcd
abcd
As you can see "ab" and "cd\n" are never mixed but every time I run the code the output differs. I want to make sure that every time I run this code the output will be:
abcd
abcd
abcd
for ten times.
I am really stuck with this since I can't find any solution from the things I already know.

A mutex cannot (by itself) solve your problem. It can prevent your two threads from running concurrently, but it cannot force them to take turns.
You can do this with a condition variable in addition to the mutex, or with a pair of semaphores. Either way, the key is to maintain at all times a sense of which thread's turn it is.
Myself, I think the semaphore approach is easier to understand and code. Each semaphore is primarily associated with a different thread. That thread must lock the semaphore to proceed. When it finishes one iteration it unlocks the other semaphore to allow the other thread to proceed, and loops back to try to lock its own semaphore again (which it cannot yet do). The other thread works the same way, but with the semaphore roles reversed. Roughly, that would be:
sem_t sem1;
sem_t sem2;
// ...
void *thread1_do(void *arg) {
int result;
do {
result = sem_wait(&sem1);
// do something
result = sem_post(&sem2);
} while (!done);
}
void *thread2_do(void *arg) {
int result;
do {
result = sem_wait(&sem2);
// do something else
result = sem_post(&sem1);
} while (!done);
}
Semaphore initialization, error checking, etc. omitted for brevity.
Updated to add:
Since you now add that you must use mutexes (presumably in a non-trivial way) the next best way to go is to introduce a condition variable (to be used together with the mutex) and an ordinary shared variable to track which thread's turn it is. Each thread then waits on the condition variable to obtain the mutex, under protection of the mutex checks the shared variable to see whether it is its turn, and if so, proceeds. Roughly, that would be:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int whose_turn = 1;
// ...
void *thread1_do(void *arg) {
int result;
result = pthread_mutex_lock(&mutex);
while (1) {
if (whose_turn == 1) {
// do something
whose_turn = 2; // it is thread 2's turn next
}
// break from the loop if finished
result = pthread_cond_broadcast(&cond);
result = pthread_cond_wait(&cond, &mutex);
}
result = pthread_mutex_unlock(&mutex);
}
void *thread1_do(void *arg) {
int result;
result = pthread_mutex_lock(&mutex);
while (1) {
if (whose_turn == 2) {
// do something else
whose_turn = 1; // it is thread 1's turn next
}
// break from the loop if finished
result = pthread_cond_broadcast(&cond);
result = pthread_cond_wait(&cond, &mutex);
}
result = pthread_mutex_unlock(&mutex);
}
Error checking is again omitted for brevity.
Note in particular that when a thread waits on a condition variable, it releases the associated mutex. It reaquires the mutex before returning from the wait. Note also that each checks at each iteration whether it is its turn to proceed. This is necessary because spurious wakeups from waiting on a condition variable are possible.

You can use a conditional variable to take turns between threads:
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int turn = 0;
void *ab(void *arg)
{
pthread_mutex_lock(&m1);
while (turn != 0)
pthread_cond_wait(&cond, &m1);
display("ab");
turn = 1;
pthread_mutex_unlock(&m1);
pthread_cond_signal(&cond);
}
void *cd(void *arg)
{
pthread_mutex_lock(&m1);
while (turn != 1)
pthread_cond_wait(&cond, &m1);
display("cd\n");
turn = 0;
pthread_mutex_unlock(&m1);
pthread_cond_signal(&cond);
}
Another problem is, you are joining with the last two pair of threads created in main() thread, which are not necessarily the ones get executed as last. If threads created early are not completed, then you are destroying the mutex m1 while it might be in use and exiting whole process.

Consider this approach to the issue:
for(i=0;i<10;i++)
{
ab();
cd();
}
This achieves your goals completely, given the shown code. The problem with your example is that you effectively prevent any synchronization and that seems to be your goal even!
Assuming that before the output, you actually want to do something useful which takes CPU time, the answer is that you will have to change the code of display(), which is simply not suitable for parallelization. Proper concurrent code is designed to work independent of other code, in particular it shouldn't compete for resources (locks) with other calls and it shouldn't rely on the order it finishes.
In summary, you can't learn much from this, it's a bad example. In order to improve the code (the one you don't want to change, but that's your problem), consider that the resource the different threads compete for is stdout. If they each wrote to their own buffer, you could create the threads, wait for them to finish and only then reorder their results for output.

Related

Global variable not changing in thread?

I'm trying to update a global variable in the main function and have a thread tell me when this variable is positive.
The code: https://pastebin.com/r4DUHaUV
When I run it, only 2 shows up though 1 and 2 should be the correct answer.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_t tid;
pthread_mutex_t mtx;
pthread_cond_t cond;
int nr=0;
void* function(void* arg)
{
pthread_mutex_lock(&mtx);
printf("Number in thread : %d \n",nr);
while(nr<=0)
pthread_cond_wait(&cond,&mtx);
printf("Number %d is positive \n",nr);
pthread_mutex_unlock(&mtx);
}
int main()
{
pthread_mutex_init(&mtx,NULL);
pthread_create(&tid,NULL,function,NULL);
int i;
for(i=0;i<3;i++)
{
int isPos=0;
pthread_mutex_lock(&mtx);
if(i==0)
nr=nr+1;
if(i==1)
nr=nr-2;
if(i==2)
nr=nr+3;
if(nr>0)
isPos=1;
if(isPos==1)
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mtx);
}
pthread_join(tid,NULL);
return 0;
}
As I mentioned in general comment, I'll repeat here:
There is no guarantee the main thread won't go off, locking the mutex,
changing nr, signaling the cv (whether or not anyone is actually
waiting on it), and unlocking the mutex, all before the child thread
even locks the mutex, much less starts waiting on the cv. In that
case, nr can be 1 (or 2, etc) when the child finally gets the mutex.
That means your while loop will be skipped (nr<=0 is not true), and
whatever the current value of nr is will be printed on the way out.
I've run this several times, and gotten 1x1, 1x2, and 2x2, multiple
times.
A simple fix for this involves using the cv/mtx pair you've set up for monitoring for changes from main to also monitor startup-start from function. First the code:
The Code
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int nr = -1;
void* function(void* arg)
{
// signal main to start up once we start waiting
pthread_mutex_lock(&mtx);
nr = 0;
pthread_cond_signal(&cond);
// now start waiting (which will unlock the mutex as well, which means
// the main thread will be be able to acquire it and check nr safely
while(nr<=0)
pthread_cond_wait(&cond,&mtx);
printf("Number %d is positive \n",nr);
pthread_mutex_unlock(&mtx);
return NULL;
}
int main()
{
pthread_t tid;
pthread_create(&tid,NULL,function,NULL);
// wait until child is knowingly waiting
pthread_mutex_lock(&mtx);
while (nr != 0)
pthread_cond_wait(&cond, &mtx);
pthread_mutex_unlock(&mtx);
// now we know the child is ready to receive signals
int i;
for(i=0;i<3;i++)
{
pthread_mutex_lock(&mtx);
if(i==0)
nr=nr+1;
if(i==1)
nr=nr-2;
if(i==2)
nr=nr+3;
int isPos = (nr>0);
pthread_mutex_unlock(&mtx);
if (isPos)
pthread_cond_signal(&cond);
}
pthread_join(tid,NULL);
return 0;
}
How It Works
The initial value of nr is established as -1. Only the child thread will change this directly to 0, and even then only under the protection of the predicate mutex.
// signal main to start up once we start waiting
pthread_mutex_lock(&mtx);
nr = 0;
pthread_cond_signal(&cond);
Note that after the above three lines, the child still owns the mutex. It atomically releases it and begins waiting for notifications with the first entry into the subsequent loop:
while(nr<=0)
pthread_cond_wait(&cond,&mtx);
Now, back in main, the startup creates the child thread, acquires the mutex, then monitors until nr is zero.
pthread_create(&tid,NULL,function,NULL);
// wait until child is knowingly waiting
pthread_mutex_lock(&mtx);
while (nr != 0)
pthread_cond_wait(&cond, &mtx);
pthread_mutex_unlock(&mtx);
The only way to make it past this is when nr == 0. When that happens, the child must have changed it, but more importantly, it also must be waiting on the condition variable (that is how we got the mutex; remember?) From that point on, the code is similar. Worth noting, I use the pthread initializers to ensure the mutex and cvar are properly stood up. Your original post was missing the cvar initialization.
Lastly, doing multiple-predicate double-duty with a single cvar-mtx pair is easy to mess up, and can be very hard to detect edge cases when you did (mess up, that is). Be careful. This specific example is a hand-off sequence of duties, not concurrent duties, making it fairly trivial, so I'm comfortable in showing it.
Hope it helps.

The mutex locks a value in a function for ever

I am new in threads in c. My code has a thread that increasing a counter and occasionally(randomly) another thread reads that counter. I used mutex in this code but my code always gives me value equal to 1. Although I used pthread_mutex_unlock but it seems the value becomes lock for ever. what should I do to solve the problem?
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <pthread.h>
///////////////////////////
long int count=0;
int RunFlag=0;
pthread_mutex_t mtx;
void *readfun(void *arg)
{
while (RunFlag==0)
{
pthread_mutex_lock(&mtx);
count=count+1;
pthread_mutex_unlock(&mtx);
}
}
void *printfun(void *arg)
{
int RadnTime=0;
for (int j=0;j<4;j++)
{
RadnTime=rand()%3+1;
sleep(RadnTime);
printf("The current counter after %d seconds is: ",RadnTime);
pthread_mutex_lock(&mtx);
printf("%d\n",count);
pthread_mutex_unlock(&mtx);
}
}
void main ()
{
pthread_t thread1;
pthread_t thread2;
pthread_mutex_init(&mtx, NULL);
pthread_create(&thread1,NULL,readfun,NULL);
pthread_create(&thread2,NULL,printfun,NULL);
//stop the counter
RunFlag=1;
pthread_exit(NULL);
}
You are setting RunFlag immediately after the two threads are created, so readfun barely has any time to execute. RunFlag=1; should be at the end of printfun.
As far as I know, reading from and writing to RunFlag isn't guaranteed to be atomic, so access to it should be protected as well. I don't see a problem happening here (given the values in question), but you are entering undefined behaviour territory.
Your functions don't return anything even though they are declared as returning void*. Add return NULL; to them.
Finally, the second %d should be %ld since count is a long int.
Note that
pthread_mutex_t mtx;
pthread_mutex_init(&mtx, NULL);
can be replaced with
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
1) You also have data race as two are accessing RunFlag. So, you need to protect it with synchronization primitive (such as mutex or use a semaphore).
But you don't need the RunFlag for this purpose. Since you can use an infinite loop in readfun() thread and then simply call _exit() from printfun() thread to exit the whole process.
2) Thread functions must return a pointer to satisfy by pthread_create()'s requirement. But you thread functions don't return anything. You can add return NULL; at the end of both thread functions.
Be aware of signed integer overflow as count could potentially overflow.

Unable to get lock when eventfd is used for synchronization

I am trying to use eventfd for synchronization b/w two threads. Please look below code. In this if main thread acquires a lock first it wont release unless I uncomment sleep after write function. It is true if thread gets the lock first. Please let me know how to handle without using sleep after write.
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
int event_fd;
uint64_t counter;
void * Thread1(void *p)
{
printf("\n%s eventfd = %d\n",(char*)p, event_fd);
while(1)
{
read(event_fd, &counter,sizeof(counter));
printf("\n %s function counter = %llu\n",(char*)p,counter);
sleep(1);
write(event_fd,&counter,sizeof(counter));
//sleep(1);
}
return NULL;
}
void main()
{
char str[]="In Thread1";
int ret;
pthread_t p_th;
printf("Events demonstration pid = %d sizeof counter %lu\n ",getpid(),sizeof(counter));
event_fd=eventfd(1,0);
printf("event_fd %d\n",event_fd);
pthread_create(&p_th,NULL,Thread1, str);
while(1)
{
read(event_fd, &counter,sizeof(counter));
printf("\n In main function counter = %llu\n",counter);
sleep(1);
write(event_fd,&counter,sizeof(counter));
//sleep(1);
}
pthread_exit (NULL);
}
Firstly, they aren't locks. They are eventfd semaphores.
Secondly, they contain no provision for fairness amongst threads. So if you omit the sleep() clause, the semaphore will be grabbed again the moment you release it by the next read. eventfd is more often used in a producer consumer environment where one end is doing the write and the other the read.

How can I wait for any/all pthreads to complete?

I just want my main thread to wait for any and all my (p)threads to complete before exiting.
The threads come and go a lot for different reasons, and I really don't want to keep track of all of them - I just want to know when they're all gone.
wait() does this for child processes, returning ECHILD when there are no children left, however wait does not (appear to work with) (p)threads.
I really don't want to go through the trouble of keeping a list of every single outstanding thread (as they come and go), then having to call pthread_join on each.
As there a quick-and-dirty way to do this?
Do you want your main thread to do anything in particular after all the threads have completed?
If not, you can have your main thread simply call pthread_exit() instead of returning (or calling exit()).
If main() returns it implicitly calls (or behaves as if it called) exit(), which will terminate the process. However, if main() calls pthread_exit() instead of returning, that implicit call to exit() doesn't occur and the process won't immediately end - it'll end when all threads have terminated.
http://pubs.opengroup.org/onlinepubs/007908799/xsh/pthread_exit.html
Can't get too much quick-n-dirtier.
Here's a small example program that will let you see the difference. Pass -DUSE_PTHREAD_EXIT to the compiler to see the process wait for all threads to finish. Compile without that macro defined to see the process stop threads in their tracks.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
static
void sleep(int ms)
{
struct timespec waittime;
waittime.tv_sec = (ms / 1000);
ms = ms % 1000;
waittime.tv_nsec = ms * 1000 * 1000;
nanosleep( &waittime, NULL);
}
void* threadfunc( void* c)
{
int id = (int) c;
int i = 0;
for (i = 0 ; i < 12; ++i) {
printf( "thread %d, iteration %d\n", id, i);
sleep(10);
}
return 0;
}
int main()
{
int i = 4;
for (; i; --i) {
pthread_t* tcb = malloc( sizeof(*tcb));
pthread_create( tcb, NULL, threadfunc, (void*) i);
}
sleep(40);
#ifdef USE_PTHREAD_EXIT
pthread_exit(0);
#endif
return 0;
}
The proper way is to keep track of all of your pthread_id's, but you asked for a quick and dirty way so here it is. Basically:
just keep a total count of running threads,
increment it in the main loop before calling pthread_create,
decrement the thread count as each thread finishes.
Then sleep at the end of the main process until the count returns to 0.
.
volatile int running_threads = 0;
pthread_mutex_t running_mutex = PTHREAD_MUTEX_INITIALIZER;
void * threadStart()
{
// do the thread work
pthread_mutex_lock(&running_mutex);
running_threads--;
pthread_mutex_unlock(&running_mutex);
}
int main()
{
for (i = 0; i < num_threads;i++)
{
pthread_mutex_lock(&running_mutex);
running_threads++;
pthread_mutex_unlock(&running_mutex);
// launch thread
}
while (running_threads > 0)
{
sleep(1);
}
}
If you don't want to keep track of your threads then you can detach the threads so you don't have to care about them, but in order to tell when they are finished you will have to go a bit further.
One trick would be to keep a list (linked list, array, whatever) of the threads' statuses. When a thread starts it sets its status in the array to something like THREAD_STATUS_RUNNING and just before it ends it updates its status to something like THREAD_STATUS_STOPPED. Then when you want to check if all threads have stopped you can just iterate over this array and check all the statuses.
Don't forget though that if you do something like this, you will need to control access to the array so that only one thread can access (read and write) it at a time, so you'll need to use a mutex on it.
you could keep a list all your thread ids and then do pthread_join on each one,
of course you will need a mutex to control access to the thread id list. you will
also need some kind of list that can be modified while being iterated on, maybe a std::set<pthread_t>?
int main() {
pthread_mutex_lock(&mutex);
void *data;
for(threadId in threadIdList) {
pthread_mutex_unlock(&mutex);
pthread_join(threadId, &data);
pthread_mutex_lock(&mutex);
}
printf("All threads completed.\n");
}
// called by any thread to create another
void CreateThread()
{
pthread_t id;
pthread_mutex_lock(&mutex);
pthread_create(&id, NULL, ThreadInit, &id); // pass the id so the thread can use it with to remove itself
threadIdList.add(id);
pthread_mutex_unlock(&mutex);
}
// called by each thread before it dies
void RemoveThread(pthread_t& id)
{
pthread_mutex_lock(&mutex);
threadIdList.remove(id);
pthread_mutex_unlock(&mutex);
}
Thanks all for the great answers! There has been a lot of talk about using memory barriers etc - so I figured I'd post an answer that properly showed them used for this.
#define NUM_THREADS 5
unsigned int thread_count;
void *threadfunc(void *arg) {
printf("Thread %p running\n",arg);
sleep(3);
printf("Thread %p exiting\n",arg);
__sync_fetch_and_sub(&thread_count,1);
return 0L;
}
int main() {
int i;
pthread_t thread[NUM_THREADS];
thread_count=NUM_THREADS;
for (i=0;i<NUM_THREADS;i++) {
pthread_create(&thread[i],0L,threadfunc,&thread[i]);
}
do {
__sync_synchronize();
} while (thread_count);
printf("All threads done\n");
}
Note that the __sync macros are "non-standard" GCC internal macros. LLVM supports these too - but if your using another compiler, you may have to do something different.
Another big thing to note is: Why would you burn an entire core, or waste "half" of a CPU spinning in a tight poll-loop just waiting for others to finish - when you could easily put it to work? The following mod uses the initial thread to run one of the workers, then wait for the others to complete:
thread_count=NUM_THREADS;
for (i=1;i<NUM_THREADS;i++) {
pthread_create(&thread[i],0L,threadfunc,&thread[i]);
}
threadfunc(&thread[0]);
do {
__sync_synchronize();
} while (thread_count);
printf("All threads done\n");
}
Note that we start creating the threads starting at "1" instead of "0", then directly run "thread 0" inline, waiting for all threads to complete after it's done. We pass &thread[0] to it for consistency (even though it's meaningless here), though in reality you'd probably pass your own variables/context.

pthread_exit and/or pthread_join causing Abort and SegFaults

The following code is a simple thread game, that switches between threads causing the timer to decrease.
It works fine for 3 threads, causes and Abort(core dumped) for 4 threads, and causes a seg fault for 5 or more threads.
Anyone have any idea why this might be happening?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <assert.h>
int volatile num_of_threads;
int volatile time_per_round;
int volatile time_left;
int volatile turn_id;
int volatile thread_running;
int volatile can_check;
void * player (void * id_in){
int id= (int)id_in;
while(1){
if(can_check){
if (time_left<=0){
break;
}
can_check=0;
if(thread_running){
if(turn_id==id-1){
turn_id=random()%num_of_threads;
time_left--;
}
}
can_check=1;
}
}
pthread_exit(NULL);
}
int main(int argc, char *args[]){
int i;
int buffer;
pthread_t * threads =(pthread_t *)malloc(num_of_threads*sizeof(pthread_t));
thread_running=0;
num_of_threads=atoi(args[1]);
can_check=0;
time_per_round = atoi(args[2]);
time_left=time_per_round;
srandom(time(NULL));
//Create Threads
for (i=0;i<num_of_threads;i++){
do{
buffer=pthread_create(&threads[i],NULL,player,(void *)(i+1));
}while(buffer == EAGAIN);
}
can_check=1;
time_left=time_per_round;
turn_id=random()%num_of_threads;
thread_running=1;
for (i=0;i<num_of_threads;i++){
assert(!pthread_join(threads[i], NULL));
}
return 0;
}
See below on why you should not depend on volatile in pthreads. However, your specific problem is probably because you malloc your pthread array, based on the num_of_threads variable before you've actually set num_of_thread from argv[]:
pthread_t *threads = (pthread_t *)malloc (num_of_threads * sizeof (pthread_t));
thread_running = 0;
num_of_threads = atoi (args[1]);
So there's a very good chance you're writing beyond the end of the threads array. The num_of_threads variable will probably be zero on start-up which means you're not allocating what you think you are. Move the allocation to after the extraction of the arguments and that should fix it.
And now, for your viewing pleasure :-), my original rant on the unsafe use of volatile, which I still stand by.
Do not rely on volatile to protect your shared variables. The correct way to do this is with the pthread_mutex_blab_blah_blah calls.
Of particular note, examine this code segment:
if (can_check) {
if (time_left <= 0) {
break;
}
// URK!!
can_check=0;
URK!! is the point where your current thread may be switched out and another run, leading to the possibility that two threads can be running a critical section of code.
My advice is to forget the can_check altogether and just protect all the shared variables with a mutex, something like (from memory):
void *player (void * id_in) {
int id = (int)id_in;
while (1) {
pthread_mutex_lock (&mutex);
if (time_left <= 0) {
pthread_mutex_unlock (&mutex);
break;
}
if (thread_running) {
if (turn_id == id-1) {
turn_id = random() % num_of_threads;
time_left--;
}
}
pthread_mutex_unlock (&mutex);
}
pthread_exit(NULL);
}
Then put at file-level:
pthread_mutexattr_t mutexattr; // prob. not needed at file level.
pthread_mutex_t mutex;
and, in main, before starting any other threads:
pthread_mutexattr_init (&mutexattr);
// Change attributes if needed.
pthread_mutex_init (&mutex, &mutex_attr);
// Then run all you other stuff here, make sure you've joined with all threads.
pthread_mutex_destroy (&mutex);
Oh yeah, although I haven't done it, you should also check the return codes for all those mutex calls. I'm not going to add that since it'll clog up the answer with unnecessary detail, but it's good practice.

Resources