I have a program with multiple threads.
In my main thread I examine in a permanent loop whether a global variable has the value 1.
This variable I set during the runtime in the other thread with a Mutex locked on it to 1.
So the if condition should be true in the main thread. But it doesn't work... But if i put a printf before the if condition it works. This is so weird I have no idea whats wrong. Thanks
The code:
while(1)
{
printf("\n");
if(logging_active == 1) {
//check filesize every 30s. If logfile size over 1MB (1.000.000) send file
if((timestamp_realtime_sec() - last_time) >= ((logtime+1))) {
printf("check filesize...\n");
if(fileSize("log") > 100000) {
logfileHandler("log");
}
last_time = timestamp_realtime_sec();
}
}
}
Output:
check filesize ...
Without the printf it's output nothing.
Solution for me:
changing the variable declaration from int logging_active to volatile int logging_active solved the problem.
I am assuming you are locking mutex and updating logging_active in other thread. You should lock the same mutex and do the check in current thread.
pthread_mutex_lock(mutex);
while(logging_active == 0) {
pthread_mutex_unlock(mutex)
sleep(SOME_TIME);
}
pthread_mutex_unlock(mutex)
//Your code
}
But I recommend you to use condition variables.
The compiler doesn't know you're updating the variable from another thread, so it may not be actually checking it every time. Mark the variable as volatile and it should work as you expect. This tells the compiler that it isn't allowed to omit loads from that variable--it really has to read it every time.
Related
#include <stdio.h>
#include <pthread.h>
long mails = 0;
int lock = 0;
void *routine()
{
printf("Thread Start\n");
for (long i = 0; i < 100000; i++)
{
while (lock)
{
}
lock = 1;
mails++;
lock = 0;
}
printf("Thread End\n");
}
int main(int argc, int *argv[])
{
pthread_t p1, p2;
if (pthread_create(&p1, NULL, &routine, NULL) != 0)
{
return 1;
}
if (pthread_create(&p2, NULL, &routine, NULL) != 0)
{
return 2;
}
if (pthread_join(p1, NULL) != 0)
{
return 3;
}
if (pthread_join(p2, NULL) != 0)
{
return 4;
}
printf("Number of mails: %ld \n", mails);
return 0;
}
In the above code each thread runs a for loop to increase the value
of mails by 100000.
To avoid race condition is used lock variable
along with while loop.
Using while loop in routine function does not
help to avoid race condition and give correct output for mails
variable.
In C, the compiler can safely assume a (global) variable is not modified by other threads unless in few cases (eg. volatile variable, atomic accesses). This means the compiler can assume lock is not modified and while (lock) {} can be replaced with an infinite loop. In fact, this kind of loop cause an undefined behaviour since it does not have any visible effect. This means the compiler can remove it (or generate a wrong code). The compiler can also remove the lock = 1 statement since it is followed by lock = 0. The resulting code is bogus. Note that even if the compiler would generate a correct code, some processor (eg. AFAIK ARM and PowerPC) can reorder instructions resulting in a bogus behaviour.
To make sure accesses between multiple threads are correct, you need at least atomic accesses on lock. The atomic access should be combined with proper memory barriers for relaxed atomic accesses. The thing is while (lock) {} will result in a spin lock. Spin locks are known to be a pretty bad solution in many cases unless you really know what you are doing and all the consequence (in doubt, don't use them).
Generally, it is better to uses mutexes, semaphores and wait conditions in this case. Mutexes are generally implemented using an atomic boolean flag internally (with right memory barriers so you do not need to care about that). When the flag is mark as locked, an OS sleeping function is called. The sleeping function wake up when the lock has been released by another thread. This is possible since the thread releasing a lock can send a wake up signal. For more information about this, please read this. In old C, you can use pthread for that. Since C11, you can do that directly using this standard API. For pthread, it is here (do not forget the initialization).
If you really want a spinlock, you need something like:
#include <stdatomic.h>
atomic_flag lock = ATOMIC_FLAG_INIT;
void *routine()
{
printf("Thread Start\n");
for (long i = 0; i < 100000; i++)
{
while (atomic_flag_test_and_set(&lock)) {}
mails++;
atomic_flag_clear(&lock);
}
printf("Thread End\n");
}
However, since you are already using pthreads, you're better off using a pthread_mutex
Jérôme Richard told you about ways in which the compiler could optimize the sense out of your code, but even if you turned all the optimizations off, you still would be left with a race condition. You wrote
while (lock) { }
lock=1;
...critical section...
lock=0;
The problem with that is, suppose lock==0. Two threads racing toward that critical section at the same time could both test lock, and they could both find that lock==0. Then they both would set lock=1, and they both would enter the critical section...
...at the same time.
In order to implement a spin lock,* you need some way for one thread to prevent other threads from accessing the lock variable in between when the first thread tests it, and when the first thread sets it. You need an atomic (i.e., indivisible) "test and set" operation.
Most computer architectures have some kind of specialized op-code that does what you want. It has names like "test and set," "compare and exchange," "load-linked and store-conditional," etc. Chris Dodd's answer shows you how to use a standard C library function that does the right thing on whatever CPU you happen to be using...
...But don't forget what Jérôme said.*
* Jérôme told you that spin locks are a bad idea.
I'm using semaphors. I have two threads. The first thread, every two seconds, executes a loop that creates a dynamic array. At the beginning of the loop it creates the dynamic array, and eventually deletes it. On the other hand, a thread must write to this dynamic array, obviously provided that it has already been created and that it has not yet been deleted (i.e., after creation and before deletion). I don't know how to use correctly semaphores. Where am I doing wrong? Thank you for your help!
int *array
int position = 0;
static void *thread_A(void *p_vp_arg)
{
while (1)
{
sem_post(&sem);
array = malloc(1024*sizeof(int));
/* SOME STUFF HERE */
sleep(2);
free(array);
}
}
static void function_B(...){
if(sem_trywait(&sem)){
printf("I can write into the array\n");
array[position] = variable;
position += 1;
}
}
Into the main:
sem_init(&sem, 0, 0)
In your deceleration of the array you perform sem_post() before you allocate the array this should really be after it, with a sem_wait() before the deletion as right now you are releasing the lock and allowing the other thread to try access it before it has been malloced. and you could also delete it while another thread is currently writing to the array.
In the writing method i would switch to using sem_wait instead of sem_trywait it will then handle most of the waiting itself. this is unless you have a specific reason to use sem_trywait
Also don't use the sem result from sem_trywait() or any sem as a loop condition this can cause it to fail. instead do
int result = sem_trywait(&sem)
if(result == 0){
//rest of code
it returns 0 on success and or an errorcode for anything else more can be read on the manual page about the specific errors
Finally you never release the lock in the writing thread, you need to do sem_post() when you are done with the lock as right now you never release the lock.
I have written this code in C language and there are two pthreads that are using this code and trying to access the mutex "firstSection" (in both of them we are sure that the mutex passed to function is the same). The code suppose to check two mutexes, and if both of them were available, performs some actions which take place in function safeUnlockTwoMutexes(), and if failed to acquire at least one of them, it has to wait for two seconds and tries again. ("intersection" mutex is the main-lock to safe check the situation of the other mutexes)
void twoSectionRoute(pthread_mutex_t firstSection, pthread_mutex_t secondSection){
bool pathClear = false;
while (!pathClear){
pthread_mutex_lock(&intersection);
if (pthread_mutex_trylock(&firstSection) == 0){
if (pthread_mutex_trylock(&secondSection) == 0){
pathClear = true;
pthread_mutex_unlock(&intersection);
} else {
pthread_mutex_unlock(&firstSection);
pthread_mutex_unlock(&intersection);
sleep(2);
}
} else {
pthread_mutex_unlock(&intersection);
sleep(2);
}
}
safeUnlockTwoMutexes(firstSection, secondSection, 1);
}
Now the problem with this code is both threads are able to lock the mutex "firstSectio" at almost same time and I don't know why. (maybe because its type is recursive mutex?! I've used "PTHREAD_MUTEX_INITIALIZER" in the beginning of the file as global variables)
I'm wondering how can I fix this issue, and the threads access this sections one after another?
Your function signature passes pthread_mutex_t values firstSection and secondSection by value. You need to pass mutexes by pointer.
void twoSectionRoute(pthread_mutex_t* firstSection, pthread_mutex_t* secondSection){
Then, within the function use just firstSection and secondSection rather than &firstSection and &secondSection.
If you pass the mutex by value (as here), and it compiles, then the mutex itself is copied, so you end up with undefined behaviour and the mutex locks do not operate on the same state.
This question already has an answer here:
Pthread_create() incorrect start routine parameter passing
(1 answer)
Closed 3 years ago.
I tried to build a program which should create threads and assign a Print function to each one of them, while the main process should use printf function directly.
Firstly, I made it without any synchronization means and expected to get a randomized output.
Later I tried to add a mutex to the Print function which was assigned to the threads and expected to get a chronological output but it seems like the mutex had no effect about the output.
Should I use a mutex on the printf function in the main process as well?
Thanks in advance
My code:
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
pthread_t threadID[20];
pthread_mutex_t lock;
void* Print(void* _num);
int main(void)
{
int num = 20, indx = 0, k = 0;
if (pthread_mutex_init(&lock, NULL))
{
perror("err pthread_mutex_init\n");
return errno;
}
for (; indx < num; ++indx)
{
if (pthread_create(&threadID[indx], NULL, Print, &indx))
{
perror("err pthread_create\n");
return errno;
}
}
for (; k < num; ++k)
{
printf("%d from main\n", k);
}
indx = 0;
for (; indx < num; ++indx)
{
if (pthread_join(threadID[indx], NULL))
{
perror("err pthread_join\n");
return errno;
}
}
pthread_mutex_destroy(&lock);
return 0;
}
void* Print(void* _indx)
{
pthread_mutex_lock(&lock);
printf("%d from thread\n", *(int*)_indx);
pthread_mutex_unlock(&lock);
return NULL;
}
All questions of program bugs notwithstanding, pthreads mutexes provide only mutual exclusion, not any guarantee of scheduling order. This is typical of mutex implementations. Similarly, pthread_create() only creates and starts threads; it does not make any guarantee about scheduling order, such as would justify an assumption that the threads reach the pthread_mutex_lock() call in the same order that they were created.
Overall, if you want to order thread activities based on some characteristic of the threads, then you have to manage that yourself. You need to maintain a sense of which thread's turn it is, and provide a mechanism sufficient to make a thread notice when it's turn arrives. In some circumstances, with some care, you can do this by using semaphores instead of mutexes. The more general solution, however, is to use a condition variable together with your mutex, and some shared variable that serves as to indicate who's turn it currently is.
The code passes the address of the same local variable to all threads. Meanwhile, this variable gets updated by the main thread.
Instead pass it by value cast to void*.
Fix:
pthread_create(&threadID[indx], NULL, Print, (void*)indx)
// ...
printf("%d from thread\n", (int)_indx);
Now, since there is no data shared between the threads, you can remove that mutex.
All the threads created in the for loop have different value of indx. Because of the operating system scheduler, you can never be sure which thread will run. Therefore, the values printed are in random order depending on the randomness of the scheduler. The second for-loop running in the parent thread will run immediately after creating the child threads. Again, the scheduler decides the order of what thread should run next.
Every OS should have an interrupt (at least the major operating systems have). When running the for-loop in the parent thread, an interrupt might happen and leaves the scheduler to make a decision of which thread to run. Therefore, the numbers being printed in the parent for-loop are printed randomly, because all threads run "concurrently".
Joining a thread means waiting for a thread. If you want to make sure you print all numbers in the parent for loop in chronological order, without letting child thread interrupt it, then relocate the for-loop section to be after the thread joining.
My problem is that I cannot reuse cancelled pthread. Sample code:
#include <pthread.h>
pthread_t alg;
pthread_t stop_alg;
int thread_available;
void *stopAlgorithm() {
while (1) {
sleep(6);
if (thread_available == 1) {
pthread_cancel(alg);
printf("Now it's dead!\n");
thread_available = 0;
}
}
}
void *algorithm() {
while (1) {
printf("I'm here\n");
}
}
int main() {
thread_available = 0;
pthread_create(&stop_alg, NULL, stopAlgorithm, 0);
while (1) {
sleep(1);
if (thread_available == 0) {
sleep(2);
printf("Starting algorithm\n");
pthread_create(&alg, NULL, algorithm, 0);
thread_available = 1;
}
}
}
This sample should create two threads - one will be created at the program beginning and will try to cancel second as soon it starts, second should be rerunned as soon at it was cancelled and say "I'm here". But when algorithm thread cancelled once it doesn't start once again, it says "Starting algorithm" and does nothing, no "I'm here" messages any more. Could you please tell me the way to start cancelled(immediately stopped) thread once again?
UPD: So, thanks to your help I understood what is the problem. When I rerun algorithm thread it throws error 11:"The system lacked the necessary resources to create another thread, or the system-imposed limit on the total number of threads in a process PTHREAD_THREADS_MAX would be exceeded.". Actually I have 5 threads, but only one is cancelled, others stop by pthread_exit. So after algorithm stopped and program went to standby mode I checked status of all threads with pthread_join - all thread show 0(cancelled shows PTHREAD_CANCELED), as far as I can understand this means, that all threads stopped successfully. But one more try to run algorithm throws error 11 again. So I've checked memory usage. In standby mode before algorithm - 10428, during the algorithm, when all threads used - 2026m, in standby mode after algorithm stopped - 2019m. So even if threads stopped they still use memory, pthread_detach didn't help with this. Are there any other ways to clean-up after threads?
Also, sometimes on pthread_cancel my program crashes with "libgcc_s.so.1 must be installed for pthread_cancel to work"
Several points:
First, this is not safe:
int thread_available;
void *stopAlgorithm() {
while (1) {
sleep(6);
if (thread_available == 1) {
pthread_cancel(alg);
printf("Now it's dead!\n");
thread_available = 0;
}
}
}
It's not safe for at least reasons. Firstly, you've not marked thread_available as volatile. This means that the compiler can optimise stopAlgorithm to read the variable once, and never reread it. Secondly, you haven't ensured access to it is atomic, or protected it by a mutex. Either declare it:
volatile sig_atomic_t thread_available;
(or similar), or better, protect it by a mutex.
But for the general case of triggering one thread from another, you are better using a condition variable (and a mutex), using pthread_condwait or pthread_condtimedwait in the listening thread, and pthread_condbroadcast in the triggering thread.
Next, what's the point of the stopAlgorithm thread? All it does is cancel the algorithm thread after an unpredictable amount of time between 0 and 6 seconds? Why not just sent the pthread_cancel from the main thread?
Next, do you care where your algorithm is when it is cancelled? If not, just pthread_cancel it. If so (and anyway, I think it's far nicer), regularly check a flag (either atomic and volatile as above, or protected by a mutex) and pthread_exit if it's set. If your algorithm does big chunks every second or so, then check it then. If it does lots of tiny things, check it (say) every 1,000 operations so taking the mutex doesn't introduce a performance penalty.
Lastly, if you cancel a thread (or if it pthread_exits), the way you start it again is simply to call pthread_create again. It's then a new thread running the same code.