Home | History | Annotate | Download | only in pthreads-win32
      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 (at) 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 #include "pthread.h"
     38 #include "implement.h"
     39 
     40 
     41 int
     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