fix pointer type mismatch and misplacement of const
[musl] / src / thread / synccall.c
1 #include "pthread_impl.h"
2 #include <semaphore.h>
3
4 static struct chain {
5         struct chain *next;
6         sem_t sem, sem2;
7 } *head, *cur;
8
9 static void (*callback)(void *), *context;
10 static int chainlen;
11 static sem_t chainlock, chaindone;
12
13 static void handler(int sig, siginfo_t *si, void *ctx)
14 {
15         struct chain ch;
16         pthread_t self = __pthread_self();
17         int old_errno = errno;
18
19         if (chainlen == libc.threads_minus_1) return;
20
21         sigqueue(self->pid, SIGSYNCCALL, (union sigval){0});
22
23         sem_init(&ch.sem, 0, 0);
24         sem_init(&ch.sem2, 0, 0);
25
26         while (sem_wait(&chainlock));
27         ch.next = head;
28         head = &ch;
29         if (++chainlen == libc.threads_minus_1) sem_post(&chaindone);
30         sem_post(&chainlock);
31
32         while (sem_wait(&ch.sem));
33         callback(context);
34         sem_post(&ch.sem2);
35         while (sem_wait(&ch.sem));
36
37         errno = old_errno;
38 }
39
40 void __synccall(void (*func)(void *), void *ctx)
41 {
42         pthread_t self;
43         struct sigaction sa;
44         struct chain *next;
45         sigset_t oldmask;
46
47         if (!libc.threads_minus_1) {
48                 func(ctx);
49                 return;
50         }
51
52         __inhibit_ptc();
53
54         __block_all_sigs(&oldmask);
55
56         sem_init(&chaindone, 0, 0);
57         sem_init(&chainlock, 0, 1);
58         chainlen = 0;
59         head = 0;
60         callback = func;
61         context = ctx;
62
63         sa.sa_flags = SA_SIGINFO | SA_RESTART;
64         sa.sa_sigaction = handler;
65         sigfillset(&sa.sa_mask);
66         __libc_sigaction(SIGSYNCCALL, &sa, 0);
67
68         self = __pthread_self();
69         sigqueue(self->pid, SIGSYNCCALL, (union sigval){0});
70         while (sem_wait(&chaindone));
71
72         sa.sa_flags = 0;
73         sa.sa_handler = SIG_IGN;
74         __libc_sigaction(SIGSYNCCALL, &sa, 0);
75
76         for (cur=head; cur; cur=cur->next) {
77                 sem_post(&cur->sem);
78                 while (sem_wait(&cur->sem2));
79         }
80         func(ctx);
81
82         for (cur=head; cur; cur=next) {
83                 next = cur->next;
84                 sem_post(&cur->sem);
85         }
86
87         __restore_sigs(&oldmask);
88
89         __release_ptc();
90 }