1 | /* Internal definitions for pthreads library. |
2 | Copyright (C) 2016-2024 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
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 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #ifndef _PT_MUTEX_H |
20 | #define _PT_MUTEX_H 1 |
21 | |
22 | /* Special ID used to signal an unrecoverable robust mutex. */ |
23 | #define NOTRECOVERABLE_ID (1U << 31) |
24 | |
25 | /* Common path for robust mutexes. Assumes the variable 'ret' |
26 | * is bound in the function this is called from. */ |
27 | #define ROBUST_LOCK(self, mtxp, cb, ...) \ |
28 | if (mtxp->__owner_id == NOTRECOVERABLE_ID) \ |
29 | return ENOTRECOVERABLE; \ |
30 | else if (mtxp->__owner_id == self->thread \ |
31 | && __getpid () == (int)(mtxp->__lock & LLL_OWNER_MASK)) \ |
32 | { \ |
33 | if (mtxp->__type == PT_MTX_RECURSIVE) \ |
34 | { \ |
35 | if (__glibc_unlikely (mtxp->__cnt + 1 == 0)) \ |
36 | return EAGAIN; \ |
37 | \ |
38 | ++mtxp->__cnt; \ |
39 | return 0; \ |
40 | } \ |
41 | else if (mtxp->__type == PT_MTX_ERRORCHECK) \ |
42 | return EDEADLK; \ |
43 | } \ |
44 | \ |
45 | ret = cb (mtxp->__lock, ##__VA_ARGS__); \ |
46 | if (ret == 0 || ret == EOWNERDEAD) \ |
47 | { \ |
48 | if (mtxp->__owner_id == ENOTRECOVERABLE) \ |
49 | ret = ENOTRECOVERABLE; \ |
50 | else \ |
51 | { \ |
52 | mtxp->__owner_id = self->thread; \ |
53 | mtxp->__cnt = 1; \ |
54 | if (ret == EOWNERDEAD) \ |
55 | { \ |
56 | mtxp->__lock = mtxp->__lock | LLL_DEAD_OWNER; \ |
57 | atomic_write_barrier (); \ |
58 | } \ |
59 | } \ |
60 | } \ |
61 | (void)0 |
62 | |
63 | /* Check that a thread owns the mutex. For non-robust, task-shared |
64 | * objects, we have to check the thread *and* process-id. */ |
65 | #define mtx_owned_p(mtx, pt, flags) \ |
66 | ((mtx)->__owner_id == (pt)->thread \ |
67 | && (((flags) & GSYNC_SHARED) == 0 \ |
68 | || (mtx)->__shpid == __getpid ())) |
69 | |
70 | /* Record a thread as the owner of the mutex. */ |
71 | #define mtx_set_owner(mtx, pt, flags) \ |
72 | (void) \ |
73 | ({ \ |
74 | (mtx)->__owner_id = (pt)->thread; \ |
75 | if ((flags) & GSYNC_SHARED) \ |
76 | (mtx)->__shpid = __getpid (); \ |
77 | }) |
78 | |
79 | /* Redefined mutex types. The +1 is for binary compatibility. */ |
80 | #define PT_MTX_NORMAL __PTHREAD_MUTEX_TIMED |
81 | #define PT_MTX_RECURSIVE (__PTHREAD_MUTEX_RECURSIVE + 1) |
82 | #define PT_MTX_ERRORCHECK (__PTHREAD_MUTEX_ERRORCHECK + 1) |
83 | |
84 | /* Mutex type, including robustness. */ |
85 | #define MTX_TYPE(mtxp) \ |
86 | ((mtxp)->__type | ((mtxp)->__flags & PTHREAD_MUTEX_ROBUST)) |
87 | |
88 | extern int __getpid (void) __attribute__ ((const)); |
89 | |
90 | #endif /* pt-mutex.h */ |
91 | |