1 /*
2  * pthread_mutex_trylock.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 
37 #include "pthread.h"
38 #include "implement.h"
39 
40 
41 int
pthread_mutex_trylock(pthread_mutex_t * mutex)42 pthread_mutex_trylock (pthread_mutex_t * mutex)
43 {
44   pthread_mutex_t mx;
45   int kind;
46   int result = 0;
47 
48   /*
49    * Let the system deal with invalid pointers.
50    */
51 
52   /*
53    * We do a quick check to see if we need to do more work
54    * to initialise a static mutex. We check
55    * again inside the guarded section of ptw32_mutex_check_need_init()
56    * to avoid race conditions.
57    */
58   if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
59     {
60       if ((result = ptw32_mutex_check_need_init (mutex)) != 0)
61 	{
62 	  return (result);
63 	}
64     }
65 
66   mx = *mutex;
67   kind = mx->kind;
68 
69   if (kind >= 0)
70     {
71       /* Non-robust */
72       if (0 == (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG (
73 		         (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
74 		         (PTW32_INTERLOCKED_LONG) 1,
75 		         (PTW32_INTERLOCKED_LONG) 0))
76         {
77           if (kind != PTHREAD_MUTEX_NORMAL)
78 	    {
79 	      mx->recursive_count = 1;
80 	      mx->ownerThread = pthread_self ();
81 	    }
82         }
83       else
84         {
85           if (kind == PTHREAD_MUTEX_RECURSIVE &&
86 	      pthread_equal (mx->ownerThread, pthread_self ()))
87 	    {
88 	      mx->recursive_count++;
89 	    }
90           else
91 	    {
92 	      result = EBUSY;
93 	    }
94         }
95     }
96   else
97     {
98       /*
99        * Robust types
100        * All types record the current owner thread.
101        * The mutex is added to a per thread list when ownership is acquired.
102        */
103       pthread_t self;
104       ptw32_robust_state_t* statePtr = &mx->robustNode->stateInconsistent;
105 
106       if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE ==
107                   PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(
108                     (PTW32_INTERLOCKED_LONGPTR)statePtr,
109                     (PTW32_INTERLOCKED_LONG)0))
110         {
111           return ENOTRECOVERABLE;
112         }
113 
114       self = pthread_self();
115       kind = -kind - 1; /* Convert to non-robust range */
116 
117       if (0 == (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG (
118         	         (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
119         	         (PTW32_INTERLOCKED_LONG) 1,
120         	         (PTW32_INTERLOCKED_LONG) 0))
121         {
122           if (kind != PTHREAD_MUTEX_NORMAL)
123             {
124               mx->recursive_count = 1;
125             }
126           ptw32_robust_mutex_add(mutex, self);
127         }
128       else
129         {
130           if (PTHREAD_MUTEX_RECURSIVE == kind &&
131               pthread_equal (mx->ownerThread, pthread_self ()))
132             {
133               mx->recursive_count++;
134             }
135           else
136             {
137               if (EOWNERDEAD == (result = ptw32_robust_mutex_inherit(mutex)))
138                 {
139                   mx->recursive_count = 1;
140                   ptw32_robust_mutex_add(mutex, self);
141                 }
142               else
143                 {
144                   if (0 == result)
145                     {
146 	              result = EBUSY;
147                     }
148                 }
149 	    }
150         }
151     }
152 
153   return (result);
154 }
155