Status_Control _CORE_RWLock_Seize_for_writing( CORE_RWLock_Control *the_rwlock, Thread_Control *executing, bool wait, Watchdog_Interval timeout, Thread_queue_Context *queue_context ) { /* * If unlocked, then OK to read. * Otherwise, we have to block. * If locked for reading and no waiters, then OK to read. * If any thread is waiting, then we wait. */ _CORE_RWLock_Acquire_critical( the_rwlock, queue_context ); switch ( the_rwlock->current_state ) { case CORE_RWLOCK_UNLOCKED: the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_WRITING; _CORE_RWLock_Release( the_rwlock, queue_context ); return STATUS_SUCCESSFUL; case CORE_RWLOCK_LOCKED_FOR_READING: case CORE_RWLOCK_LOCKED_FOR_WRITING: break; } /* * If the thread is not willing to wait, then return immediately. */ if ( !wait ) { _CORE_RWLock_Release( the_rwlock, queue_context ); return STATUS_UNAVAILABLE; } /* * We need to wait to enter this critical section */ executing->Wait.option = CORE_RWLOCK_THREAD_WAITING_FOR_WRITE; _Thread_queue_Context_set_expected_level( queue_context, 1 ); _Thread_queue_Enqueue_critical( &the_rwlock->Wait_queue.Queue, CORE_RWLOCK_TQ_OPERATIONS, executing, STATES_WAITING_FOR_RWLOCK, timeout, queue_context ); return _Thread_Wait_get_status( executing ); }
Status_Control _CORE_RWLock_Surrender( CORE_RWLock_Control *the_rwlock, Thread_queue_Context *queue_context ) { /* * If unlocked, then OK to read. * Otherwise, we have to block. * If locked for reading and no waiters, then OK to read. * If any thread is waiting, then we wait. */ _CORE_RWLock_Acquire_critical( the_rwlock, queue_context ); if ( the_rwlock->current_state == CORE_RWLOCK_UNLOCKED){ /* This is an error at the caller site */ _CORE_RWLock_Release( the_rwlock, queue_context ); return STATUS_SUCCESSFUL; } if ( the_rwlock->current_state == CORE_RWLOCK_LOCKED_FOR_READING ) { the_rwlock->number_of_readers -= 1; if ( the_rwlock->number_of_readers != 0 ) { /* must be unlocked again */ _CORE_RWLock_Release( the_rwlock, queue_context ); return STATUS_SUCCESSFUL; } } _Assert( the_rwlock->current_state == CORE_RWLOCK_LOCKED_FOR_WRITING || ( the_rwlock->current_state == CORE_RWLOCK_LOCKED_FOR_READING && the_rwlock->number_of_readers == 0 ) ); /* * Implicitly transition to "unlocked" and find another thread interested * in obtaining this rwlock. */ the_rwlock->current_state = CORE_RWLOCK_UNLOCKED; _Thread_queue_Flush_critical( &the_rwlock->Wait_queue.Queue, CORE_RWLOCK_TQ_OPERATIONS, _CORE_RWLock_Flush_filter, queue_context ); return STATUS_SUCCESSFUL; }
int pthread_rwlock_destroy( pthread_rwlock_t *rwlock ) { POSIX_RWLock_Control *the_rwlock; ISR_lock_Context lock_context; _Objects_Allocator_lock(); the_rwlock = _POSIX_RWLock_Get( rwlock, &lock_context ); if ( the_rwlock == NULL ) { _Objects_Allocator_unlock(); return EINVAL; } _CORE_RWLock_Acquire_critical( &the_rwlock->RWLock, &lock_context ); /* * If there is at least one thread waiting, then do not delete it. */ if ( !_Thread_queue_Is_empty( &the_rwlock->RWLock.Wait_queue.Queue ) ) { _CORE_RWLock_Release( &the_rwlock->RWLock, &lock_context ); _Objects_Allocator_unlock(); return EBUSY; } /* * POSIX doesn't require behavior when it is locked. */ _Objects_Close( &_POSIX_RWLock_Information, &the_rwlock->Object ); _CORE_RWLock_Release( &the_rwlock->RWLock, &lock_context ); _POSIX_RWLock_Free( the_rwlock ); _Objects_Allocator_unlock(); return 0; }