This is a strange problem.I init sem and destory it first,then i init it again in a thread.then, i can't wake it again.the code is:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <time.h>
#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <pthread.h>
sem_t sem;
int key = 1;
static void *
wait_func()
{
printf("i'm wait\n");
sem_wait(&sem);
}
static void *
cancel_func(void *arg)
{
pthread_t tid = *(pthread_t *)arg;
if (key == 1)
{
sleep(1);
key = 0;
}
else
sleep(3);
if(pthread_cancel(tid) == 0)
printf("cancle!\n");
sem_init(&sem, 0, 0);
sem_destroy(&sem);
}
int
main(int argc, char *argv[])
{
pthread_t wthread, cthread;
pthread_attr_t attr;
int i = 0;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
sem_init(&sem, 0, 0);
while (i < 2)
{
// sem_init(&sem, 0, 0);
pthread_create(&wthread, &attr, wait_func, NULL);
if (i < 1)
pthread_create(&cthread, &attr, cancel_func, &wthread);
if (key == 0)
{
sleep(2);
if (sem_post(&sem) == 0)
printf("post!\n");
key = 1;
}
sleep(4);
++i;
}
sleep(1000);
}
however,it will be work that changed sem_init in while loop like comment!So i have straced two program,and finded 1)init in thread,sem_post didn't call sys_futex,like this:
nanosleep({2, 0}, i'm wait
{2, 0}) = 0 write(1, "post!\\n", 6post! ) = 6
2)init in main process,sem_post call sys_futex,like this:
nanosleep({2, 0}, i'm wait
{2, 0}) = 0 futex(0x600dc0, FUTEX_WAKE_PRIVATE, 1) = 1 write(1, "post!\\n", 6post! ) = 6
Then,i thought maybe this is a problem with syscall.I have used gdb to disassemble two program in sem_post. unfortunately,1)init in thread,it also call syscall in sem_post;2) compared their registry status where rip is syscall,same too.
in thread:
rax 0xca 202 //sys_futex
rbx 0x3c0e61bbc0 257939323840
rcx 0x0 0 //utime
rdx 0x1 1 //val
rsi 0x81 129 //op:private_wake
rdi 0x600dc0 6294976 //sem uaddr
in main process:
rax 0xca 202
rbx 0x3c0e61bbc0 257939323840
rcx 0x0 0
rdx 0x1 1
rsi 0x81 129
rdi 0x600da0 6294944
At last,i have no idea about this problem.Please give me some advise to find out the solution,thanks.
I think that your problem lies in the access to key
. There is no guarantee that the access to shared variables is atomic. In particular the compiler might optimize the reading of a value from memory, such that it doesn't see a modification of the value that is done in another thread.
To avoid that the optimizer kicks in, you'd have to declare your key
variable volatile
. But I am not sure that the way you have written your program would guarantee that there are memory barriers that would guarantee that the threads are guaranteed to seen modifications and that the concurrent write is not mixing things up.
Modern C11 also has _Atomic
to ensure that the access is atomic. But C11 is not yet fully implemented (there may be some compilers that have that feature). If it would be, there would be a problem with semaphores, since C11 only has mutexes and not semaphores as lock structures. How these two features would cooperate is not specified, yet.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.