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