/*
 * ptw32_mcs_lock_acquire -- acquire an MCS lock.
 * 
 * See: 
 * J. M. Mellor-Crummey and M. L. Scott.
 * Algorithms for Scalable Synchronization on Shared-Memory Multiprocessors.
 * ACM Transactions on Computer Systems, 9(1):21-65, Feb. 1991.
 */
INLINE void 
ptw32_mcs_lock_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node)
{
  ptw32_mcs_local_node_t  *pred;
  
  node->lock = lock;
  node->nextFlag = 0;
  node->readyFlag = 0;
  node->next = 0; /* initially, no successor */
  
  /* queue for the lock */
  pred = (ptw32_mcs_local_node_t *)PTW32_INTERLOCKED_EXCHANGE((LPLONG)lock,
						              (LONG)node);

  if (0 != pred)
    {
      /* the lock was not free. link behind predecessor. */
      pred->next = node;
      ptw32_mcs_flag_set(&pred->nextFlag);
      ptw32_mcs_flag_wait(&node->readyFlag);
    }
}
示例#2
0
INLINE int
pthread_mutex_unlock (pthread_mutex_t * mutex)
{
  int result = 0;
  pthread_mutex_t mx;

  /*
   * Let the system deal with invalid pointers.
   */

  mx = *mutex;

  /*
   * If the thread calling us holds the mutex then there is no
   * race condition. If another thread holds the
   * lock then we shouldn't be in here.
   */
  if (!ptw32_static_mutex_enable || (mx < PTHREAD_ERRORCHECK_MUTEX_INITIALIZER))
    {
      if (mx->kind == PTHREAD_MUTEX_NORMAL)
	{
	  LONG idx;

	  idx = (LONG) PTW32_INTERLOCKED_EXCHANGE ((LPLONG) &mx->lock_idx,
						   (LONG) 0);
	  if (idx != 0)
	    {
	      if (idx < 0)
		{
		  /*
		   * Someone may be waiting on that mutex.
		   */
		  if (SetEvent (mx->event) == 0)
		    {
		      result = EINVAL;
		    }
		}
	    }
	  else
	    {
	      /*
	       * Was not locked (so can't be owned by us).
	       */
	      result = EPERM;
	    }
	}
      else
	{
	  if (pthread_equal (mx->ownerThread, pthread_self ()))
	    {
	      if (mx->kind != PTHREAD_MUTEX_RECURSIVE
		  || 0 == --mx->recursive_count)
		{
		  mx->ownerThread.p = NULL;

		  if ((LONG) PTW32_INTERLOCKED_EXCHANGE ((LPLONG) &mx->lock_idx,
							 (LONG) 0) < 0)
		    {
		      /* Someone may be waiting on that mutex */
		      if (SetEvent (mx->event) == 0)
			{
			  result = EINVAL;
			}
		    }
		}
	    }
	  else
	    {
	      result = EPERM;
	    }
	}
    }
  else
    {
      result = EINVAL;
    }

  return (result);
}
示例#3
0
int
pthread_mutex_lock (pthread_mutex_t * mutex)
{
  int result = 0;
  pthread_mutex_t mx;

  /*
   * Let the system deal with invalid pointers.
   */

  /*
   * We do a quick check to see if we need to do more work
   * to initialise a static mutex. We check
   * again inside the guarded section of ptw32_mutex_check_need_init()
   * to avoid race conditions.
   */
  if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
    {
      if ((result = ptw32_mutex_check_need_init (mutex)) != 0)
	{
	  return (result);
	}
    }

  mx = *mutex;

  if (mx->kind == PTHREAD_MUTEX_NORMAL)
    {
      if ((LONG) PTW32_INTERLOCKED_EXCHANGE(
		   (LPLONG) &mx->lock_idx,
		   (LONG) 1) != 0)
	{
	  while ((LONG) PTW32_INTERLOCKED_EXCHANGE(
                          (LPLONG) &mx->lock_idx,
			  (LONG) -1) != 0)
	    {
	      if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE))
	        {
	          result = EINVAL;
		  break;
	        }
	    }
	}
    }
  else
    {
      pthread_t self = pthread_self();

      if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE(
                   (PTW32_INTERLOCKED_LPLONG) &mx->lock_idx,
		   (PTW32_INTERLOCKED_LONG) 1,
		   (PTW32_INTERLOCKED_LONG) 0) == 0)
	{
	  mx->recursive_count = 1;
	  mx->ownerThread = self;
	}
      else
	{
	  if (pthread_equal (mx->ownerThread, self))
	    {
	      if (mx->kind == PTHREAD_MUTEX_RECURSIVE)
		{
		  mx->recursive_count++;
		}
	      else
		{
		  result = EDEADLK;
		}
	    }
	  else
	    {
	      while ((LONG) PTW32_INTERLOCKED_EXCHANGE(
                              (LPLONG) &mx->lock_idx,
			      (LONG) -1) != 0)
		{
	          if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE))
		    {
	              result = EINVAL;
		      break;
		    }
		}

	      if (0 == result)
		{
		  mx->recursive_count = 1;
		  mx->ownerThread = self;
		}
	    }
	}
    }

  return (result);
}