/** * 11.4.2 Initializing and Destroying a Condition Variable, * P1003.1c/Draft 10, p. 87 */ int pthread_cond_destroy( pthread_cond_t *cond ) { POSIX_Condition_variables_Control *the_cond; Objects_Locations location; the_cond = _POSIX_Condition_variables_Get( cond, &location ); switch ( location ) { case OBJECTS_LOCAL: if ( _Thread_queue_First( &the_cond->Wait_queue ) ) { _Thread_Enable_dispatch(); return EBUSY; } _Objects_Close( &_POSIX_Condition_variables_Information, &the_cond->Object ); _POSIX_Condition_variables_Free( the_cond ); _Thread_Enable_dispatch(); return 0; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: #endif case OBJECTS_ERROR: break; } return EINVAL; }
void _Region_Process_queue( Region_Control *the_region ) { Thread_Control *the_thread; void *the_segment; /* * Switch from using the memory allocation mutex to using a * dispatching disabled critical section. We have to do this * because this thread may unblock one or more threads that were * waiting on memory. * * NOTE: Be sure to disable dispatching before unlocking the mutex * since we do not want to open a window where a context * switch could occur. */ _Thread_Disable_dispatch(); _RTEMS_Unlock_allocator(); /* * NOTE: The following loop is O(n) where n is the number of * threads whose memory request is satisfied. */ for ( ; ; ) { the_thread = _Thread_queue_First( &the_region->Wait_queue ); if ( the_thread == NULL ) break; the_segment = (void **) _Region_Allocate_segment( the_region, the_thread->Wait.count ); if ( the_segment == NULL ) break; *(void **)the_thread->Wait.return_argument = the_segment; the_region->number_of_used_blocks += 1; _Thread_queue_Extract( &the_region->Wait_queue, the_thread ); the_thread->Wait.return_code = RTEMS_SUCCESSFUL; } _Thread_Enable_dispatch(); }
/** * 11.4.2 Initializing and Destroying a Condition Variable, * P1003.1c/Draft 10, p. 87 */ int pthread_cond_destroy( pthread_cond_t *cond ) { POSIX_Condition_variables_Control *the_cond; Objects_Locations location; _Objects_Allocator_lock(); the_cond = _POSIX_Condition_variables_Get( cond, &location ); switch ( location ) { case OBJECTS_LOCAL: if ( _Thread_queue_First( &the_cond->Wait_queue, POSIX_CONDITION_VARIABLES_TQ_OPERATIONS ) ) { _Objects_Put( &the_cond->Object ); _Objects_Allocator_unlock(); return EBUSY; } _Objects_Close( &_POSIX_Condition_variables_Information, &the_cond->Object ); _Objects_Put( &the_cond->Object ); _POSIX_Condition_variables_Free( the_cond ); _Objects_Allocator_unlock(); return 0; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: #endif case OBJECTS_ERROR: break; } _Objects_Allocator_unlock(); return EINVAL; }
/** * This directive allows a thread to delete a rwlock specified by * the rwlock id. The rwlock is freed back to the inactive * rwlock chain. * * @param[in] rwlock is the rwlock id * * @return This method returns 0 if there was not an * error. Otherwise, a status code is returned indicating the * source of the error. */ int pthread_rwlock_destroy( pthread_rwlock_t *rwlock ) { POSIX_RWLock_Control *the_rwlock = NULL; Objects_Locations location; if ( !rwlock ) return EINVAL; the_rwlock = _POSIX_RWLock_Get( rwlock, &location ); switch ( location ) { case OBJECTS_LOCAL: /* * If there is at least one thread waiting, then do not delete it. */ if ( _Thread_queue_First( &the_rwlock->RWLock.Wait_queue ) != NULL ) { _Objects_Put( &the_rwlock->Object ); return EBUSY; } /* * POSIX doesn't require behavior when it is locked. */ _Objects_Close( &_POSIX_RWLock_Information, &the_rwlock->Object ); _POSIX_RWLock_Free( the_rwlock ); _Objects_Put( &the_rwlock->Object ); return 0; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: #endif case OBJECTS_ERROR: break; } return EINVAL; }
ER ref_mbx( T_RMBX *pk_rmbx, ID mbxid ) { register ITRON_Mailbox_Control *the_mailbox; Objects_Locations location; Chain_Control *pending; if ( !pk_rmbx ) return E_PAR; the_mailbox = _ITRON_Mailbox_Get( mbxid, &location ); switch ( location ) { #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: #endif case OBJECTS_ERROR: return _ITRON_Mailbox_Clarify_get_id_error( mbxid ); case OBJECTS_LOCAL: pending = &the_mailbox->message_queue.Pending_messages; if ( _Chain_Is_empty( pending ) ) pk_rmbx->pk_msg = NULL; else pk_rmbx->pk_msg = (T_MSG *) pending->first; /* * Fill in whether or not there is a waiting task */ if ( !_Thread_queue_First( &the_mailbox->message_queue.Wait_queue ) ) pk_rmbx->wtsk = FALSE; else pk_rmbx->wtsk = TRUE; break; } _ITRON_return_errorno( E_OK ); }
void _CORE_RWLock_Obtain_for_reading( CORE_RWLock_Control *the_rwlock, Thread_Control *executing, Objects_Id id, bool wait, Watchdog_Interval timeout, CORE_RWLock_API_mp_support_callout api_rwlock_mp_support ) { ISR_Level level; /* * If unlocked, then OK to read. * If locked for reading and no waiters, then OK to read. * If any thread is waiting, then we wait. */ _ISR_Disable( level ); switch ( the_rwlock->current_state ) { case CORE_RWLOCK_UNLOCKED: the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_READING; the_rwlock->number_of_readers += 1; _ISR_Enable( level ); executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL; return; case CORE_RWLOCK_LOCKED_FOR_READING: { Thread_Control *waiter; waiter = _Thread_queue_First( &the_rwlock->Wait_queue ); if ( !waiter ) { the_rwlock->number_of_readers += 1; _ISR_Enable( level ); executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL; return; } break; } case CORE_RWLOCK_LOCKED_FOR_WRITING: break; } /* * If the thread is not willing to wait, then return immediately. */ if ( !wait ) { _ISR_Enable( level ); executing->Wait.return_code = CORE_RWLOCK_UNAVAILABLE; return; } /* * We need to wait to enter this critical section */ _Thread_queue_Enter_critical_section( &the_rwlock->Wait_queue ); executing->Wait.queue = &the_rwlock->Wait_queue; executing->Wait.id = id; executing->Wait.option = CORE_RWLOCK_THREAD_WAITING_FOR_READ; executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL; _ISR_Enable( level ); _Thread_queue_Enqueue( &the_rwlock->Wait_queue, executing, STATES_WAITING_FOR_RWLOCK, timeout ); /* return to API level so it can dispatch and we block */ }
CORE_RWLock_Status _CORE_RWLock_Release( CORE_RWLock_Control *the_rwlock, Thread_Control *executing ) { ISR_Level level; Thread_Control *next; /* * 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. */ _ISR_Disable( level ); if ( the_rwlock->current_state == CORE_RWLOCK_UNLOCKED){ _ISR_Enable( level ); executing->Wait.return_code = CORE_RWLOCK_UNAVAILABLE; return CORE_RWLOCK_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 */ _ISR_Enable( level ); return CORE_RWLOCK_SUCCESSFUL; } } /* CORE_RWLOCK_LOCKED_FOR_WRITING or READING with readers */ executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL; /* * Implicitly transition to "unlocked" and find another thread interested * in obtaining this rwlock. */ the_rwlock->current_state = CORE_RWLOCK_UNLOCKED; _ISR_Enable( level ); next = _Thread_queue_Dequeue( &the_rwlock->Wait_queue ); if ( next ) { if ( next->Wait.option == CORE_RWLOCK_THREAD_WAITING_FOR_WRITE ) { the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_WRITING; return CORE_RWLOCK_SUCCESSFUL; } /* * Must be CORE_RWLOCK_THREAD_WAITING_FOR_READING */ the_rwlock->number_of_readers += 1; the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_READING; /* * Now see if more readers can be let go. */ while ( 1 ) { next = _Thread_queue_First( &the_rwlock->Wait_queue ); if ( !next || next->Wait.option == CORE_RWLOCK_THREAD_WAITING_FOR_WRITE ) return CORE_RWLOCK_SUCCESSFUL; the_rwlock->number_of_readers += 1; _Thread_queue_Extract( &the_rwlock->Wait_queue, next ); } } /* indentation is to match _ISR_Disable at top */ return CORE_RWLOCK_SUCCESSFUL; }