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.