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;
 | |
| }
 |