1 /*
2  * Copyright (C) 2000-2011 Erik Andersen <andersen@uclibc.org>
3  *
4  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
5  */
6 
7 #ifndef _CANCEL_H
8 #define _CANCEL_H
9 
10 /*
11  * Usage of this header:
12  * 1. define a static or hidden function __NC(NAME) - expands to __NAME_nocancel
13  * 2. if it is hidden, add the prototype to the appropiate header where NAME has
14  * it's prototype (guarded by _LIBC)
15  * 3. add a CANCELLABLE_SYSCALL(...) line at the end, this will create the function
16  * NAME (as weak) with enabled cancellation for NPTL, for
17  * LT it will also create a strong_alias to __libc_NAME to be used in libpthread
18  * 4. if you need libc_hidden_(weak|def) line, use instead lt_libc_hidden, this will
19  * take care of the correct type, weak or strong depending on the THREADS type
20  * 5. If the implementation can't be done using CANCELLABLE_SYSCALL (like for fcntl)
21  * you need to manually add lt_strong_alias() line too, to optionally create the
22  * __libc_NAME alias
23  * 6. if functions are needed to implement __NC(NAME), that themselves are cancellable,
24  * decide how the cancellation should be solved, two variants are possible:
25  *  a. use the other function as __NC(FUNC), this way you access the non-cancellable
26  *  variant and provide by CANCELLABLE_SYSCALL(...) the dedicated cancellation for NAME.
27  *  be aware, that for this case __NC(FUNC) has to be hidden (not static)
28  *  b. use the other function with it's name (FUNC) and add LIBC_CANCEL_HANDLED(); at
29  *  the end of file with a comment telling us which function took care of the cancellation
30  * Note: LIBC_CANCEL_HANDLED() is noop on uClibc, glibc uses it only for tests, we use
31  * it only for "documentation".
32  *
33  * For now the use of this file is limited to libc, will expand later to support libpthread
34  * and librt as well.
35  */
36 
37 #include <features.h>
38 
39 #define __NC(name) _NC(name)
40 #define _NC(name) __##name##_nocancel
41 
42 #define __NC_OLD(name) _NC_OLD(name)
43 #define _NC_OLD(name) __libc_##name
44 
45 #define __NC_PROTO(name) extern __typeof(name) __NC(name) attribute_hidden;
46 #define __NC_OLD_PROTO(name) extern __typeof(name) __NC_OLD(name);
47 
48 #if defined __UCLIBC_HAS_THREADS__ && !defined __UCLIBC_HAS_LINUXTHREADS__
49 # define __NEW_THREADS 1
50 #else
51 # define SINGLE_THREAD_P 1
52 #endif
53 
54 #ifdef __NEW_THREADS
55 # include <sysdep-cancel.h>
56 
57 # define CANCELLABLE_SYSCALL(res_type, name, param_list, params)	\
58 res_type weak_function name param_list					\
59 {									\
60 	int oldtype;							\
61 	res_type result;						\
62 	if (SINGLE_THREAD_P)						\
63 		return __NC(name) params;				\
64 	oldtype = LIBC_CANCEL_ASYNC();					\
65 	result = __NC(name) params;					\
66 	LIBC_CANCEL_RESET(oldtype);					\
67 	return result;							\
68 }
69 
70 # define lt_strong_alias(name)
71 # define lt_libc_hidden(name) libc_hidden_def(name)
72 
73 #elif defined __UCLIBC_HAS_LINUXTHREADS__
74 
75 # define CANCELLABLE_SYSCALL(res_type, name, param_list, params)	\
76 weak_alias(__NC(name),name)						\
77 lt_strong_alias(name)
78 
79 # define lt_strong_alias(name)						\
80 __NC_OLD_PROTO(name)							\
81 strong_alias(name,__NC_OLD(name))
82 # define lt_libc_hidden(name) libc_hidden_weak(name)
83 
84 #else
85 
86 # define CANCELLABLE_SYSCALL(res_type, name, param_list, params)	\
87 strong_alias(__NC(name),name)
88 
89 # define lt_strong_alias(name)
90 # define lt_libc_hidden(name) libc_hidden_def(name)
91 
92 #endif
93 
94 /* disable it, useless, glibc uses it only for tests */
95 # undef LIBC_CANCEL_HANDLED
96 # define LIBC_CANCEL_HANDLED()
97 
98 #endif
99