This is locks_shared.c in view mode; [Download] [Up]
/*
* -- FILE: locks_shared.c
* AUTHOR: Michael T. Peterson
*
* Copyright (C) 1994, by Michael T. Peterson
* All rights reserved.
*
* Permission is granted for noncommercial, private use of this software.
* You are expressely prohibited from selling this software, distributing
* this software with (or within) another product, or removing this notice.
*/
#include <utils.h>
#include <locks.h>
static const int WRITER_ACTIVE = -1;
static const int NO_THREAD_ACTIVE = 0;
static pthread_once_t once_block = pthread_once_init;
static int lib_initialized = FALSE;
static pthread_mutex_t liblock;
#define UNLOCK(l) ((void)pthread_mutex_unlock( &(l) ))
#define LOCK(l) ((void)pthread_mutex_lock( &(l) ))
struct SHARED_LOCK
{
int Activity;
int ReaderCount; /* The count of Readers waiting at 'Shared' */
int WriterCount; /* The count of Writers waiting at 'Exclusive */
pthread_mutex_t Lock;
pthread_cond_t Exclusive;
pthread_cond_t Shared;
};
static void
_rw_init( void )
{
pthread_mutex_init( &liblock, NULL );
lib_initialized = TRUE;
}
int
pthread_rw_lock_shared_np( const pthread_rwlock_t *lock )
{
struct SHARED_LOCK *sh;
pthread_once( &once_block, _rw_init );
if( lock == NULL )
return( ENOLCK );
if( (sh = *lock) == NULL )
return( ENOLCK );
pthread_mutex_lock( &sh->Lock );
sh->ReaderCount+= 1;
/*
* -- If a writer is waiting to access the shared data, signal it
* to proceed then block. It will wake up the reader upon the
* writer's completion.
*/
if( sh->WriterCount > 0 )
{
pthread_cond_signal( &sh->Exclusive );
pthread_cond_wait( &sh->Shared, &sh->Lock );
}
while( sh->Activity < 0 )
pthread_cond_wait( &sh->Shared, &sh->Lock );
sh->ReaderCount -= 1;
sh->Activity += 1;
pthread_mutex_unlock( &sh->Lock );
pthread_cond_signal( &sh->Shared );
return( SUCCESS );
}
int
pthread_rw_unlock_exclusive_np( const pthread_rwlock_t *lock )
{
struct SHARED_LOCK *sh;
pthread_once( &once_block, _rw_init );
if( lock == NULL )
return( ENOLCK );
if( (sh = *lock) == NULL )
return( ENOLCK );
pthread_mutex_lock( &sh->Lock );
sh->Activity = NO_THREAD_ACTIVE;
if( sh->ReaderCount > 0 )
pthread_cond_broadcast( &sh->Shared );
else
{
if( sh->WriterCount > 0 )
pthread_cond_signal( &sh->Exclusive );
}
pthread_mutex_unlock( &sh->Lock );
return( SUCCESS );
}
int
pthread_rw_lock_exclusive_np( const pthread_rwlock_t *lock )
{
struct SHARED_LOCK *sh;
pthread_once( &once_block, _rw_init );
if( lock == NULL )
return( ENOLCK );
if( (sh = *lock) == NULL )
return( ENOLCK );
pthread_mutex_lock( &sh->Lock );
sh->WriterCount += 1;
while( sh->Activity != 0 )
pthread_cond_wait( &sh->Exclusive, &sh->Lock );
sh->WriterCount -= 1;
sh->Activity = WRITER_ACTIVE;
pthread_mutex_unlock( &sh->Lock );
return( SUCCESS );
}
int
pthread_rw_unlock_shared_np( const pthread_rwlock_t *lock )
{
int DoSignal = FALSE;
struct SHARED_LOCK *sh;
pthread_once( &once_block, _rw_init );
if( lock == NULL )
return( ENOLCK );
if( (sh = *lock) == NULL )
return( ENOLCK );
pthread_mutex_lock( &sh->Lock );
sh->Activity -= 1;
if( sh->Activity == NO_THREAD_ACTIVE )
DoSignal = TRUE;
pthread_mutex_unlock( &sh->Lock );
if( DoSignal )
pthread_cond_signal( &sh->Exclusive );
return( SUCCESS );
}
int
pthread_rw_init_np( pthread_rwlock_t *shared )
{
struct SHARED_LOCK *sh;
int status;
pthread_once( &once_block, _rw_init );
sh = (struct SHARED_LOCK *) malloc_r( sizeof( struct SHARED_LOCK ));
if( sh == NULL )
return( ENOMEM );
sh->Activity = 0;
sh->ReaderCount = 0;
sh->WriterCount = 0;
status = pthread_mutex_init( &sh->Lock, NULL );
if( status != SUCCESS )
{
free_r( sh );
return( status );
}
status = pthread_cond_init( &sh->Exclusive, NULL );
if( status != SUCCESS )
{
(void) pthread_mutex_destroy( &sh->Lock );
free_r( sh );
return( status );
}
status = pthread_cond_init( &sh->Shared, NULL );
if( status != SUCCESS )
{
(void) pthread_mutex_destroy( &sh->Lock );
(void) pthread_cond_destroy( &sh->Exclusive );
free_r( sh );
return( status );
}
*shared = sh;
return( SUCCESS );
}
int
pthread_rw_destroy_np( pthread_rwlock_t *lock )
{
struct SHARED_LOCK *sh;
pthread_once( &once_block, _rw_init );
LOCK(liblock);
if( lock == NULL )
return( ENOLCK );
if( (sh = *lock) == NULL )
return( ENOLCK );
pthread_mutex_destroy( &sh->Lock );
pthread_cond_destroy( &sh->Exclusive );
pthread_cond_destroy( &sh->Shared );
free_r( sh );
*lock = NULL;
UNLOCK(liblock);
return( SUCCESS );
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.