• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"
9 #ifndef __LITEOS__
10 #include "pthread_impl.h"
11 #endif
12 
13 #ifndef __LITEOS_A__
14 struct args {
15 	sem_t sem;
16 	int sock;
17 	mqd_t mqd;
18 	int err;
19 	const struct sigevent *sev;
20 };
21 
start(void * p)22 static void *start(void *p)
23 {
24 	struct args *args = p;
25 	char buf[32];
26 	ssize_t n;
27 	int s = args->sock;
28 	void (*func)(union sigval) = args->sev->sigev_notify_function;
29 	union sigval val = args->sev->sigev_value;
30 	struct sigevent sev2;
31 	static const char zeros[32];
32 	int err;
33 
34 	sev2.sigev_notify = SIGEV_THREAD;
35 	sev2.sigev_signo = s;
36 	sev2.sigev_value.sival_ptr = (void *)&zeros;
37 
38 	args->err = err = -__syscall(SYS_mq_notify, args->mqd, &sev2);
39 	sem_post(&args->sem);
40 	if (err) return 0;
41 
42 	pthread_detach(pthread_self());
43 	n = recv(s, buf, sizeof(buf), MSG_NOSIGNAL|MSG_WAITALL);
44 	close(s);
45 	if (n==sizeof buf && buf[sizeof buf - 1] == 1)
46 		func(val);
47 	return 0;
48 }
49 #endif
50 
mq_notify(mqd_t mqd,const struct sigevent * sev)51 int mq_notify(mqd_t mqd, const struct sigevent *sev)
52 {
53 #ifdef __LITEOS_A__
54 	if (!sev || sev->sigev_notify != SIGEV_THREAD) {
55 		return syscall(SYS_mq_notify, mqd, sev);
56 	}
57 
58 	errno = ENOTSUP;
59 	return -1;
60 #else
61 	struct args args = { .sev = sev };
62 	pthread_attr_t attr;
63 	pthread_t td;
64 	int s;
65 	int cs;
66 	sigset_t allmask, origmask;
67 
68 	if (!sev || sev->sigev_notify != SIGEV_THREAD)
69 		return syscall(SYS_mq_notify, mqd, sev);
70 
71 	s = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, 0);
72 	if (s < 0) return -1;
73 	args.sock = s;
74 	args.mqd = mqd;
75 
76 	if (sev->sigev_notify_attributes) attr = *sev->sigev_notify_attributes;
77 	else pthread_attr_init(&attr);
78 	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
79 	sem_init(&args.sem, 0, 0);
80 
81 	sigfillset(&allmask);
82 	pthread_sigmask(SIG_BLOCK, &allmask, &origmask);
83 	if (pthread_create(&td, &attr, start, &args)) {
84 		__syscall(SYS_close, s);
85 		pthread_sigmask(SIG_SETMASK, &origmask, 0);
86 		errno = EAGAIN;
87 		return -1;
88 	}
89 	pthread_sigmask(SIG_SETMASK, &origmask, 0);
90 
91 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
92 	sem_wait(&args.sem);
93 	sem_destroy(&args.sem);
94 
95 	if (args.err) {
96 #ifdef FEATURE_PTHREAD_CANCEL
97 #else
98 		__syscall(SYS_tkill, td->tid, SIGCANCEL);
99 #endif
100 		__syscall(SYS_close, s);
101 		pthread_join(td, 0);
102 		pthread_setcancelstate(cs, 0);
103 		errno = args.err;
104 		return -1;
105 	}
106 
107 	pthread_setcancelstate(cs, 0);
108 	return 0;
109 #endif
110 }
111