1 | /* pthread_mutex_unlock. Hurd version. |
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 | #include <pthread.h> |
20 | #include <stdlib.h> |
21 | #include <assert.h> |
22 | #include <pt-internal.h> |
23 | #include "pt-mutex.h" |
24 | #include <hurdlock.h> |
25 | |
26 | int |
27 | __pthread_mutex_unlock (pthread_mutex_t *mtxp) |
28 | { |
29 | struct __pthread *self; |
30 | int ret = 0, flags = mtxp->__flags & GSYNC_SHARED; |
31 | |
32 | switch (MTX_TYPE (mtxp)) |
33 | { |
34 | case PT_MTX_NORMAL: |
35 | lll_unlock (mtxp->__lock, flags); |
36 | break; |
37 | |
38 | case PT_MTX_RECURSIVE: |
39 | self = _pthread_self (); |
40 | if (!mtx_owned_p (mtxp, self, flags)) |
41 | ret = EPERM; |
42 | else if (--mtxp->__cnt == 0) |
43 | { |
44 | mtxp->__owner_id = mtxp->__shpid = 0; |
45 | lll_unlock (mtxp->__lock, flags); |
46 | } |
47 | |
48 | break; |
49 | |
50 | case PT_MTX_ERRORCHECK: |
51 | self = _pthread_self (); |
52 | if (!mtx_owned_p (mtxp, self, flags)) |
53 | ret = EPERM; |
54 | else |
55 | { |
56 | mtxp->__owner_id = mtxp->__shpid = 0; |
57 | lll_unlock (mtxp->__lock, flags); |
58 | } |
59 | |
60 | break; |
61 | |
62 | case PT_MTX_NORMAL | PTHREAD_MUTEX_ROBUST: |
63 | case PT_MTX_RECURSIVE | PTHREAD_MUTEX_ROBUST: |
64 | case PT_MTX_ERRORCHECK | PTHREAD_MUTEX_ROBUST: |
65 | self = _pthread_self (); |
66 | if (mtxp->__owner_id == NOTRECOVERABLE_ID) |
67 | ; /* Nothing to do. */ |
68 | else if (mtxp->__owner_id != self->thread |
69 | || (int) (mtxp->__lock & LLL_OWNER_MASK) != __getpid ()) |
70 | ret = EPERM; |
71 | else if (--mtxp->__cnt == 0) |
72 | { |
73 | /* Release the lock. If it's in an inconsistent |
74 | * state, mark it as irrecoverable. */ |
75 | mtxp->__owner_id = ((mtxp->__lock & LLL_DEAD_OWNER) |
76 | ? NOTRECOVERABLE_ID : 0); |
77 | lll_robust_unlock (mtxp->__lock, flags); |
78 | } |
79 | |
80 | break; |
81 | |
82 | default: |
83 | ret = EINVAL; |
84 | break; |
85 | } |
86 | |
87 | return ret; |
88 | } |
89 | |
90 | hidden_def (__pthread_mutex_unlock) |
91 | strong_alias (__pthread_mutex_unlock, _pthread_mutex_unlock) |
92 | weak_alias (__pthread_mutex_unlock, pthread_mutex_unlock) |
93 | |