NPTL/arc: notify kernel of the TP value
[uClibc.git] / test / pthread / cancellation-points.c
blob5453060f7f2c16940ffa7953513c73d4358e1aae
1 /*
2 * Make sure functions marked as cancellation points actually are.
3 * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_09.html#tag_02_09_05
4 */
6 #ifndef _GNU_SOURCE
7 #define _GNU_SOURCE
8 #endif
10 #include <features.h>
11 #include <sys/ipc.h>
12 #include <sys/mman.h>
13 #include <sys/msg.h>
14 #include <sys/socket.h>
15 #include <sys/types.h>
16 #include <sys/wait.h>
17 #include <fcntl.h>
18 #include <mqueue.h>
19 #include <poll.h>
20 #include <pthread.h>
21 #include <semaphore.h>
22 #include <signal.h>
23 #include <stdbool.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <termios.h>
27 #include <time.h>
28 #include <unistd.h>
30 /* take care of optional things ... */
31 #define STUB(func, args) static void func args { sleep(0); }
32 #if defined(__UCLIBC_AIO__)
33 # include <aio.h>
34 #else
35 STUB(aio_suspend, (void *p, int n, const void *p2))
36 #endif
37 #if defined(__UCLIBC_STROPTS__)
38 # include <stropts.h>
39 #else
40 STUB(getmsg, (int f, void *p, void *p2, void *p3))
41 STUB(getpmsg, (int f, void *p, void *p2, void *p3, void *p4))
42 STUB(putmsg, (int f, void *p, void *p2, void *p3))
43 STUB(putpmsg, (int f, void *p, void *p2, void *p3, void *p4))
44 #endif
45 #if defined(__UCLIBC__)
46 STUB(clock_nanosleep, (int i, int f, const void *p, void *p2))
47 #endif
49 int cnt;
50 bool ready;
52 void cancel_timeout(int sig)
54 ready = false;
56 void cancel_thread_cleanup(void *arg)
58 ready = false;
61 /* some funcs need some help as they wont take NULL args ... */
62 const struct timespec zero_sec = { .tv_sec = 0, .tv_nsec = 0 };
64 sem_t sem;
65 void help_sem_setup(void)
67 if (sem_init(&sem, 0, 1) == -1) {
68 perror("sem_init() failed");
69 exit(-1);
73 pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
74 pthread_mutex_t mutex;
75 void help_pthread_setup(void)
77 pthread_mutex_init(&mutex, NULL);
78 pthread_mutex_lock(&mutex);
81 /* the pthread function that will call the cancellable function over and over */
82 #define _MAKE_CANCEL_THREAD_FUNC_EX(func, sysfunc, args, setup) \
83 void *cancel_thread_##func(void *arg) \
84 { \
85 if (pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL)) { \
86 perror("unable to set cancel type to deferred; something is seriously broken"); \
87 exit(-1); \
88 } \
89 pthread_cleanup_push(cancel_thread_cleanup, NULL); \
90 setup; \
91 ready = true; \
92 while (ready) \
93 sysfunc args; \
94 pthread_cleanup_pop(1); \
95 return NULL; \
97 #define MAKE_CANCEL_THREAD_FUNC_RE(func, sysfunc, args) _MAKE_CANCEL_THREAD_FUNC_EX(func, sysfunc, args, (void)0)
98 #define MAKE_CANCEL_THREAD_FUNC_EX(func, args, setup) _MAKE_CANCEL_THREAD_FUNC_EX(func, func, args, setup)
99 #define MAKE_CANCEL_THREAD_FUNC(func, args) _MAKE_CANCEL_THREAD_FUNC_EX(func, func, args, (void)0)
101 MAKE_CANCEL_THREAD_FUNC(accept, (-1, NULL, NULL))
102 MAKE_CANCEL_THREAD_FUNC(aio_suspend, (NULL, 0, &zero_sec))
103 MAKE_CANCEL_THREAD_FUNC(clock_nanosleep, (0, 0, NULL, NULL))
104 MAKE_CANCEL_THREAD_FUNC(close, (-1))
105 MAKE_CANCEL_THREAD_FUNC(connect, (-1, NULL, 0))
106 MAKE_CANCEL_THREAD_FUNC(creat, ("", 0))
107 MAKE_CANCEL_THREAD_FUNC(fcntl, (0, F_SETLKW, NULL))
108 MAKE_CANCEL_THREAD_FUNC(fdatasync, (-1))
109 MAKE_CANCEL_THREAD_FUNC(fsync, (0))
110 MAKE_CANCEL_THREAD_FUNC(getmsg, (-1, NULL, NULL, NULL))
111 MAKE_CANCEL_THREAD_FUNC(getpmsg, (-1, NULL, NULL, NULL, NULL))
112 MAKE_CANCEL_THREAD_FUNC(lockf, (-1, F_TEST, 0))
113 MAKE_CANCEL_THREAD_FUNC(mq_receive, (0, NULL, 0, NULL))
114 MAKE_CANCEL_THREAD_FUNC(mq_send, (0, NULL, 0, 0))
115 MAKE_CANCEL_THREAD_FUNC(mq_timedreceive, (0, NULL, 0, NULL, NULL))
116 MAKE_CANCEL_THREAD_FUNC(mq_timedsend, (0, NULL, 0, 0, NULL))
117 MAKE_CANCEL_THREAD_FUNC(msgrcv, (-1, NULL, 0, 0, 0))
118 MAKE_CANCEL_THREAD_FUNC(msgsnd, (-1, NULL, 0, 0))
119 MAKE_CANCEL_THREAD_FUNC(msync, (NULL, 0, 0))
120 MAKE_CANCEL_THREAD_FUNC(nanosleep, (NULL, NULL))
121 MAKE_CANCEL_THREAD_FUNC(open, ("", 0))
122 MAKE_CANCEL_THREAD_FUNC(pause, ())
123 MAKE_CANCEL_THREAD_FUNC(poll, (NULL, 0, 0))
124 MAKE_CANCEL_THREAD_FUNC(pread, (-1, NULL, 0, 0))
125 MAKE_CANCEL_THREAD_FUNC(pselect, (0, NULL, NULL, NULL, NULL, NULL))
126 MAKE_CANCEL_THREAD_FUNC_EX(pthread_cond_timedwait, (&cond, &mutex, &zero_sec), help_pthread_setup())
127 MAKE_CANCEL_THREAD_FUNC_EX(pthread_cond_wait, (&cond, &mutex), help_pthread_setup())
128 /*MAKE_CANCEL_THREAD_FUNC_EX(pthread_join, (0, NULL))*/
129 MAKE_CANCEL_THREAD_FUNC(pthread_testcancel, ())
130 MAKE_CANCEL_THREAD_FUNC(putmsg, (-1, NULL, NULL, 0))
131 MAKE_CANCEL_THREAD_FUNC(putpmsg, (-1, NULL, NULL, 0, 0))
132 MAKE_CANCEL_THREAD_FUNC(pwrite, (-1, NULL, 0, 0))
133 MAKE_CANCEL_THREAD_FUNC(read, (-1, NULL, 0))
134 MAKE_CANCEL_THREAD_FUNC(readv, (-1, NULL, 0))
135 MAKE_CANCEL_THREAD_FUNC(recv, (-1, NULL, 0, 0))
136 MAKE_CANCEL_THREAD_FUNC(recvfrom, (-1, NULL, 0, 0, NULL, NULL))
137 MAKE_CANCEL_THREAD_FUNC(recvmsg, (-1, NULL, 0))
138 MAKE_CANCEL_THREAD_FUNC(select, (0, NULL, NULL, NULL, NULL))
139 MAKE_CANCEL_THREAD_FUNC_EX(sem_timedwait, (&sem, &zero_sec), help_sem_setup())
140 MAKE_CANCEL_THREAD_FUNC_EX(sem_wait, (&sem), help_sem_setup())
141 MAKE_CANCEL_THREAD_FUNC(send, (-1, NULL, 0, 0))
142 MAKE_CANCEL_THREAD_FUNC(sendmsg, (-1, NULL, 0))
143 MAKE_CANCEL_THREAD_FUNC(sendto, (-1, NULL, 0, 0, NULL, 0))
144 #ifdef __UCLIBC_SUSV4_LEGACY__
145 MAKE_CANCEL_THREAD_FUNC(sigpause, (0))
146 #endif
147 MAKE_CANCEL_THREAD_FUNC(sigsuspend, (NULL))
148 MAKE_CANCEL_THREAD_FUNC(sigtimedwait, (NULL, NULL, NULL))
149 MAKE_CANCEL_THREAD_FUNC(sigwait, (NULL, NULL))
150 MAKE_CANCEL_THREAD_FUNC(sigwaitinfo, (NULL, NULL))
151 MAKE_CANCEL_THREAD_FUNC(sleep, (0))
152 MAKE_CANCEL_THREAD_FUNC(system, (""))
153 MAKE_CANCEL_THREAD_FUNC(tcdrain, (-1))
154 #ifdef __UCLIBC_SUSV3_LEGACY__
155 MAKE_CANCEL_THREAD_FUNC(usleep, (0))
156 #endif
157 MAKE_CANCEL_THREAD_FUNC(wait, (NULL))
158 MAKE_CANCEL_THREAD_FUNC(waitid, (0, 0, NULL, 0))
159 MAKE_CANCEL_THREAD_FUNC(waitpid, (-1, NULL, 0))
160 MAKE_CANCEL_THREAD_FUNC(write, (-1, NULL, 0))
161 MAKE_CANCEL_THREAD_FUNC(writev, (-1, NULL, 0))
163 /* test a few variations that should not cancel ... */
164 MAKE_CANCEL_THREAD_FUNC_RE(fcntl_another, fcntl, (0, F_GETFD))
166 /* main test that creates thread, cancels it, etc... */
167 int _test_func(const char *func_name, void *(*func)(void*), const int should_cancel)
169 int ret;
170 pthread_t cancel_thread_id;
172 ++cnt;
174 printf("testing %-30s ", func_name);
176 printf(".");
177 if (signal(SIGALRM, cancel_timeout) == SIG_ERR) {
178 perror("unable to bind SIGALRM");
179 exit(-1);
182 printf(".");
183 ready = false;
184 pthread_create(&cancel_thread_id, NULL, func, NULL);
186 printf(".");
187 while (!ready)
188 sched_yield();
190 printf(".");
191 if (pthread_cancel(cancel_thread_id)) {
192 perror("unable to cancel thread");
193 exit(-1);
196 printf(".");
197 alarm(5);
198 while (ready)
199 sched_yield();
201 printf(".");
202 ret = (!!!alarm(0) == should_cancel);
204 if (ret)
205 printf(" failed ;(\n");
206 else
207 printf(" OK!\n");
209 return ret;
211 #define TEST_FUNC(f) _test_func(#f, cancel_thread_##f, 1)
212 #define TEST_FUNC_RE(f) _test_func(#f, cancel_thread_##f, 0)
214 int main(int argc, char *argv[])
216 int ret = 0;
217 setbuf(stdout, NULL);
218 cnt = 0;
220 ret += TEST_FUNC(accept);
221 ret += TEST_FUNC(aio_suspend);
222 ret += TEST_FUNC(clock_nanosleep);
223 ret += TEST_FUNC(close);
224 ret += TEST_FUNC(connect);
225 ret += TEST_FUNC(creat);
226 ret += TEST_FUNC(fcntl);
227 ret += TEST_FUNC(fdatasync);
228 ret += TEST_FUNC(fsync);
229 ret += TEST_FUNC(getmsg);
230 ret += TEST_FUNC(getpmsg);
231 ret += TEST_FUNC(lockf);
232 ret += TEST_FUNC(mq_receive);
233 ret += TEST_FUNC(mq_send);
234 ret += TEST_FUNC(mq_timedreceive);
235 ret += TEST_FUNC(mq_timedsend);
236 ret += TEST_FUNC(msgrcv);
237 ret += TEST_FUNC(msgsnd);
238 ret += TEST_FUNC(msync);
239 ret += TEST_FUNC(nanosleep);
240 ret += TEST_FUNC(open);
241 ret += TEST_FUNC(pause);
242 ret += TEST_FUNC(poll);
243 ret += TEST_FUNC(pread);
244 ret += TEST_FUNC(pselect);
245 ret += TEST_FUNC(pthread_cond_timedwait);
246 ret += TEST_FUNC(pthread_cond_wait);
247 /*ret += TEST_FUNC(pthread_join);*/
248 ret += TEST_FUNC(pthread_testcancel);
249 ret += TEST_FUNC(putmsg);
250 ret += TEST_FUNC(putpmsg);
251 ret += TEST_FUNC(pwrite);
252 ret += TEST_FUNC(read);
253 ret += TEST_FUNC(readv);
254 ret += TEST_FUNC(recv);
255 ret += TEST_FUNC(recvfrom);
256 ret += TEST_FUNC(recvmsg);
257 ret += TEST_FUNC(select);
258 ret += TEST_FUNC(sem_timedwait);
259 ret += TEST_FUNC(sem_wait);
260 ret += TEST_FUNC(send);
261 ret += TEST_FUNC(sendmsg);
262 ret += TEST_FUNC(sendto);
263 ret += TEST_FUNC(sigpause);
264 ret += TEST_FUNC(sigsuspend);
265 ret += TEST_FUNC(sigtimedwait);
266 ret += TEST_FUNC(sigwait);
267 ret += TEST_FUNC(sigwaitinfo);
268 ret += TEST_FUNC(sleep);
269 ret += TEST_FUNC(system);
270 ret += TEST_FUNC(tcdrain);
271 #ifdef __UCLIBC_SUSV3_LEGACY__
272 ret += TEST_FUNC(usleep);
273 #endif
274 ret += TEST_FUNC(wait);
275 ret += TEST_FUNC(waitid);
276 ret += TEST_FUNC(waitpid);
277 ret += TEST_FUNC(write);
278 ret += TEST_FUNC(writev);
280 ret += TEST_FUNC_RE(fcntl_another);
282 if (ret)
283 printf("!!! %i / %i tests failed\n", ret, cnt);
285 return ret;