OLD | NEW |
(Empty) | |
| 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 "syscall.h" |
| 8 |
| 9 struct args { |
| 10 pthread_barrier_t barrier; |
| 11 int sock; |
| 12 const struct sigevent *sev; |
| 13 }; |
| 14 |
| 15 static void *start(void *p) |
| 16 { |
| 17 struct args *args = p; |
| 18 char buf[32]; |
| 19 ssize_t n; |
| 20 int s = args->sock; |
| 21 void (*func)(union sigval) = args->sev->sigev_notify_function; |
| 22 union sigval val = args->sev->sigev_value; |
| 23 |
| 24 pthread_barrier_wait(&args->barrier); |
| 25 n = recv(s, buf, sizeof(buf), MSG_NOSIGNAL|MSG_WAITALL); |
| 26 close(s); |
| 27 if (n==sizeof buf && buf[sizeof buf - 1] == 1) |
| 28 func(val); |
| 29 return 0; |
| 30 } |
| 31 |
| 32 int mq_notify(mqd_t mqd, const struct sigevent *sev) |
| 33 { |
| 34 struct args args = { .sev = sev }; |
| 35 pthread_attr_t attr; |
| 36 pthread_t td; |
| 37 int s; |
| 38 struct sigevent sev2; |
| 39 static const char zeros[32]; |
| 40 |
| 41 if (!sev || sev->sigev_notify != SIGEV_THREAD) |
| 42 return syscall(SYS_mq_notify, mqd, sev); |
| 43 |
| 44 s = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, 0); |
| 45 if (s < 0) return -1; |
| 46 args.sock = s; |
| 47 |
| 48 if (sev->sigev_notify_attributes) attr = *sev->sigev_notify_attributes; |
| 49 else pthread_attr_init(&attr); |
| 50 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
| 51 pthread_barrier_init(&args.barrier, 0, 2); |
| 52 |
| 53 if (pthread_create(&td, &attr, start, &args)) { |
| 54 __syscall(SYS_close, s); |
| 55 errno = EAGAIN; |
| 56 return -1; |
| 57 } |
| 58 |
| 59 pthread_barrier_wait(&args.barrier); |
| 60 pthread_barrier_destroy(&args.barrier); |
| 61 |
| 62 sev2.sigev_notify = SIGEV_THREAD; |
| 63 sev2.sigev_signo = s; |
| 64 sev2.sigev_value.sival_ptr = (void *)&zeros; |
| 65 |
| 66 if (syscall(SYS_mq_notify, mqd, &sev2) < 0) { |
| 67 pthread_cancel(td); |
| 68 __syscall(SYS_close, s); |
| 69 return -1; |
| 70 } |
| 71 |
| 72 return 0; |
| 73 } |
OLD | NEW |