1/* Copyright (C) 2009 Free Software Foundation, Inc. 2 This file is part of the GNU C Library. 3 Contributed by Ulrich Drepper <drepper@redhat.com>, 2009. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <http://www.gnu.org/licenses/>. */ 18 19#include <sysdep.h> 20#include <tcb-offsets.h> 21#include <bits/kernel-features.h> 22#include "lowlevellock.h" 23 24#ifdef IS_IN_libpthread 25# ifdef SHARED 26# define __pthread_unwind __GI___pthread_unwind 27# endif 28#else 29# ifndef SHARED 30 .weak __pthread_unwind 31# endif 32#endif 33 34 35#ifdef __ASSUME_PRIVATE_FUTEX 36# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ 37 movl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg 38#else 39# if FUTEX_WAIT == 0 40# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ 41 movl %fs:PRIVATE_FUTEX, reg 42# else 43# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ 44 movl %fs:PRIVATE_FUTEX, reg ; \ 45 orl $FUTEX_WAIT, reg 46# endif 47#endif 48 49/* It is crucial that the functions in this file don't modify registers 50 other than %rax and %r11. The syscall wrapper code depends on this 51 because it doesn't explicitly save the other registers which hold 52 relevant values. */ 53 .text 54 55 .hidden __pthread_enable_asynccancel 56ENTRY(__pthread_enable_asynccancel) 57 movl %fs:CANCELHANDLING, %eax 582: movl %eax, %r11d 59 orl $TCB_CANCELTYPE_BITMASK, %r11d 60 cmpl %eax, %r11d 61 je 1f 62 63 lock 64 cmpxchgl %r11d, %fs:CANCELHANDLING 65 jnz 2b 66 67 andl $(TCB_CANCELSTATE_BITMASK|TCB_CANCELTYPE_BITMASK|TCB_CANCELED_BITMASK|TCB_EXITING_BITMASK|TCB_CANCEL_RESTMASK|TCB_TERMINATED_BITMASK), %r11d 68 cmpl $(TCB_CANCELTYPE_BITMASK|TCB_CANCELED_BITMASK), %r11d 69 je 3f 70 711: ret 72 733: movq $TCB_PTHREAD_CANCELED, %fs:RESULT 74 lock 75 orl $TCB_EXITING_BITMASK, %fs:CANCELHANDLING 76 movq %fs:CLEANUP_JMP_BUF, %rdi 77#ifdef SHARED 78 call __pthread_unwind@PLT 79#else 80 call __pthread_unwind 81#endif 82 hlt 83END(__pthread_enable_asynccancel) 84 85 86 .hidden __pthread_disable_asynccancel 87ENTRY(__pthread_disable_asynccancel) 88 testl $TCB_CANCELTYPE_BITMASK, %edi 89 jnz 1f 90 91 movl %fs:CANCELHANDLING, %eax 922: movl %eax, %r11d 93 andl $~TCB_CANCELTYPE_BITMASK, %r11d 94 lock 95 cmpxchgl %r11d, %fs:CANCELHANDLING 96 jnz 2b 97 98 movl %r11d, %eax 993: andl $(TCB_CANCELING_BITMASK|TCB_CANCELED_BITMASK), %eax 100 cmpl $TCB_CANCELING_BITMASK, %eax 101 je 4f 1021: ret 103 104 /* Performance doesn't matter in this loop. We will 105 delay until the thread is canceled. And we will unlikely 106 enter the loop twice. */ 1074: movq %fs:0, %rdi 108 movl $__NR_futex, %eax 109 xorq %r10, %r10 110 addq $CANCELHANDLING, %rdi 111 LOAD_PRIVATE_FUTEX_WAIT (%esi) 112 syscall 113 movl %fs:CANCELHANDLING, %eax 114 jmp 3b 115END(__pthread_disable_asynccancel) 116