iconv: add euro symbol to GBK as single byte 0x80
[musl.git] / src / mq / mq_notify.c
blob0e1e6c7ab73bb5214a4bcee52edbeae1724cf58d
1 #include <mqueue.h>
2 #include <pthread.h>
3 #include <errno.h>
4 #include <sys/socket.h>
5 #include <signal.h>
6 #include <unistd.h>
7 #include <semaphore.h>
8 #include "syscall.h"
10 struct args {
11 sem_t sem;
12 int sock;
13 mqd_t mqd;
14 int err;
15 const struct sigevent *sev;
18 static void *start(void *p)
20 struct args *args = p;
21 char buf[32];
22 ssize_t n;
23 int s = args->sock;
24 void (*func)(union sigval) = args->sev->sigev_notify_function;
25 union sigval val = args->sev->sigev_value;
26 struct sigevent sev2;
27 static const char zeros[32];
28 int err;
30 sev2.sigev_notify = SIGEV_THREAD;
31 sev2.sigev_signo = s;
32 sev2.sigev_value.sival_ptr = (void *)&zeros;
34 args->err = err = -__syscall(SYS_mq_notify, args->mqd, &sev2);
35 sem_post(&args->sem);
36 if (err) return 0;
38 pthread_detach(pthread_self());
39 n = recv(s, buf, sizeof(buf), MSG_NOSIGNAL|MSG_WAITALL);
40 close(s);
41 if (n==sizeof buf && buf[sizeof buf - 1] == 1)
42 func(val);
43 return 0;
46 int mq_notify(mqd_t mqd, const struct sigevent *sev)
48 struct args args = { .sev = sev };
49 pthread_attr_t attr;
50 pthread_t td;
51 int s;
52 int cs;
53 sigset_t allmask, origmask;
55 if (!sev || sev->sigev_notify != SIGEV_THREAD)
56 return syscall(SYS_mq_notify, mqd, sev);
58 s = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, 0);
59 if (s < 0) return -1;
60 args.sock = s;
61 args.mqd = mqd;
63 if (sev->sigev_notify_attributes) attr = *sev->sigev_notify_attributes;
64 else pthread_attr_init(&attr);
65 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
66 sem_init(&args.sem, 0, 0);
68 sigfillset(&allmask);
69 pthread_sigmask(SIG_BLOCK, &allmask, &origmask);
70 if (pthread_create(&td, &attr, start, &args)) {
71 __syscall(SYS_close, s);
72 pthread_sigmask(SIG_SETMASK, &origmask, 0);
73 errno = EAGAIN;
74 return -1;
76 pthread_sigmask(SIG_SETMASK, &origmask, 0);
78 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
79 sem_wait(&args.sem);
80 sem_destroy(&args.sem);
82 if (args.err) {
83 __syscall(SYS_close, s);
84 pthread_join(td, 0);
85 pthread_setcancelstate(cs, 0);
86 errno = args.err;
87 return -1;
90 pthread_setcancelstate(cs, 0);
91 return 0;