summaryrefslogtreecommitdiff
path: root/libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/sysdep-cancel.h
diff options
context:
space:
mode:
Diffstat (limited to 'libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/sysdep-cancel.h')
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/sysdep-cancel.h139
1 files changed, 139 insertions, 0 deletions
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/sysdep-cancel.h
new file mode 100644
index 000000000..2af79cab5
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/microblaze/sysdep-cancel.h
@@ -0,0 +1,139 @@
+/* Copyright (C) 2014-2016 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <tls.h>
+#ifndef __ASSEMBLER__
+# include <pthreadP.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+#ifdef __ASSEMBLER__
+
+#undef ret
+#define ret
+
+# if !IS_IN_librt || !defined(PIC)
+# define AC_STACK_SIZE 16 /* space for r15, async_cancel arg and 2 temp words */
+# define AC_SET_GOT /* empty */
+# define AC_RESTORE_GOT /* empty */
+# else
+# define AC_STACK_SIZE 20 /* extra 4 bytes for r20 */
+# define AC_SET_GOT \
+ swi r20, r1, AC_STACK_SIZE-4; \
+ mfs r20, rpc; \
+ addik r20, r20, _GLOBAL_OFFSET_TABLE_+8;
+# define AC_RESTORE_GOT \
+ lwi r20, r1, AC_STACK_SIZE-4;
+# endif
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args) \
+ .text; \
+ ENTRY (name) \
+ SINGLE_THREAD_P(r12); \
+ bnei r12, L(pseudo_cancel); \
+ .globl __##syscall_name##_nocancel; \
+ .type __##syscall_name##_nocancel,@function; \
+__##syscall_name##_nocancel: \
+ DO_CALL (syscall_name, args); \
+ addik r4, r0, -4095; \
+ cmpu r4, r4, r3; \
+ rsubk r3,r3,r0; \
+ rtsd r15,8; \
+ addik r3,r0,-1; \
+ rtsd r15, 8; \
+ nop; \
+ .size __##syscall_name##_nocancel, .-__##syscall_name##_nocancel; \
+L(pseudo_cancel): \
+ addik r1, r1, -AC_STACK_SIZE; \
+ swi r15, r1, 0; \
+ AC_SET_GOT \
+ DOCARGS_##args \
+ CENABLE; \
+ swi r3, r1, 8; \
+ UNDOCARGS_##args \
+ DO_CALL (syscall_name, args); \
+ swi r3, r1, 12; \
+ lwi r5, r1, 8; \
+ CDISABLE; \
+ lwi r3, r1, 12; \
+ lwi r15, r1, 0; \
+ AC_RESTORE_GOT \
+ addik r1, r1, AC_STACK_SIZE; \
+ addik r4, r0, -4095; \
+ cmpu r4, r4, r3; \
+ rsubk r3,r3,r0; \
+ rtsd r15,8; \
+ addik r3,r0,-1; \
+ rtsd r15, 8; \
+ nop;
+
+/*
+ * Macros to save/restore syscall arguments across CENABLE
+ * The arguments are saved into the caller's stack (original r1 + 4)
+ */
+
+# define DOCARGS_0
+# define DOCARGS_1 swi r5, r1, AC_STACK_SIZE + 4;
+# define DOCARGS_2 swi r6, r1, AC_STACK_SIZE + 8; DOCARGS_1
+# define DOCARGS_3 swi r7, r1, AC_STACK_SIZE + 12; DOCARGS_2
+# define DOCARGS_4 swi r8, r1, AC_STACK_SIZE + 16; DOCARGS_3
+# define DOCARGS_5 swi r9, r1, AC_STACK_SIZE + 20; DOCARGS_4
+# define DOCARGS_6 swi r10, r1, AC_STACK_SIZE + 24; DOCARGS_5
+
+# define UNDOCARGS_0
+# define UNDOCARGS_1 lwi r5, r1, AC_STACK_SIZE + 4;
+# define UNDOCARGS_2 UNDOCARGS_1 lwi r6, r1, AC_STACK_SIZE + 8;
+# define UNDOCARGS_3 UNDOCARGS_2 lwi r7, r1, AC_STACK_SIZE + 12;
+# define UNDOCARGS_4 UNDOCARGS_3 lwi r8, r1, AC_STACK_SIZE + 16;
+# define UNDOCARGS_5 UNDOCARGS_4 lwi r9, r1, AC_STACK_SIZE + 20;
+# define UNDOCARGS_6 UNDOCARGS_5 lwi r10, r1, AC_STACK_SIZE + 24;
+
+# ifdef PIC
+# define PSEUDO_JMP(sym) brlid r15, sym##@PLTPC; addk r0, r0, r0
+# else
+# define PSEUDO_JMP(sym) brlid r15, sym; addk r0, r0, r0
+# endif
+
+# if defined IS_IN_libpthread
+# define CENABLE PSEUDO_JMP (__pthread_enable_asynccancel)
+# define CDISABLE PSEUDO_JMP (__pthread_disable_asynccancel)
+# define __local_multiple_threads __pthread_multiple_threads
+# elif !defined NOT_IN_libc
+# define CENABLE PSEUDO_JMP (__libc_enable_asynccancel)
+# define CDISABLE PSEUDO_JMP (__libc_disable_asynccancel)
+# define __local_multiple_threads __libc_multiple_threads
+# elif defined IS_IN_librt
+# define CENABLE PSEUDO_JMP (__librt_enable_asynccancel)
+# define CDISABLE PSEUDO_JMP (__librt_disable_asynccancel)
+# else
+# error Unsupported library
+# endif
+
+#define SINGLE_THREAD_P(reg) \
+ lwi reg, r0, MULTIPLE_THREADS_OFFSET(reg)
+
+#else /* !__ASSEMBLER__ */
+# define SINGLE_THREAD_P \
+ __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+ header.multiple_threads) == 0, 1)
+
+#endif /* __ASSEMBLER__ */
+
+#endif