📄 semlib.c
字号:
/* ** Ok... got a control block. Initialize it. */#ifdef DIAG_PRINTFS printf( "\r\nCreating binary semaphore - id %p", semaphore );#endif /* ** Option and Type Flags for semaphore */ semaphore->flags = (opt & SEM_Q_PRIORITY) | BINARY_SEMA4; /* ** Link the new semaphore into the semaphore list. */ link_smcb( semaphore ); } return( semaphore );}/******************************************************************************* semCCreate - creates a VxWorks counting semaphore*****************************************************************************/vxwk_sema4_t * semCCreate( int opt, int initial_count ){ vxwk_sema4_t *semaphore; /* ** First allocate memory for the semaphore control block */ semaphore = new_sema4( initial_count ); if ( semaphore != (vxwk_sema4_t *)NULL ) { /* ** Ok... got a control block. Initialize it. */#ifdef DIAG_PRINTFS printf( "\r\nCreating counting semaphore - id %p", semaphore );#endif /* ** Option and Type Flags for semaphore */ semaphore->flags = (opt & SEM_Q_PRIORITY) | COUNTING_SEMA4; /* ** Link the new semaphore into the semaphore list. */ link_smcb( semaphore ); } return( semaphore );}/******************************************************************************* semMCreate - creates a VxWorks mutual exclusion semaphore*****************************************************************************/vxwk_sema4_t * semMCreate( int opt ){ vxwk_sema4_t *semaphore; /* ** First allocate memory for the semaphore control block */ semaphore = new_sema4( 1 ); if ( semaphore != (vxwk_sema4_t *)NULL ) { /* ** Ok... got a control block. Initialize it. */#ifdef DIAG_PRINTFS printf( "\r\nCreating mutex semaphore - id %p", semaphore );#endif /* ** Option and Type Flags for semaphore */ semaphore->flags = (opt & SEM_OPT_MASK) | MUTEX_SEMA4; /* ** Link the new semaphore into the semaphore list. */ link_smcb( semaphore ); } return( semaphore );}/******************************************************************************* semDelete - removes the specified semaphore from the semaphore list and** frees the memory allocated for the semaphore control block.*****************************************************************************/STATUS semDelete( vxwk_sema4_t *semaphore ){#ifdef DIAG_PRINTFS vxwk2pthread_cb_t *our_tcb;#endif STATUS error; error = OK; /* ** First ensure that the specified semaphore exists and that we have ** exclusive access to it. */ pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock, (void *)&(semaphore->sema4_lock)); if ( sema4_valid( semaphore ) ) {#ifdef DIAG_PRINTFS our_tcb = my_tcb(); printf( "\r\ntask @ %p delete semaphore @ %p", our_tcb, semaphore );#endif /* ** Send signal and block while any tasks are still waiting ** on the semaphore */ taskLock(); if ( semaphore->first_susp != (vxwk2pthread_cb_t *)NULL ) {#ifdef DIAG_PRINTFS printf( "\r\nisemDelete - tasks pending on semaphore list @ %p", semaphore->first_susp );#endif /* ** Lock mutex for semaphore delete completion */ pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock, (void *)&(semaphore->smdel_lock) ); pthread_mutex_lock( &(semaphore->smdel_lock) ); /* ** Declare the send type */ semaphore->send_type = KILLD; /* ** Signal the condition variable for the semaphore */ pthread_cond_broadcast( &(semaphore->sema4_send) ); /* ** Unlock the semaphore mutex. */ pthread_mutex_unlock( &(semaphore->sema4_lock) ); /* ** Wait for all pended tasks to receive delete message. ** The last task to receive the message will signal the ** delete-complete condition variable. */ while ( semaphore->first_susp != (vxwk2pthread_cb_t *)NULL ) pthread_cond_wait( &(semaphore->smdel_cplt), &(semaphore->smdel_lock) ); /* ** (No need to unlock the semaphore delete completion mutex.) */ pthread_cleanup_pop( 0 ); } /* ** First remove the semaphore from the semaphore list */ unlink_smcb( semaphore ); /* ** Finally delete the semaphore control block itself; */ ts_free( (void *)semaphore ); taskUnlock(); } else { error = S_objLib_OBJ_ID_ERROR; /* Invalid semaphore specified */ } /* ** Clean up the opening pthread_cleanup_push() */ pthread_cleanup_pop( 0 ); if ( error != OK ) { errno = (int)error; error = ERROR; } return( error );}/******************************************************************************* semFlush - unblocks all tasks waiting on the specified semaphore*****************************************************************************/STATUS semFlush( vxwk_sema4_t *semaphore ){#ifdef DIAG_PRINTFS vxwk2pthread_cb_t *our_tcb;#endif STATUS error; error = OK; /* ** First ensure that the specified semaphore exists and that we have ** exclusive access to it. */ pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock, (void *)&(semaphore->sema4_lock)); if ( sema4_valid( semaphore ) ) { if ( (semaphore->flags & SEM_TYPE_MASK) != MUTEX_SEMA4 ) {#ifdef DIAG_PRINTFS our_tcb = my_tcb(); printf( "\r\ntask @ %p flush semaphore list @ %p", our_tcb, &(semaphore->first_susp) );#endif /* ** Send signal and block while any tasks are still waiting ** on the semaphore */ taskLock(); if ( semaphore->first_susp != (vxwk2pthread_cb_t *)NULL ) { /* ** Lock mutex for semaphore delete completion */ pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock, (void *)&(semaphore->smdel_lock) ); pthread_mutex_lock( &(semaphore->smdel_lock) ); /* ** Declare the send type */ semaphore->send_type = FLUSH; /* ** Signal the condition variable for the semaphore */ pthread_cond_broadcast( &(semaphore->sema4_send) ); /* ** Unlock the semaphore mutex. */ pthread_mutex_unlock( &(semaphore->sema4_lock) ); /* ** Wait for all pended tasks to receive delete message. ** The last task to receive the message will signal the ** delete-complete condition variable. */ while ( semaphore->first_susp != (vxwk2pthread_cb_t *)NULL ) pthread_cond_wait( &(semaphore->smdel_cplt), &(semaphore->smdel_lock) ); /* ** Unlock the semaphore delete completion mutex. */ pthread_mutex_unlock( &(semaphore->smdel_lock) ); pthread_cleanup_pop( 0 ); } taskUnlock(); } else { error = S_semLib_INVALID_OPERATION; /* Flush invalid for mutex */ /* ** Unlock the semaphore mutex. */ pthread_mutex_unlock( &(semaphore->sema4_lock) ); } } else { error = S_objLib_OBJ_ID_ERROR; /* Invalid semaphore specified */ } /* ** Clean up the opening pthread_cleanup_push() */ pthread_cleanup_pop( 0 ); if ( error != OK ) { errno = (int)error; error = ERROR; } return( error );}/******************************************************************************* semGive - releases a VxWorks semaphore token and awakens the first** selected task waiting on the semaphore.*****************************************************************************/STATUS semGive( vxwk_sema4_t *semaphore ){ vxwk2pthread_cb_t *our_tcb; STATUS error; error = OK; /* ** First ensure that the specified semaphore exists and that we have ** exclusive access to it. */ pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock, (void *)&(semaphore->sema4_lock)); if ( sema4_valid( semaphore ) ) { /* ** If semaphore is a mutex, make sure we own it before giving up ** the token. */ our_tcb = my_tcb(); if ( ((semaphore->flags & SEM_TYPE_MASK) == MUTEX_SEMA4) && (semaphore->current_owner != our_tcb) ) { error = S_semLib_INVALID_OPERATION; /* Not owner of mutex */ } else { /* ** Either semaphore isn't a mutex or we currently own the mutex. ** If semaphore is a mutex, recursion level should be > zero. ** In this case, decrement recursion level, and if level == zero ** after decrement, relinquish mutex ownership. */#ifdef DIAG_PRINTFS printf( "\r\nSemaphore list @ %p recursion level = %d", &(semaphore->first_susp), semaphore->recursion_level );#endif if ( semaphore->recursion_level > 0 ) { if ( (--(semaphore->recursion_level)) == 0 ) { semaphore->token_count++; semaphore->current_owner = (vxwk2pthread_cb_t *)NULL; if ( semaphore->flags & SEM_DELETE_SAFE ) /* ** Task was made deletion-safe when mutex acquired... ** Remove deletion safety now. */ taskUnsafe(); if ( semaphore->flags & SEM_INVERSION_SAFE ) { /* ** Task priority may have been boosted during ** ownership of semaphore... ** Restore to original priority now. Call taskLock ** so taskUnlock can be called to restore priority. */#ifdef DIAG_PRINTFS printf( "\r\nRestoring task priority for owner of semaphore list @ %p", &(semaphore->first_susp) );#endif taskLock(); taskUnlock(); } } } else semaphore->token_count++;#ifdef DIAG_PRINTFS printf( "\r\ntask @ %p post to semaphore list @ %p", our_tcb, &(semaphore->first_susp) );#endif if ( semaphore->first_susp != (vxwk2pthread_cb_t *)NULL ) /* ** Signal the condition variable for the semaphore */ pthread_cond_broadcast( &(semaphore->sema4_send) ); } /* ** Unlock the semaphore mutex. */ pthread_mutex_unlock( &(semaphore->sema4_lock) ); } else { error = S_objLib_OBJ_ID_ERROR; /* Invalid semaphore specified */ } /* ** Clean up the opening pthread_cleanup_push() */ pthread_cleanup_pop( 0 ); if ( error != OK ) { errno = (int)error; error = ERROR; } return( error );}/******************************************************************************* waiting_on_sema4 - returns a nonzero result unless a qualifying event** occurs on the specified semaphore which should cause the** pended task to be awakened. The qualifying events** are:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -