mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 15:03:34 +00:00
Demonstrate signal safety of recursive mutexes
This commit is contained in:
parent
135d538b1d
commit
fdab49b30e
2 changed files with 112 additions and 0 deletions
30
test/posix/exit_async_signal_safety_test.c
Normal file
30
test/posix/exit_async_signal_safety_test.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
#include <pthread.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
atomic_bool ready;
|
||||
|
||||
void* work(void* arg) {
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
|
||||
ready = true;
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
pthread_t th;
|
||||
if (pthread_create(&th, 0, work, 0))
|
||||
_Exit(1);
|
||||
for (;;)
|
||||
if (ready)
|
||||
break;
|
||||
pthread_cancel(th);
|
||||
if (pthread_join(th, 0))
|
||||
_Exit(3);
|
||||
}
|
||||
|
||||
while (!pthread_orphan_np())
|
||||
pthread_decimate_np();
|
||||
}
|
82
test/posix/mutex_async_signal_safety_test.c
Normal file
82
test/posix/mutex_async_signal_safety_test.c
Normal file
|
@ -0,0 +1,82 @@
|
|||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// tests that recursive mutexes are implemented atomically
|
||||
//
|
||||
// glibc fails this test
|
||||
|
||||
atomic_bool done;
|
||||
atomic_bool ready;
|
||||
pthread_mutex_t lock;
|
||||
|
||||
void hand(int sig) {
|
||||
if (pthread_mutex_lock(&lock))
|
||||
_Exit(50);
|
||||
if (pthread_mutex_unlock(&lock))
|
||||
_Exit(51);
|
||||
}
|
||||
|
||||
void* work(void* arg) {
|
||||
ready = true;
|
||||
while (!done) {
|
||||
if (pthread_mutex_lock(&lock))
|
||||
_Exit(60);
|
||||
if (pthread_mutex_unlock(&lock))
|
||||
_Exit(61);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = hand;
|
||||
sa.sa_flags = SA_NODEFER;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
if (sigaction(SIGUSR1, &sa, 0))
|
||||
_Exit(1);
|
||||
|
||||
pthread_mutexattr_t attr;
|
||||
if (pthread_mutexattr_init(&attr))
|
||||
_Exit(2);
|
||||
if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE))
|
||||
_Exit(3);
|
||||
if (pthread_mutex_init(&lock, &attr))
|
||||
_Exit(4);
|
||||
if (pthread_mutexattr_destroy(&attr))
|
||||
_Exit(5);
|
||||
|
||||
pthread_t th;
|
||||
pthread_attr_t tattr;
|
||||
if (pthread_attr_init(&tattr))
|
||||
_Exit(6);
|
||||
if (pthread_attr_setstacksize(&tattr, 8 * 1024 * 1024))
|
||||
_Exit(7);
|
||||
if (pthread_attr_setguardsize(&tattr, 64 * 1024))
|
||||
_Exit(8);
|
||||
if (pthread_create(&th, &tattr, work, 0))
|
||||
_Exit(9);
|
||||
if (pthread_attr_destroy(&tattr))
|
||||
_Exit(10);
|
||||
for (;;)
|
||||
if (ready)
|
||||
break;
|
||||
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
if (pthread_kill(th, SIGUSR1))
|
||||
_Exit(11);
|
||||
if (pthread_kill(th, SIGUSR1))
|
||||
_Exit(12);
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
done = true;
|
||||
if (pthread_join(th, 0))
|
||||
_Exit(13);
|
||||
if (pthread_mutex_destroy(&lock))
|
||||
_Exit(14);
|
||||
}
|
Loading…
Reference in a new issue