From b26db0813ca2aab8882535caa9d0a6c8671e9bbc Mon Sep 17 00:00:00 2001
From: "Peter S. Mazinger" <ps.m@gmx.net>
Date: Thu, 21 Apr 2011 21:19:39 +0200
Subject: [PATCH 1/6] 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>
(cherry picked from commit 9f68f0cbf8c8eea6a7f9e195e4617bbaa808d7c6)

Conflicts:
	Makefile.in
---
 Makefile.in      |   1 +
 include/cancel.h | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 102 insertions(+)
 create mode 100644 include/cancel.h

diff --git a/Makefile.in b/Makefile.in
index 9ba590d..e81926d 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -210,6 +210,7 @@ $(top_builddir)extra/scripts/unifdef: $(top_srcdir)extra/scripts/unifdef.c
 # a "y" here means the feature is enabled and so we should *not* rm it.
 # if the option expands to nothing though, we can punt the headers.
 HEADERS_RM- := \
+	cancel.h \
 	dl-osinfo.h \
 	hp-timing.h \
 	_lfs_64.h \
diff --git a/include/cancel.h b/include/cancel.h
new file mode 100644
index 0000000..ac6f6b6
--- /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
-- 
1.7.11.1

