diff options
Diffstat (limited to 'pthread_mutex_timedlock.c')
| -rw-r--r-- | pthread_mutex_timedlock.c | 175 | 
1 files changed, 73 insertions, 102 deletions
diff --git a/pthread_mutex_timedlock.c b/pthread_mutex_timedlock.c index 58f5613..cf929bc 100644 --- a/pthread_mutex_timedlock.c +++ b/pthread_mutex_timedlock.c @@ -206,7 +206,7 @@ int  pthread_mutex_timedlock (pthread_mutex_t * mutex,  			 const struct timespec *abstime)  { -  int result = 0; +  LONG c;    pthread_mutex_t mx;  #ifdef NEED_SEM @@ -226,6 +226,8 @@ pthread_mutex_timedlock (pthread_mutex_t * mutex,     */    if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)      { +      int result; +        if ((result = ptw32_mutex_check_need_init (mutex)) != 0)  	{  	  return (result); @@ -236,63 +238,51 @@ pthread_mutex_timedlock (pthread_mutex_t * mutex,    if (mx->kind == PTHREAD_MUTEX_NORMAL)      { -      if (0 != InterlockedIncrement (&mx->lock_idx)) +      if ((c = (LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE( +		        (PTW32_INTERLOCKED_LPLONG) &mx->lock_idx, +		        (PTW32_INTERLOCKED_LONG) 0, +		        (PTW32_INTERLOCKED_LONG) -1)) != -1)  	{ -	  switch (ptw32_timed_semwait (&mx->wait_sema, abstime)) -	    { -	      case 0:	/* We got the mutex. */ -		{ -		  break; -		} -	      case 1:	/* Timed out. */ -	      case 2:	/* abstime passed before we started to wait. */ -		{ -		  /* -		   * If we timeout, it is up to us to adjust lock_idx to say -		   * we're no longer waiting. -		   * -		   * The owner thread may still have posted wait_sema thinking -		   * we were waiting. We must check but then NOT do any -		   * programmed work if we have acquired the mutex because -		   * we don't know how long ago abstime was. We MUST just release it -		   * immediately. -		   */ -		  EnterCriticalSection (&mx->wait_cs); - -		  result = ETIMEDOUT; - -		  if (-1 == sem_trywait (&mx->wait_sema)) +          do +            { +              if (c == 1 || +                  (LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE( +                           (PTW32_INTERLOCKED_LPLONG) &mx->lock_idx, +                           (PTW32_INTERLOCKED_LONG) 1, +                           (PTW32_INTERLOCKED_LONG) 0) != -1) +                { +		  switch (ptw32_timed_semwait (&mx->wait_sema, abstime))  		    { -		      (void) InterlockedDecrement (&mx->lock_idx); -		    } -		  else -		    { -		      if (InterlockedDecrement (&mx->lock_idx) >= 0) -			{ -			  /* Someone else is waiting on that mutex */ -			  if (sem_post (&mx->wait_sema) != 0) -			    { -			      result = errno; -			    } -			} -		    } - -		  LeaveCriticalSection (&mx->wait_cs); -		  break; -		} -	      default: -		{ -		  result = errno; -		  break; +		    case 0:	/* We got woken up so try get the lock again. */ +		      { +		        break; +		      } +		    case 1:	/* Timed out. */ +		    case 2:	/* abstime passed before we started to wait. */ +		      { +		        return ETIMEDOUT; +		      } +		    default: +		      { +		        return errno; +		      } +		  }  		} -	    } +            } +          while ((c = (LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE( +                               (PTW32_INTERLOCKED_LPLONG) &mx->lock_idx, +                               (PTW32_INTERLOCKED_LONG) 1, +                               (PTW32_INTERLOCKED_LONG) -1)) != -1);  	}      }    else      {        pthread_t self = pthread_self(); -      if (0 == InterlockedIncrement (&mx->lock_idx)) +      if ((c = (LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE( +                        (PTW32_INTERLOCKED_LPLONG) &mx->lock_idx, +		        (PTW32_INTERLOCKED_LONG) 0, +		        (PTW32_INTERLOCKED_LONG) -1)) == -1)  	{  	  mx->recursive_count = 1;  	  mx->ownerThread = self; @@ -301,72 +291,53 @@ pthread_mutex_timedlock (pthread_mutex_t * mutex,  	{  	  if (pthread_equal (mx->ownerThread, self))  	    { -	      (void) InterlockedDecrement (&mx->lock_idx); -  	      if (mx->kind == PTHREAD_MUTEX_RECURSIVE)  		{  		  mx->recursive_count++;  		}  	      else  		{ -		  result = EDEADLK; +		  return EDEADLK;  		}  	    }  	  else  	    { -	      switch (ptw32_timed_semwait (&mx->wait_sema, abstime)) -		{ -		  case 0:	/* We got the mutex. */ -		    { -		      mx->recursive_count = 1; -		      mx->ownerThread = self; -		      break; +              do +                { +                  if (c == 1 || +                      (LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE( +                               (PTW32_INTERLOCKED_LPLONG) &mx->lock_idx, +                               (PTW32_INTERLOCKED_LONG) 1, +                               (PTW32_INTERLOCKED_LONG) 0) != -1) +                    { +		      switch (ptw32_timed_semwait (&mx->wait_sema, abstime)) +		        { +		        case 0:	/* We got woken up so try get the lock again. */ +		          { +		            break; +		          } +		        case 1:	/* Timed out. */ +		        case 2:	/* abstime passed before we started to wait. */ +		          { +		            return ETIMEDOUT; +		          } +		        default: +		          { +		            return errno; +		          } +		      }  		    } -		  case 1:	/* Timedout. */ -		  case 2:	/* abstime passed before we started to wait. */ -		    { -		      /* -		       * If we timeout, it is up to us to adjust lock_idx to say -		       * we're no longer waiting. -		       * -		       * The owner thread may still have posted wait_sema thinking -		       * we were waiting. We must check but then NOT do any -		       * programmed work if we have acquired the mutex because -		       * we don't know how long ago abstime was. We MUST just release it -		       * immediately. -		       */ -		      EnterCriticalSection (&mx->wait_cs); - -		      result = ETIMEDOUT; - -		      if (-1 == sem_trywait (&mx->wait_sema)) -			{ -			  (void) InterlockedDecrement (&mx->lock_idx); -			} -		     else -			{ -			  if (InterlockedDecrement (&mx->lock_idx) >= 0) -			    { -			      /* Someone else is waiting on that mutex */ -			      if (sem_post (&mx->wait_sema) != 0) -				{ -				  result = errno; -				} -			    } -			} - -		      LeaveCriticalSection (&mx->wait_cs); -		      break; -		    } -		  default: -		    { -		      result = errno; -		      break; -		    } -		} +                } +              while ((c = (LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE( +                                   (PTW32_INTERLOCKED_LPLONG) &mx->lock_idx, +                                   (PTW32_INTERLOCKED_LONG) 1, +                                   (PTW32_INTERLOCKED_LONG) -1)) != -1); + +	      mx->recursive_count = 1; +	      mx->ownerThread = self;  	    }  	}      } -  return (result); +  return 0;  }  | 
