1 /*
2 * pthread_mutex_consistent.c
3 *
4 * Description:
5 * This translation unit implements mutual exclusion (mutex) primitives.
6 *
7 * --------------------------------------------------------------------------
8 *
9 * Pthreads-win32 - POSIX Threads Library for Win32
10 * Copyright(C) 1998 John E. Bossom
11 * Copyright(C) 1999,2005 Pthreads-win32 contributors
12 *
13 * Contact Email: rpj@callisto.canberra.edu.au
14 *
15 * The current list of contributors is contained
16 * in the file CONTRIBUTORS included with the source
17 * code distribution. The list can also be seen at the
18 * following World Wide Web location:
19 * http://sources.redhat.com/pthreads-win32/contributors.html
20 *
21 * This library is free software; you can redistribute it and/or
22 * modify it under the terms of the GNU Lesser General Public
23 * License as published by the Free Software Foundation; either
24 * version 2 of the License, or (at your option) any later version.
25 *
26 * This library is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29 * Lesser General Public License for more details.
30 *
31 * You should have received a copy of the GNU Lesser General Public
32 * License along with this library in the file COPYING.LIB;
33 * if not, write to the Free Software Foundation, Inc.,
34 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
35 */
36 #if !defined(_UWIN)
37 /*# include <process.h> */
38 #endif
39 #include "pthread.h"
40 #include "implement.h"
41
42 INLINE
43 int
ptw32_robust_mutex_inherit(pthread_mutex_t * mutex)44 ptw32_robust_mutex_inherit(pthread_mutex_t * mutex)
45 {
46 int result;
47 pthread_mutex_t mx = *mutex;
48 ptw32_robust_node_t* robust = mx->robustNode;
49
50 switch ((LONG)PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(
51 (PTW32_INTERLOCKED_LONGPTR)&robust->stateInconsistent,
52 (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_INCONSISTENT,
53 (PTW32_INTERLOCKED_LONG)-1 /* The terminating thread sets this */))
54 {
55 case -1L:
56 result = EOWNERDEAD;
57 break;
58 case (LONG)PTW32_ROBUST_NOTRECOVERABLE:
59 result = ENOTRECOVERABLE;
60 break;
61 default:
62 result = 0;
63 break;
64 }
65
66 return result;
67 }
68
69 /*
70 * The next two internal support functions depend on only being
71 * called by the thread that owns the robust mutex. This enables
72 * us to avoid additional locks.
73 * Any mutex currently in the thread's robust mutex list is held
74 * by the thread, again eliminating the need for locks.
75 * The forward/backward links allow the thread to unlock mutexes
76 * in any order, not necessarily the reverse locking order.
77 * This is all possible because it is an error if a thread that
78 * does not own the [robust] mutex attempts to unlock it.
79 */
80
81 INLINE
82 void
ptw32_robust_mutex_add(pthread_mutex_t * mutex,pthread_t self)83 ptw32_robust_mutex_add(pthread_mutex_t* mutex, pthread_t self)
84 {
85 ptw32_robust_node_t** list;
86 pthread_mutex_t mx = *mutex;
87 ptw32_thread_t* tp = (ptw32_thread_t*)self.p;
88 ptw32_robust_node_t* robust = mx->robustNode;
89
90 list = &tp->robustMxList;
91 mx->ownerThread = self;
92 if (NULL == *list)
93 {
94 robust->prev = NULL;
95 robust->next = NULL;
96 *list = robust;
97 }
98 else
99 {
100 robust->prev = NULL;
101 robust->next = *list;
102 (*list)->prev = robust;
103 *list = robust;
104 }
105 }
106
107 INLINE
108 void
ptw32_robust_mutex_remove(pthread_mutex_t * mutex,ptw32_thread_t * otp)109 ptw32_robust_mutex_remove(pthread_mutex_t* mutex, ptw32_thread_t* otp)
110 {
111 ptw32_robust_node_t** list;
112 pthread_mutex_t mx = *mutex;
113 ptw32_robust_node_t* robust = mx->robustNode;
114
115 list = &(((ptw32_thread_t*)mx->ownerThread.p)->robustMxList);
116 mx->ownerThread.p = otp;
117 if (robust->next != NULL)
118 {
119 robust->next->prev = robust->prev;
120 }
121 if (robust->prev != NULL)
122 {
123 robust->prev->next = robust->next;
124 }
125 if (*list == robust)
126 {
127 *list = robust->next;
128 }
129 }
130
131
132 int
pthread_mutex_consistent(pthread_mutex_t * mutex)133 pthread_mutex_consistent (pthread_mutex_t* mutex)
134 {
135 pthread_mutex_t mx = *mutex;
136 int result = 0;
137
138 /*
139 * Let the system deal with invalid pointers.
140 */
141 if (mx == NULL)
142 {
143 return EINVAL;
144 }
145
146 if (mx->kind >= 0
147 || (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_INCONSISTENT != PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(
148 (PTW32_INTERLOCKED_LONGPTR)&mx->robustNode->stateInconsistent,
149 (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_CONSISTENT,
150 (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_INCONSISTENT))
151 {
152 result = EINVAL;
153 }
154
155 return (result);
156 }
157
158