Locking global array in a reentrancy-desired function in a multithreaded program? - c

Sorry if a question title is confusing. I just wanted to put all the things together.
I have a piece of code like:
int newThread(int(*pfunc)())
{
pthread_t tid;
pthread_create(&tid, NULL, pfunc, NULL);
int i = 0;
while(threads[i] != 0 && i < MAX_NUM_THREADS)
{
if ((MAX_NUM_THREADS - 1) == i)
{
puts("We've run out of threads' number limit\n");
return 1;
}
++i;
}
threads[i] = tid;
pthread_join(tid, NULL);
return 0;
}
threads[] is a global array. I want to make this function reentrant, but this means I shouldn't use global variables as far as I understand. I guess that's because values of global variables can be unpredictable at a certain time. But in my case the array seems to be quite predictable.
Is it ok, if I lock array with a mutex to make this function reentrant?
If yes, then how do I do it right? Just lock the first element before using it and unlock after? or is it better to lock/unlock every element while accessing it?
Is this even possible to make this function reentrant?

To say a function is reentrant, it should only rely on local variables to be simultaneously called by two (or more threads) and return correct results.
If the function rely on some shared data, (we can't really made it reentrant), we can make it thread-safe to be called simultaneously by two (or more) threads if all access to the shared data is serialized.
To make your function thread-safe, you should lock the loop and the insertion into threads[]. If you lock only the loop part, somebody could modify the content of threads between the end of the loop and the affectation at rank i.
pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;
int newThread(int(*pfunc)())
{
pthread_t tid;
pthread_create(&tid, NULL, pfunc, NULL);
int i = 0;
pthread_mutex_lock(&mymutex); // take the lock
while(threads[i] != 0 && i < MAX_NUM_THREADS)
{
if ((MAX_NUM_THREADS - 1) == i)
{
puts("We've run out of threads' number limit\n");
pthread_mutex_unlock(&mymutex); // don't forget to release the lock here too :)
return 1;
}
++i;
}
threads[i] = tid;
pthread_mutex_unlock(&mymutex); // release the lock
pthread_join(tid, NULL);
return 0;
}

Related

How do I sync my two threads which each use a while loop for a shared resource?

I am trying to do this implementation but it's not working properly.
I have a global variable called counter which starts at 100 and I have two threads.
Both threads are decrementing the counter in a while loop that runs if counter is != 0.
However though the thread which does decrement the counter to 0 will stop running as expected. But the thread which does not decrement the counter continues running when it should stop.
How do I fix this?
Below is my code:
int counter = 0;
pthread_mutex_t counter_mutex;
void *Thread1(void *vargs)
{
while (counter != 0) {
pthread_mutex_lock(&counter_mutex);
counter--;
pthread_mutex_unlock(&counter_mutex);
}
sleep(1);
printf("Completed Thread1\n");
return NULL;
}
void *Thread2(void *vargs)
{
while (counter != 0) {
pthread_mutex_lock(&counter_mutex);
counter--;
pthread_mutex_unlock(&counter_mutex);
}
sleep(1);
printf("Completed Thread2\n");
return NULL;
}
int main(void)
{
pthread_t tid[2];
// initialize the mutex
pthread_mutex_init(&counter_mutex, NULL);
// create worker threads
pthread_create(&tid[0], NULL, Thread1, NULL);
pthread_create(&tid[1], NULL, Thread2, NULL);
// wait for worker threads to terminate
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
// print final counter value
printf("Counter is %d\n", counter);
return 0;
}
Output:
Completed Thread1
Thread1 completes but the program runs indefinitely because Thread2 stays in the while loop and doesn't finish.
Or vice versa, where Thread2 completes and then runs indefinitely because Thread1 stays
in the while loop and doesn't finish.
I'm really confused on how to approach fixing this problem because the two Threads should be running and stopping when counter == 0. However only the Thread that decrements counter to 0, stops while the other runs indefinitely.
Any and all help is really appreciated!
Thank you so much
At some point, while one thread will be blocked waiting to lock the mutex, the other will have decremented counter to zero. As soon as the waiting thread gains access to the lock, it will decrement as well, resulting in -1. counter will never approach zero again, and it will be decremented until Undefined Behavior is invoked by overflowing a signed integer.
None of this really matters, because the read of counter in each while loop predicate is not protected by the mutex
while (counter != 0)
which means you can have a read/write race condition.
Instead, structure your locks so they fully surround all reads & writes, and adjust your predicate to be independently checked.
#include <pthread.h>
#include <stdio.h>
int counter = 0;
pthread_mutex_t counter_mutex;
void *runner(void *arg) {
int *n = arg;
int done = 0;
while (!done) {
pthread_mutex_lock(&counter_mutex);
if (counter == 0)
done = 1;
else
counter--;
pthread_mutex_unlock(&counter_mutex);
}
printf("Completed Thread %d\n", *n);
return NULL;
}
int main(void)
{
pthread_t tid[2];
int args[2] = { 1, 2 };
pthread_mutex_init(&counter_mutex, NULL);
pthread_create(&tid[0], NULL, runner, &args[0]);
pthread_create(&tid[1], NULL, runner, &args[1]);
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
printf("Counter is %d\n", counter);
return 0;
}
FYI: This is practically always a bad idea:
while (...trivial condition...) {
pthread_mutex_lock(&some_mutex);
...do some work...
pthread_mutex_unlock(&some_mutex);
}
The reason it's bad is that the loop tries to keep the mutex locked almost 100% of the time. The only time when the mutex is not locked is the brief moment when the loop evaluates the "...trivial condition..."
There's no point in executing the loop in more than one thread at the same time because the mutex prevents more than one thread from ever doing "...work..." at the same time.
If you're trying to use threads for parallel computing, then something like this works better:
typedef struct { ... } task_t;
int find_a_task(task_t* task) {
int result = FALSE;
pthread_mutex_lock(&some_mutex);
if (...there's more work to be done...) {
...copy from shared data into *task...
result = TRUE;
}
pthread_mutex_unlock(&some_mutex);
return result;
}
task_t local_task;
while (find_a_task(&local_task)) {
do_some_heavy_work_on(&local_task);
pthread_mutex_lock(&some_mutex);
if (...contents of local_task still are meaningful...) {
copy from local_task back to shared data structure
}
pthread_mutex_unlock(&some_mutex);
}
The idea is, to do most of the heavy work without keeping any mutex locked. The mutex is only briefly locked (a) before doing the heavy work, to copy shared data into private, local variables and (b) after the heavy work, to copy results, if still valid,* back into the shared data.
* The result might not still be valid because of some other thread changing shared data items that the caller used. This is optimistic locking. It may sound inefficient, but in many programs, the efficiency gained by not keeping a mutex locked while doing heavy work is MUCH greater than the efficiency lost because of threads occasionally duplicating or invalidating each other's effort.

Scheduling two threads in linux two print a pattern of numbers

I want to print numbers using two threads T1 and T2. T1 should print numbers like 1,2,3,4,5 and then T2 should print 6,7,8,9,10 and again T1 should start and then T2 should follow. It should print from 1....100. I have two questions.
How can I complete the task using threads and one global variable?
How can I schedule threads in desired order in linux?
How can I schedule threads in desired order in linux?
You need to use locking primitives, such as mutexes or condition variables to influence scheduling order of threads. Or you have to make your threads work independently on the order.
How can I complete the task using threads and one global variable?
If you are allowed to use only one variable, then you can't use mutex (it will be the second variable). So the first thing you must do is to declare your variable atomic. Otherwise compiler may optimize your code in such a way that one thread will not see changes made by other thread. And for such simple code that you want, it will do so by caching variable on register. Use std::atomic_int. You may find an advice to use volatile int, but nowdays std::atomic_int is a more direct approach to specify what you want.
You can't use mutexes, so you can't make your threads wait. They will be constantly running and wasting CPU. But that's seems OK for the task. So you will need to write a spinlock. Threads will wait in a loop constantly checking the value. If value % 10 < 5 then first thread breaks the loop and does incrementing, otherwise second thread does the job.
Because the question looks like a homework I don't show here any code samples, you need to write them yourself.
1: the easiest way is to use mutexes.
this is a basic implementation with a unfair/undefined sheduling
int counter=1;
pthread_mutex_t mutex; //needs to be initialised
void incrementGlobal() {
for(int i=0;i<5;i++){
counter++;
printf("%i\n",counter);
}
}
T1/T2:
pthread_mutex_lock(&mutex);
incrementGlobal();
pthread_mutex_unlock(&mutex);
2: the correct order can be archieved with conditional-variables:
(but this needs more global-variables)
global:
int num_thread=2;
int current_thread_id=0;
pthread_cond_t cond; //needs to be initialised
T1/T2:
int local_thread_id; // the ID of the thread
while(true) {
phread_mutex_lock(&mutex);
while (current_thread_id != local_thread_id) {
pthread_cond_wait(&cond, &mutex);
}
incrementGlobal();
current_thread_id = (current_thread_id+1) % num_threads;
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
}
How can I complete the task using threads and one global variable?
If you are using Linux, you can use POSIX library for threading in C programming Language. The library is <pthread.h>. However, as an alternative, a quite portable and relatively non-intrusive library, well supported on gcc and g++ and (with an old version) on MSVC is openMP.
It is not standard C and C++, but OpenMP itself is a standard.
How can I schedule threads in desired order in linux?
To achieve your desired operation of printing, you need to have a global variable which can be accessed by two threads of yours. Both threads take turns to access the global variable variable and perform operation (increment and print). However, to achieve desired order, you need to have a mutex. A mutex is a mutual exclusion semaphore, a special variant of a semaphore that only allows one locker at a time. It can be used when you have an instance of resource (global variable in your case) and that resource is being shared by two threads. A thread after locking that mutex can have exclusive access to an instance of resource and after completing it's operation, a thread should release the mutex for other threads.
You can start with threads and mutex in <pthread.h> from here.
The one of the possible solution to your problem could be this program is given below. However, i would suggest you to find try it yourself and then look at my solution.
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t lock;
int variable=0;
#define ONE_TIME_INC 5
#define MAX 100
void *thread1(void *arg)
{
while (1) {
pthread_mutex_lock(&lock);
printf("Thread1: \n");
int i;
for (i=0; i<ONE_TIME_INC; i++) {
if (variable >= MAX)
goto RETURN;
printf("\t\t%d\n", ++variable);
}
printf("Thread1: Sleeping\n");
pthread_mutex_unlock(&lock);
usleep(1000);
}
RETURN:
pthread_mutex_unlock(&lock);
return NULL;
}
void *thread2(void *arg)
{
while (1) {
pthread_mutex_lock(&lock);
printf("Thread2: \n");
int i;
for (i=0; i<ONE_TIME_INC; i++) {
if (variable >= MAX)
goto RETURN;
printf("%d\n", ++variable);
}
printf("Thread2: Sleeping\n");
pthread_mutex_unlock(&lock);
usleep(1000);
}
RETURN:
pthread_mutex_unlock(&lock);
return NULL;
}
int main()
{
if (pthread_mutex_init(&lock, NULL) != 0) {
printf("\n mutex init failed\n");
return 1;
}
pthread_t pthread1, pthread2;
if (pthread_create(&pthread1, NULL, thread1, NULL))
return -1;
if (pthread_create(&pthread2, NULL, thread2, NULL))
return -1;
pthread_join(pthread1, NULL);
pthread_join(pthread2, NULL);
pthread_mutex_destroy(&lock);
return 0;
}

Using Condition Variables for Asynchronous Execution.

So I'm creating a drone simulation with Pthreads and Ncurses, I can have my code work perfectly for any number of threads synchronously, simply using a Mutex to serialize the updating of my screen. However I want to create an asynchronous simulation. Right now I'm trying to use the POSIX condvar. The idea is to the synchronize the threads on movement. So say I want to move 10 threads in 10 positions in the x direction. I want Thread1 to move one unit in the X direction, then give Thread2 the ability to move in the x-direction and so on. This is just my code for handling the creation of the pthreads and attempting synchronization:
int init_threads()
{
int rc = 0; int i = 0; long t = 0;
pthread_t threads[NUM_THREADS];
pthread_mutex_init(&mutex_lock, NULL);
pthread_cond_init(&count_threshold_cv, NULL);
for(i; i < 2; i++)
{
rc = pthread_create(&threads[i], NULL, DCAS, (void *)t);
if(rc)
{
printf("Error return from create is %d\n", rc);
return -1;
}
}
pthread_exit(NULL);
}
void * DCAS(void * PID)
{
Tuple win = find_window();
int start_x = win.a/2; int start_y = win.b/2;
pthread_mutex_lock(&mutex_lock);
while(start_x != 10)
{
pthread_cond_wait(&count_threshold_cv, &mutex_lock);
}
update_screen();
pthread_mutex_unlock(&mutex_lock);
}
void update_screen()
{
Tuple win = find_window();
int start_x = win.a/2; int start_y = win.b/2;
pthread_mutex_lock(&mutex_lock);
mvwaddch(local_win, start_x, start_y, 'o');
init_base_layouts();
wrefresh(local_win);
sleep(1);
start_x--;
pthread_cond_signal(&count_threshold_cv);
pthread_mutex_lock(&mutex_lock);
}
It is exactly creating two pthreads and attempting to signal the cond-var when a thread is moved to allow another thread the ability to move in the same x-direction for 10 x positions. I cant seem to get the condition to signal that the thread has moved however. Thanks so much in advanced!
If you wait on a condition variable, you must be waiting for some particular condition over some shared state to change (that's why it's called a condition variable).
However, the condition you are waiting on (while (start_x != 10)) is not over shared state: start_x is a local variable to each thread, which is not shared.
It's not clear exactly what state you want to wait for: however, if what you want is for each thread to move once and then not move again until all the other threads have had a chance to move, then a pthread barrier might be the appropriate primitive.
In the main function, before the threads are created:
pthread_barrier_init(&barrier, NULL, NUM_THREADS);
(where NUM_THREADS is the number of moving threads that are to be created). Then in each moving thread:
for (i = 0; i < 10; i++)
{
move();
pthread_barrier_wait(&barrier);
}
All the threads will then move once (in an unspecified order), and then not continue until all other threads have moved as well.

pthread_mutex_lock causes deadlock

I am using the above code to increment a counter using 2 threads, which independently take the mut lock and increment counter. I am facing a deadlock after the threads enter this function.
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
void *increment_counter(void *counter_addr)
{
int max = MAX_COUNTER_VALUE;
int iter;
int counter;
for(iter=0;iter< max ;iter++)
// LOCK
pthread_mutex_lock(&mut);
counter++;
// UNLOCK
pthread_mutex_unlock(&mut);
return NULL;
}
Could anyone please tell me where exactly am I going wrong?
You're trying to lock the mutex max times, then increment counter and release it once.
Try:
for(iter=0;iter< max ;iter++)
{
// LOCK
pthread_mutex_lock(&mut);
counter++;
// UNLOCK
pthread_mutex_unlock(&mut);
}
return NULL;
That is maybe what you tried to do:
int max = MAX_COUNTER_VALUE;
int iter;
int counter;
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
void *increment_counter(void *counter_addr)
{
pthread_mutex_lock(&mut);
for(iter=0;iter< max ;iter++)
counter++;
pthread_mutex_unlock(&mut);
return NULL;
}
2 or more threads share only global scope data or data located on the
heap(malloc).
2 or more threads do not share variables defined on the stack this
data is unique to each thread and there is no need to lock it.
You are welcomed to read in the answers what is shared and what is not shared etc.
As a principle, the same thread should not lock a mutex more than once and that's what happened here.
lock initialization is very important. If you don't initialize your locks to the right value your code breaks. One method for initializing your lock is the following:
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
Also you can do this task dynamically by using the following code:
int rc = pthread_mutex_init(&lock, NULL);
assert(rc == 0); // always check success!
Beside lock initialization, you should check for the return code of pthread_mutex_lock to see if it fails or not as if it fails, multiple thread can enter the critical section. For this purpose, you can use a code similar to this which checks for the return code of pthread_mutex_lock:
// Use this to keep your code clean but check for failures
// Only use if exiting program is OK upon failure
void Pthread_mutex_lock(pthread_mutex_t *mutex) {
int rc = pthread_mutex_lock(mutex);
assert(rc == 0);
}

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.

Resources