- add sources.
[platform/framework/web/crosswalk.git] / src / native_client_sdk / src / libraries / third_party / pthreads-win32 / pthread_mutex_lock.c
1 /*
2  * pthread_mutex_lock.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  *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
35  */
36
37 #if !defined(_UWIN)
38 /*#   include <process.h> */
39 #endif
40 #include "pthread.h"
41 #include "implement.h"
42
43 int
44 pthread_mutex_lock (pthread_mutex_t * mutex)
45 {
46   int kind;
47   pthread_mutex_t mx;
48   int result = 0;
49
50   /*
51    * Let the system deal with invalid pointers.
52    */
53   if (*mutex == NULL)
54     {
55       return EINVAL;
56     }
57
58   /*
59    * We do a quick check to see if we need to do more work
60    * to initialise a static mutex. We check
61    * again inside the guarded section of ptw32_mutex_check_need_init()
62    * to avoid race conditions.
63    */
64   if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
65     {
66       if ((result = ptw32_mutex_check_need_init (mutex)) != 0)
67         {
68           return (result);
69         }
70     }
71
72   mx = *mutex;
73   kind = mx->kind;
74
75   if (kind >= 0)
76     {
77       /* Non-robust */
78       if (PTHREAD_MUTEX_NORMAL == kind)
79         {
80           if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
81                        (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
82                        (PTW32_INTERLOCKED_LONG) 1) != 0)
83             {
84               while ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
85                               (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
86                               (PTW32_INTERLOCKED_LONG) -1) != 0)
87                 {
88                   if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE))
89                     {
90                       result = EINVAL;
91                       break;
92                     }
93                 }
94             }
95         }
96       else
97         {
98           pthread_t self = pthread_self();
99
100           if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(
101                        (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
102                        (PTW32_INTERLOCKED_LONG) 1,
103                        (PTW32_INTERLOCKED_LONG) 0) == 0)
104             {
105               mx->recursive_count = 1;
106               mx->ownerThread = self;
107             }
108           else
109             {
110               if (pthread_equal (mx->ownerThread, self))
111                 {
112                   if (kind == PTHREAD_MUTEX_RECURSIVE)
113                     {
114                       mx->recursive_count++;
115                     }
116                   else
117                     {
118                       result = EDEADLK;
119                     }
120                 }
121               else
122                 {
123                   while ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
124                                   (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
125                                   (PTW32_INTERLOCKED_LONG) -1) != 0)
126                     {
127                       if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE))
128                         {
129                           result = EINVAL;
130                           break;
131                         }
132                     }
133
134                   if (0 == result)
135                     {
136                       mx->recursive_count = 1;
137                       mx->ownerThread = self;
138                     }
139                 }
140             }
141         }
142     }
143   else
144     {
145       /*
146        * Robust types
147        * All types record the current owner thread.
148        * The mutex is added to a per thread list when ownership is acquired.
149        */
150       ptw32_robust_state_t* statePtr = &mx->robustNode->stateInconsistent;
151
152       if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE == PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(
153                                                  (PTW32_INTERLOCKED_LONGPTR)statePtr,
154                                                  (PTW32_INTERLOCKED_LONG)0))
155         {
156           result = ENOTRECOVERABLE;
157         }
158       else
159         {
160           pthread_t self = pthread_self();
161
162           kind = -kind - 1; /* Convert to non-robust range */
163     
164           if (PTHREAD_MUTEX_NORMAL == kind)
165             {
166               if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
167                            (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
168                            (PTW32_INTERLOCKED_LONG) 1) != 0)
169                 {
170                   while (0 == (result = ptw32_robust_mutex_inherit(mutex))
171                            && (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
172                                        (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
173                                        (PTW32_INTERLOCKED_LONG) -1) != 0)
174                     {
175                       if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE))
176                         {
177                           result = EINVAL;
178                           break;
179                         }
180                       if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE ==
181                                   PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(
182                                     (PTW32_INTERLOCKED_LONGPTR)statePtr,
183                                     (PTW32_INTERLOCKED_LONG)0))
184                         {
185                           /* Unblock the next thread */
186                           SetEvent(mx->event);
187                           result = ENOTRECOVERABLE;
188                           break;
189                         }
190                     }
191                 }
192               if (0 == result || EOWNERDEAD == result)
193                 {
194                   /*
195                    * Add mutex to the per-thread robust mutex currently-held list.
196                    * If the thread terminates, all mutexes in this list will be unlocked.
197                    */
198                   ptw32_robust_mutex_add(mutex, self);
199                 }
200             }
201           else
202             {
203               if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(
204                            (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
205                            (PTW32_INTERLOCKED_LONG) 1,
206                            (PTW32_INTERLOCKED_LONG) 0) == 0)
207                 {
208                   mx->recursive_count = 1;
209                   /*
210                    * Add mutex to the per-thread robust mutex currently-held list.
211                    * If the thread terminates, all mutexes in this list will be unlocked.
212                    */
213                   ptw32_robust_mutex_add(mutex, self);
214                 }
215               else
216                 {
217                   if (pthread_equal (mx->ownerThread, self))
218                     {
219                       if (PTHREAD_MUTEX_RECURSIVE == kind)
220                         {
221                           mx->recursive_count++;
222                         }
223                       else
224                         {
225                           result = EDEADLK;
226                         }
227                     }
228                   else
229                     {
230                       while (0 == (result = ptw32_robust_mutex_inherit(mutex))
231                                && (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
232                                            (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
233                                            (PTW32_INTERLOCKED_LONG) -1) != 0)
234                         {
235                           if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE))
236                             {
237                               result = EINVAL;
238                               break;
239                             }
240                           if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE ==
241                                       PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(
242                                         (PTW32_INTERLOCKED_LONGPTR)statePtr,
243                                         (PTW32_INTERLOCKED_LONG)0))
244                             {
245                               /* Unblock the next thread */
246                               SetEvent(mx->event);
247                               result = ENOTRECOVERABLE;
248                               break;
249                             }
250                         }
251
252                       if (0 == result || EOWNERDEAD == result)
253                         {
254                           mx->recursive_count = 1;
255                           /*
256                            * Add mutex to the per-thread robust mutex currently-held list.
257                            * If the thread terminates, all mutexes in this list will be unlocked.
258                            */
259                           ptw32_robust_mutex_add(mutex, self);
260                         }
261                     }
262                 }
263             }
264         }
265     }
266
267   return (result);
268 }
269