131 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			131 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#include <minix/mthread.h>
 | 
						|
#include "global.h"
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				mthread_rwlock_init			     *
 | 
						|
 *===========================================================================*/
 | 
						|
int mthread_rwlock_init(rwlock)
 | 
						|
mthread_rwlock_t *rwlock; /* The rwlock to be initialized */
 | 
						|
{
 | 
						|
  /* Initialize a readers/writer lock. */
 | 
						|
  int r;
 | 
						|
 | 
						|
  if (!rwlock)
 | 
						|
	return EINVAL;
 | 
						|
 | 
						|
  rwlock->writer = NO_THREAD;
 | 
						|
  rwlock->readers = 0;
 | 
						|
 | 
						|
  r = mthread_mutex_init(&rwlock->queue, NULL);
 | 
						|
  if (r != 0)
 | 
						|
	return r;
 | 
						|
 | 
						|
  r = mthread_event_init(&rwlock->drain);
 | 
						|
  if (r != 0)
 | 
						|
	mthread_mutex_destroy(&rwlock->queue);
 | 
						|
 | 
						|
  return r;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				mthread_rwlock_destroy			     *
 | 
						|
 *===========================================================================*/
 | 
						|
int mthread_rwlock_destroy(rwlock)
 | 
						|
mthread_rwlock_t *rwlock; /* The rwlock to be destroyed */
 | 
						|
{
 | 
						|
  /* Destroy a readers/writer lock. */
 | 
						|
  int r;
 | 
						|
 | 
						|
  if (!rwlock)
 | 
						|
	return EINVAL;
 | 
						|
 | 
						|
  assert(rwlock->writer == NO_THREAD);
 | 
						|
  assert(rwlock->readers == 0);
 | 
						|
 | 
						|
  r = mthread_event_destroy(&rwlock->drain);
 | 
						|
  if (r != 0)
 | 
						|
	return r;
 | 
						|
 | 
						|
  return mthread_mutex_destroy(&rwlock->queue);
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				mthread_rwlock_rdlock			     *
 | 
						|
 *===========================================================================*/
 | 
						|
int mthread_rwlock_rdlock(rwlock)
 | 
						|
mthread_rwlock_t *rwlock; /* The rwlock to be read locked */
 | 
						|
{
 | 
						|
  /* Acquire a reader lock. */
 | 
						|
  int r;
 | 
						|
 | 
						|
  if (!rwlock)
 | 
						|
	return EINVAL;
 | 
						|
 | 
						|
  r = mthread_mutex_lock(&rwlock->queue);
 | 
						|
  if (r != 0)
 | 
						|
	return r;
 | 
						|
 | 
						|
  r = mthread_mutex_unlock(&rwlock->queue);
 | 
						|
  if (r != 0)
 | 
						|
	return r;
 | 
						|
 | 
						|
  rwlock->readers++;
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				mthread_rwlock_wrlock			     *
 | 
						|
 *===========================================================================*/
 | 
						|
int mthread_rwlock_wrlock(rwlock)
 | 
						|
mthread_rwlock_t *rwlock; /* The rwlock to be write locked */
 | 
						|
{
 | 
						|
  /* Acquire a writer lock. */
 | 
						|
  int r;
 | 
						|
 | 
						|
  if (!rwlock)
 | 
						|
	  return EINVAL;
 | 
						|
 | 
						|
  r = mthread_mutex_lock(&rwlock->queue);
 | 
						|
  if (r != 0)
 | 
						|
	return r;
 | 
						|
 | 
						|
  rwlock->writer = current_thread;
 | 
						|
 | 
						|
  if (rwlock->readers > 0)
 | 
						|
	r = mthread_event_wait(&rwlock->drain);
 | 
						|
 | 
						|
  if (r == 0)
 | 
						|
	assert(rwlock->readers == 0);
 | 
						|
 | 
						|
  return r;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				mthread_rwlock_unlock				*
 | 
						|
 *===========================================================================*/
 | 
						|
int mthread_rwlock_unlock(rwlock)
 | 
						|
mthread_rwlock_t *rwlock; /* The rwlock to be unlocked */
 | 
						|
{
 | 
						|
  /* Release a lock. */
 | 
						|
  int r;
 | 
						|
 | 
						|
  r = 0;
 | 
						|
  if (!rwlock)
 | 
						|
	  return EINVAL;
 | 
						|
 | 
						|
  if (rwlock->writer == current_thread) {
 | 
						|
	rwlock->writer = NO_THREAD;
 | 
						|
	r = mthread_mutex_unlock(&rwlock->queue);
 | 
						|
  } else {
 | 
						|
	assert(rwlock->readers > 0);
 | 
						|
 | 
						|
	rwlock->readers--;
 | 
						|
 | 
						|
	if (rwlock->readers == 0 && rwlock->writer != NO_THREAD)
 | 
						|
		r = mthread_event_fire(&rwlock->drain);
 | 
						|
  }
 | 
						|
 | 
						|
  return r;
 | 
						|
}
 |