diff options
author | Peter S. Mazinger <ps.m@gmx.net> | 2011-04-21 21:19:39 +0200 |
---|---|---|
committer | Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> | 2012-06-15 14:00:40 +0200 |
commit | 9f68f0cbf8c8eea6a7f9e195e4617bbaa808d7c6 (patch) | |
tree | 9ae1ee654e34413a41431b1fc032e42369c25b0a | |
parent | a92060fe161073a41a3b73e8533d65125f84e3a8 (diff) |
cancel.h: add generic file to ease cancellation support
Signed-off-by: Peter S. Mazinger <ps.m@gmx.net>
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
-rw-r--r-- | Makefile.in | 1 | ||||
-rw-r--r-- | include/cancel.h | 101 |
2 files changed, 102 insertions, 0 deletions
diff --git a/Makefile.in b/Makefile.in index 9de340011..0be507a16 100644 --- a/Makefile.in +++ b/Makefile.in @@ -217,6 +217,7 @@ $(top_builddir)extra/scripts/unifdef: $(top_srcdir)extra/scripts/unifdef.c # if the option expands to nothing though, we can punt the headers. HEADERS_RM- := \ internal \ + cancel.h \ dl-osinfo.h \ jmpbuf-offsets.h \ jmpbuf-unwind.h \ diff --git a/include/cancel.h b/include/cancel.h new file mode 100644 index 000000000..ac6f6b64d --- /dev/null +++ b/include/cancel.h @@ -0,0 +1,101 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2011 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef _CANCEL_H +#define _CANCEL_H + +/* + * Usage of this header: + * 1. define a static or hidden function __NC(NAME) - expands to __NAME_nocancel + * 2. if it is hidden, add the prototype to the appropiate header where NAME has + * it's prototype (guarded by _LIBC) + * 3. add a CANCELLABLE_SYSCALL(...) line at the end, this will create the function + * NAME (as weak) with enabled cancellation for NPTL (and later for new LT), for + * LT_OLD it will also create a strong_alias to __libc_NAME to be used in libpthread + * 4. if you need libc_hidden_(weak|def) line, use instead lt_libc_hidden, this will + * take care of the correct type, weak or strong depending on the THREADS type + * 5. If the implementation can't be done using CANCELLABLE_SYSCALL (like for fcntl) + * you need to manually add lt_strong_alias() line too, to optionally create the + * __libc_NAME alias + * 6. if functions are needed to implement __NC(NAME), that themselves are cancellable, + * decide how the cancellation should be solved, two variants are possible: + * a. use the other function as __NC(FUNC), this way you access the non-cancellable + * variant and provide by CANCELLABLE_SYSCALL(...) the dedicated cancellation for NAME. + * be aware, that for this case __NC(FUNC) has to be hidden (not static) + * b. use the other function with it's name (FUNC) and add LIBC_CANCEL_HANDLED(); at + * the end of file with a comment telling us which function took care of the cancellation + * Note: LIBC_CANCEL_HANDLED() is noop on uClibc, glibc uses it only for tests, we use + * it only for "documentation". + * + * For now the use of this file is limited to libc, will expand later to support libpthread + * and librt as well. + */ + +#include <features.h> + +#ifndef NOT_IN_libc + +#define __NC(name) _NC(name) +#define _NC(name) __##name##_nocancel + +#define __NC_OLD(name) _NC_OLD(name) +#define _NC_OLD(name) __libc_##name + +#define __NC_PROTO(name) extern __typeof(name) __NC(name) attribute_hidden; +#define __NC_OLD_PROTO(name) extern __typeof(name) __NC_OLD(name); + +#if defined __UCLIBC_HAS_THREADS__ && !defined __LINUXTHREADS_OLD__ +# define __NEW_THREADS 1 +#else +# define SINGLE_THREAD_P 1 +#endif + +#ifdef __NEW_THREADS +# include <sysdep-cancel.h> + +# define CANCELLABLE_SYSCALL(res_type, name, param_list, params) \ +res_type weak_function name param_list \ +{ \ + if (SINGLE_THREAD_P) \ + return __NC(name) params; \ + int oldtype = LIBC_CANCEL_ASYNC(); \ + res_type result = __NC(name) params; \ + LIBC_CANCEL_RESET(oldtype); \ + return result; \ +} + +# define lt_strong_alias(name) +# define lt_libc_hidden(name) libc_hidden_def(name) + +#elif defined __LINUXTHREADS_OLD__ + +# define CANCELLABLE_SYSCALL(res_type, name, param_list, params) \ +weak_alias(__NC(name),name) \ +lt_strong_alias(name) + +# define lt_strong_alias(name) \ +__NC_OLD_PROTO(name) \ +strong_alias(name,__NC_OLD(name)) +# define lt_libc_hidden(name) libc_hidden_weak(name) + +#else + +# define CANCELLABLE_SYSCALL(res_type, name, param_list, params) \ +strong_alias(__NC(name),name) + +# define lt_strong_alias(name) +# define lt_libc_hidden(name) libc_hidden_def(name) + +#endif + +/* disable it, useless, glibc uses it only for tests */ +# undef LIBC_CANCEL_HANDLED +# define LIBC_CANCEL_HANDLED() + +#endif /* NOT_IN_libc */ + +#endif |