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