How does Mutex scope work - c

How does mutex scope work exactly.
If I want 3 mutexes for different things and place them as so
static pthread_mutex_t watchdogMutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t watchdogCond = PTHREAD_COND_INITIALIZER;
int waitingForGpsSetupThread = 1;
static pthread_mutex_t gpsRunningMutex = PTHREAD_MUTEX_INITIALIZER;
int gpsRunning = 0;
static pthread_mutex_t indoorNavigationRunningMutex = PTHREAD_MUTEX_INITIALIZER;
int indoorSystemRunning = 0;
Are the variables defined within the scope of the first above mutex declaration or how does it work?

These are just C variables. It doesn't matter in what order you declare them. What matters is in what order you try to acquire/lock the mutexes if you want to hold them at the same time (as in "always acquire resources in the same order" mantra).
Edit 0:
Looks like you can use some introductory threads material:
POSIX Threads Programming
Pthreads Tutorial
I still remember how to google ... :)

As written, the three mutexes are all in the same scope. There are no blocks marked by '{...}' to indicate otherwise. The same would be true if the types were all int. From that point of view, a mutex is no different from any other type.
At the point of use, you would do something like:
pthread_mutex_lock(&watchdogMutex);
...operations protected by the watchdog mutex...
pthread_mutex_unlock(&watchdogMutex);
The bit in the middle could be said to be the scope in which the mutex is locked. It would be a very bad idea to have a return statement in the middle of those operations - unless the mutex was also unlocked before returning.
See the POSIX definitions.

Related

How to safely modify string from another thread in C with pthreads?

I am trying to create a simple CLI music player in C. I have created a second thread aside from the main thread which is responsible for playing the music. The second thread receives an argument like so (I have tried with and without the volatile keyword):
typedef struct AUDIO_S
{
volatile char audio_path[MAX_PATH];
volatile int play_state;
} audio_t;
The main thread may update both the audio path (current file) and the play state (playing/paused). The job of the second thread is to detect this change and act accordingly by changing, playing, or pausing the song.
I have an issue where what (I assume) is happening is that the second thread reads this data at the same time as it is being written to by the main thread, which is producing garbled output. I tried implementing a conditional variable but I'm still getting bad output.
Here is the code where I write the data:
extern pthread_mutex_t mutex;
extern pthread_cond_t cond;
pthread_mutex_lock(&mutex);
strcpy(audio->audio_path, state->cur_play_dir);
strcat(audio->audio_path, "/");
strcat(audio->audio_path, state->cur_play_file);
audio->play_state = MUSIC_PLAY;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
And here is the code where I read it:
extern pthread_mutex_t mutex;
extern pthread_cond_t cond;
while (1)
{
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
char *new_audio_path = audio->audio_path;
if (strcmp(new_audio_path, cur_audio_path))
{
cur_audio_path = realloc(cur_audio_path,
strlen(new_audio_path) + 1);
strcpy(cur_audio_path, audio->audio_path);
printw("PATH: %s\n", cur_audio_path);
}
pthread_mutex_unlock(&mutex);
}
The mutex and the condition are declared as global variables like so:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
I'm fairly new to parallel programming so I suspect I'm doing something glaringly obvious and stupid.
After sleeping on the issue I realised my mistake. As it turns out there was actually no issue at all with the data stored in the path string.
In the second thread I was printing the value of the path to stdout purely to check that the value was valid (so I forgot to lock anything). However, in the main thread, I was also printing other data to stdout.
With two threads both writing to stdout the data appeared garbled when printed when in reality there was no issue with the data stored in memory. I verified this by instead writing to a text file in the second thread while the first thread wrote to stdout. The data written to the text file had no issues.

Problem in communication of three threads in C language (deadlock occurs)

I am creating a program in which i have 3 linked lists and I am trying to update or remove the nodes from these linked lists in these three threads. But the deadlock is occurring
The insertion and deletion is working fine. Here the three variables var1InUse,var2InUse and var3InUse are indicating that whether the 3 linked lists are in use or not(Not all three are use in the all threads). I am putting the threads on waiting based on var1InUse,var2InUse and var3InUse as you can see in the code. Sometimes this works fine but sometimes deadlock happens. I have searched for the solution on the internet but could find it.
Am I using the wait and signal methods correctly?
pthread variables declaration
pthread_mutex_t myMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t t1cond = PTHREAD_COND_INITIALIZER;
pthread_cond_t t2cond = PTHREAD_COND_INITIALIZER;
pthread_cond_t t3cond = PTHREAD_COND_INITIALIZER;
int var1InUse=0,var2InUse=0,var3InUse=0;
THREAD 1
void* thread1(void* args){
while(var1InUse || var2InUse ) {
pthread_cond_wait(&t1cond,&myMutex);}
var1InUse=1,var2InUse=1;
while(1){
pthread_mutex_lock(&myMutex);
/*
some other code about adding and removing from
linkedlist
*/
var1InUse=0,var2InUse=0;
pthread_cond_signal(&t2cond);
pthread_cond_signal(&t3cond);
pthread_mutex_unlock(&myMutex);}
}
THREAD 2
void* thread2(void* args){
while(var1InUse || var2InUse || var3InUse) {
pthread_cond_wait(&t2cond,&myMutex);}
var1InUse=1,var2InUse=1,var3InUse=1;
while(1){
pthread_mutex_lock(&myMutex);
/*
some other code adding and removing from linkedlist
*/
var1InUse=0,var2InUse=0,var3InUse=0;
pthread_cond_signal(&t1cond);
pthread_cond_signal(&t3cond);
pthread_mutex_unlock(&myMutex);}
}
THREAD 3
void* thread3(void* args){
while(var1InUse || var3InUse ) {
pthread_cond_wait(&t3cond,&myMutex);}
var1InUse=1,var3InUse=1;
while(1){
pthread_mutex_lock(&myMutex);
/*
some other code adding and removing from linkedlist
*/
var1InUse=0,var3InUse=0;
pthread_cond_signal(&t1cond);
pthread_cond_signal(&t2cond);
pthread_mutex_unlock(&myMutex);}
}
MAIN METHOD
int main(){
pthread_t t1,t2,t3,t4;
pthread_mutex_init(&myMutex,0);
pthread_create(&t1,NULL,thread1,NULL);
pthread_create(&t2,NULL,thread2,NULL);
pthread_create(&t3,NULL,thread3,NULL);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
pthread_join(t3,NULL);
pthread_mutex_destroy(&myMutex);
return 0
}
I want the deadlock to be removed.
The mutex used by pthread_cond_wait() needs to locked before the function is called. Here is an extract from the man page:
The pthread_cond_timedwait() and pthread_cond_wait() functions shall block on a condition variable. The application shall ensure that these functions are called with mutex locked by the calling thread; otherwise, an error (for PTHREAD_MUTEX_ERRORCHECK and robust mutexes) or undefined behavior (for other mutexes) results.
Although pthread_cond_wait() unlocks the mutex internally, it is locked again before the function returns successfully:
Upon successful return, the mutex shall have been locked and shall be owned by the calling thread.
Additionally, you should access the shared variables var1InUse, var2InUse and var3InUse with the mutex locked.
Here is a modified version of your thread1() that follows these rules. The modifications to the other thread start routines should be similar:
void* thread1(void* args){
pthread_mutex_lock(&myMutex);
while(var1InUse || var2InUse ) {
pthread_cond_wait(&t1cond,&myMutex);
}
var1InUse=1,var2InUse=1;
pthread_mutex_unlock(&myMutex);
while(1){
pthread_mutex_lock(&myMutex);
/*
some other code about adding and removing from linkedlist
*/
var1InUse=0,var2InUse=0;
pthread_cond_signal(&t2cond);
pthread_cond_signal(&t3cond);
pthread_mutex_unlock(&myMutex);
}
return NULL;
}
(I'm not entirely sure that the above is correct, because it's not entirely clear from the original code what the while(1) loop is supposed to do.)

pthreads: exclusive+concurrent functions (inverse semaphore)

I have code that locks every function (of a certain library), and which I would like to optimize. Given functions A and B, I don't mind any A running concurrently with any other A, or any B running concurrently with any other B, but no A can run while any B is running, and vice-versa. The thread count is dynamic and for reason out of my control I am forced to use static allocation for mutexes and conditional variables (i.e. PTHREAD_MUTEX_INITIALIZER).
I have a hunch that the most efficient approach is two conditional variables. Using pthread_mutex_trylock allows one function (i.e. A) to run in parallel while the other must be serialized. Also *trylock with static initialization is actually undefined behavior...
Edit:
Perhaps something like this? I'm not sure if this:
Can be simpler. After all, mutexes are implemented using semaphores, but it takes four mutexes and two conditional variables to implement what is basically an inverse semaphore.
Covers all race conditions.
Is "fair" (beyond default priority and scheduling)?
static int countA = 0;
static int countB = 0;
static pthread_mutex_t lockCountA = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t lockCountB = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t lockA = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t lockB = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t condA = PTHREAD_COND_INITIALIZER;
static pthread_cond_t condB = PTHREAD_COND_INITIALIZER;
// for B(), just s/B/A/g
static void A(void) {
pthread_mutex_lock(&lockB);
while(countB)
pthread_cond_wait(&condB, &lockB);
pthread_mutex_lock(&lockCountA);
countA += 1;
pthread_mutex_unlock(&lockCountA)
doA();
pthread_mutex_lock(&lockCountA)
countA -= 1;
if countA == 0:
pthread_cond_signal(&condA);
mutex_unlock(&lockCountA)
mutex_unlock(&lockB);
}
Your solution has a race condition. Consider the case when both countA and countB are zero, and two threads simultaneously call A() and B(). The first thread locks lockB, the second thread locks lockA, both see the count they examine as zero, then proceed to increment their respective counts and proceed in error.
Another problem in your solution is that it uses pthread_cond_signal() which does not necessarily wake any more than one waiting thread, so if you have 10 threads waiting to enter B() but only one thread running A(), when the latter thread finishes only one B() thread is guaranteed to continue and the other 9 may wait indefinitely.
It also doesn't allow more than one thread to run doA() concurrently, since lockB is held over that call.
To fix the first problem, you can use one mutex that protects both countA and countB (because the shared state we must examine involves the combination of both these variables). At the same time, you might as well just use one condition variable too: the threads waiting on the condition variable must either be all waiting to enter A(), or all waiting to enter B(), but a mix of the two is impossible. Fixing the second problem just requires pthread_cond_broadcast(). That leads to the much simpler:
static int countA = 0;
static int countB = 0;
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void A(void)
{
pthread_mutex_lock(&lock);
while (countB)
pthread_cond_wait(&cond, &lock);
countA++;
pthread_mutex_unlock(&lock);
do_A();
pthread_mutex_lock(&lock);
countA--;
if (!countA)
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&lock);
}
This solution is correct, but is not "fair" - if there is a continuous stream of threads executing A() (such that a new one enters and increments countA before the previous thread has finished and decremented it) then the threads waiting to execute B() will be kept waiting forever. This may not be an issue in your particular use - for example, if you know that any thread that executes A() will eventually execute B(), then the starvation situation must eventually resolve.
Improving the system to prevent this starvation can be done by preventing new entries into A() while there are threads queued to enter B():
static int countA = 0;
static int countB = 0;
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static int queuedA = 0;
static int queuedB = 0;
static pthread_cond_t queue_cond = PTHREAD_COND_INITIALIZER;
void A(void)
{
pthread_mutex_lock(&lock);
while (queuedB)
pthread_cond_wait(&queue_cond, &lock);
while (countB)
{
queuedA++;
pthread_cond_wait(&cond, &lock);
queuedA--;
}
if (!queuedA)
pthread_cond_broadcast(&queue_cond);
countA++;
pthread_mutex_unlock(&lock);
do_A();
pthread_mutex_lock(&lock);
countA--;
if (!countA)
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&lock);
}
This prevents starvation because:
queuedB is always non-zero while there are any threads waiting on cond in B();
While queuedB is non-zero, no threads may increment countA, and therefore countA must eventually reach zero and allow the threads waiting on cond to proceed.
while countA is zero, no thread may increment queuedB and thus queuedB must eventually reach zero and allow the threads waiting on queue_cond to proceed.

Pthread: when Dynamic mutex initialization must be used

As everyone knows, there are two ways how to init pthread mutex (C language)
Static initialization:
pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
Dynamic initialization:
pthread_mutexattr_t attr;
pthread_mutex_t mutex;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP);
pthread_mutex_init(&mutex, &attr);
var 1 - I used it many times.
var 2 - the reason I posted this question:
Will really appreciate if someone could provide me with some real example(s) when dynamic initialization of pthread mutex must be used.
Thanks!
You always need the pthread_*_init() functions if the default attributes won't do/are not suitable.
An example can be found at the bottom of this page.

C: How do you declare a recursive mutex with POSIX threads?

I am a bit confused on how to declare a recursive mutex using pthread.
What I try to do is have only one thread at a time be able to run a piece of code(including functions) but after scepticism I figured out that the use of mutexes would not work and that instead I should use recursive mutexes. Here is my code:
pthread_mutex_lock(&mutex); // LOCK
item = queue_peek(queue); // get last item in queue
item_buff=item; // save item to a buffer
queue_removelast(queue); // remove last item from queue
pthread_mutex_unlock(&mutex); // UNLOCK
So what I try to do is just read/remove from the queue serially.
The thing is that there isn't any example out there on how to declare recursive mutexes. Or there maybe a few but they don't compile for me.
The code from Michael Foukarakis is almost good but he initializes the mutex twice which leads to undefined behavior. It should just be:
pthread_mutex_t Mutex;
pthread_mutexattr_t Attr;
pthread_mutexattr_init(&Attr);
pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&Mutex, &Attr);
I actually use this code in production, and I know it works correctly on Linux, Solaris, HP-UX, AIX, Mac OSX and FreeBSD.
You also need to add proper linker flag to compile this:
AIX, Linux, FreeBSD:
CPLATFORM += -pthread
mingw32:
LDFLAGS += -lpthread
To create a recursive mutex, you can either use:
#include <pthread.h>
/* Don't forget to check the return value! */
int pthread_mutexatttr_settype(pthread_mutexattr_t *attr,
int type);
where type is PTHREAD_MUTEX_RECURSIVE, or an initialiser.
For example:
/* ..or PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutexattr_t mta;
or alternatively, initialize at runtime (don't do both, it's undefined behaviour):
pthread_mutexattr_init(&mta);
/* or PTHREAD_MUTEX_RECURSIVE_NP */
pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mutex, &mta);
On Linux (but this is non portable to other systems), if the mutex is a global or static variable, you could initialize it like
static pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
(and by the way, the example is from pthread_mutex_init(3) man pages!)
You need to add mutex attributes when creating the mutex.
Call pthread_mutexattr_init, then pthread_mutexattr_settype with PTHREAD_MUTEX_RECURSIVE then use these attributes with pthread_mutex_init. Read man pthread_mutexattr_init for more info.

Resources