📄 linuxucos.c
字号:
OS_FLAG_GRP *OSFlagCreate( OS_FLAGS flags, INT8U *err ){ int i, perr; struct pthread_flag *pflag; // lock the OSFlagTbl list perr = pthread_mutex_lock( &osflagtbl_mutex ); ASSERT( perr == 0 ); // get a free OS_FLAG_GRP and initialize it for( i=0 ; i<OS_MAX_FLAGS ; i++ ) { if( lnxOSFlagTbl[i].OSFlagType == 0 ) { lnxOSFlagTbl[i].OSFlagType = OS_EVENT_TYPE_FLAG; lnxOSFlagTbl[i].OSFlagFlags = flags; pflag = (struct pthread_flag *)malloc(sizeof(struct pthread_flag)); if( !pflag ) { goto fail; } memcpy( &(pflag->mutex), &blank_mutex, sizeof(pthread_mutex_t)); memcpy( &(pflag->cond), &blank_cond, sizeof(pthread_cond_t)); // "borrow" the task list pointer lnxOSFlagTbl[i].OSFlagWaitList = (void *)pflag; // unlock the OSFlagTbl list perr = pthread_mutex_unlock( &osflagtbl_mutex ); ASSERT( perr == 0 ); *err = OS_NO_ERR; return &lnxOSFlagTbl[i]; } }fail: // unlock the OSFlagTbl list perr = pthread_mutex_unlock( &osflagtbl_mutex ); ASSERT( perr == 0 ); *err = OS_FLAG_GRP_DEPLETED; return NULL;}#if 0OS_FLAG_GRP *OSFlagDel( OS_FLAG_GRP *pgrp, INT8U opt, INT8U *err ){ if( pgrp == NULL ) { *err = OS_FLAG_INVALID_PGRP; return 0; } if( pgrp->OSFlagType != OS_EVENT_TYPE_FLAG ) { *err = OS_ERR_EVENT_TYPE; return 0; } return 0;}#endifOS_FLAGS OSFlagPend( OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U wait_type, INT16U timeout, INT8U *err ){ OS_FLAGS flags_cur; /* timeout == 0 => wait forever */ flags_cur = OS_FlagTest( pgrp, flags, wait_type, timeout, err ); return flags_cur;}OS_FLAGS OSFlagPost( OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U opt, INT8U *err ){ OS_FLAGS flags_cur; int perr; struct pthread_flag *pflag; if( pgrp == NULL ) { *err = OS_FLAG_INVALID_PGRP; return 0; } if( pgrp->OSFlagType != OS_EVENT_TYPE_FLAG ) { *err = OS_ERR_EVENT_TYPE; return 0; } // test the flags pflag = (struct pthread_flag *)pgrp->OSFlagWaitList; // lock the pthread condition perr = pthread_mutex_lock( &(pflag->mutex) ); ASSERT( perr == 0 ); switch (opt) { case OS_FLAG_CLR: pgrp->OSFlagFlags &= ~flags; /* Clear the flags specified in the group */ break; case OS_FLAG_SET: pgrp->OSFlagFlags |= flags; /* Set the flags specified in the group */ break; default: ASSERT(0); *err = OS_FLAG_INVALID_OPT; flags_cur = 0; goto fail; } // wake everyone up; the waiting thread(s) are responsible for // testing the condition (not terribly efficient but works ok // -- when in doubt use brute force) perr = pthread_cond_broadcast( &(pflag->cond) ); ASSERT( perr == 0 ); *err = OS_NO_ERR; flags_cur = pgrp->OSFlagFlags; fail: // unlock the pthread condition perr = pthread_mutex_unlock( &(pflag->mutex) ); ASSERT( perr == 0 ); return flags_cur;}// *****************//// Message Queues// // *****************struct ptrmsg { long mtype; void *ptr;};void *OSQAccept(OS_EVENT *pevent){ int err, msgid; struct ptrmsg ipcmsg; void *ptr; msgid = (int)pevent->OSEventPtr; // get a message err = msgrcv( msgid, (void *)&ipcmsg, sizeof(void *), 0, IPC_NOWAIT ); if( err < 0 ) { if( errno == ENOMSG ) { // would have timed out -- nothing to receive return NULL; } // shouldn't happen PERROR( "msgrcv() failed in OSQAccept()" ); return NULL; } // at this point, we got something ptr = ipcmsg.ptr; return ptr;}OS_EVENT *OSQCreate(void **start, INT16U size){ int msgid; OS_EVENT *evt; evt = get_free_event(OS_EVENT_TYPE_Q); if( evt == NULL ) { return NULL; } msgid = msgget( IPC_PRIVATE, 0600 ); if( msgid == -1 ) { // shouldn't happen PERROR( "msgget() failed in OSQCreate()" ); evt->OSEventType = OS_EVENT_TYPE_UNUSED; return NULL; } evt->OSEventPtr = (void *)msgid; return evt;}OS_EVENT *OSQDel(OS_EVENT *pevent, INT8U opt, INT8U *err){ int msgid; if( pevent->OSEventType != OS_EVENT_TYPE_Q ) { *err = OS_ERR_EVENT_TYPE; return NULL; } msgid = (int)pevent->OSEventPtr; if( msgctl( msgid, IPC_RMID, NULL ) ) { // shouldn't happen PERROR( "msgctl() failed OSQDel()" ); *err = OS_ERR_INTERNAL; return NULL; } // free this event structure pevent->OSEventType = OS_EVENT_TYPE_UNUSED; *err = OS_NO_ERR; return NULL;}void *OSQPend(OS_EVENT *pevent, INT16U timeout, INT8U *err){ INT16U next_sleep; void *ptr; // see OSMutexPend() for comments about polling while( 1 ) { if( (ptr=OSQAccept( pevent )) != NULL ) { *err = OS_NO_ERR; return ptr; } next_sleep = min(timeout,POLL_DELAY); OSTimeDly( next_sleep ); timeout -= next_sleep; if( timeout == 0 ) { // failed to claim *err = OS_TIMEOUT; break; } } return NULL;}INT8U OSQPost(OS_EVENT *pevent, void *msg ){ int msgid; struct ptrmsg ipcmsg; if( pevent->OSEventType != OS_EVENT_TYPE_Q ) { return OS_ERR_EVENT_TYPE; } msgid = (int)pevent->OSEventPtr; ipcmsg.mtype = 1; ipcmsg.ptr = msg; if( msgsnd( msgid, (void *)&ipcmsg, sizeof(void *), IPC_NOWAIT ) < 0 ) { // shouldn't happen PERROR( "msgsnd() failed in OSQPost" ); return OS_ERR_INTERNAL; } return OS_NO_ERR;}// *****************//// Semaphore (Mutex)//// *****************INT8U OSMutexAccept(OS_EVENT *pevent, INT8U *err){ int semid; // if the mutex is available, claim it and return 1 // otherwise, return 0 // errors are returned through *err if( pevent == NULL ) { *err = OS_ERR_PEVENT_NULL; return 0; } if( pevent->OSEventType != OS_EVENT_TYPE_SEM ) { *err = OS_ERR_EVENT_TYPE; return 0; } semid = (int)pevent->OSEventPtr; // attempt to claim the semaphore with no wait if( semop( semid, &sem_claim, 1 ) < 0 ) { if( errno == EAGAIN ) { // semaphore busy *err = OS_NO_ERR; return 0; } // shouldn't happen // FIXME -- perhaps detect EINTR return from semop() PERROR( "semop() failed in OSMutexAccept()" ); *err = OS_ERR_INTERNAL; return 0; } // we claimed the semaphore! *err = OS_NO_ERR; return 1;}OS_EVENT *OSMutexCreate(INT8U prio, INT8U *err){ int semid; OS_EVENT *evt; evt = get_free_event( OS_EVENT_TYPE_SEM ); if( evt == NULL ) { *err = OS_ERR_PEVENT_NULL; return NULL; } semid = semget( IPC_PRIVATE, 1, 0600 ); if( semid < 0 ) { // shouldn't happen PERROR( "semget() failed in OSMutexCreate()" ); *err = OS_ERR_INTERNAL; return NULL; } if( semctl( semid, 0, SETVAL, 1) < 0 ) { // shouldn't happen PERROR( "semctl() failed in OSMutexCreate()" ); *err = OS_ERR_INTERNAL; return NULL; } *err = OS_NO_ERR; evt->OSEventPtr = (void *)semid; return evt;}OS_EVENT *OSMutexDel(OS_EVENT *pevent, INT8U opt, INT8U *err){ int semid; if( pevent == NULL ) { *err = OS_ERR_PEVENT_NULL; return 0; } if( pevent->OSEventType != OS_EVENT_TYPE_SEM ) { *err = OS_ERR_EVENT_TYPE; return NULL; } semid = (int)pevent->OSEventPtr; if( semctl( semid, 0, IPC_RMID, 0 ) < 0 ) { // shouldn't happen *err = OS_ERR_INTERNAL; return NULL; } // free this event structure pevent->OSEventType = OS_EVENT_TYPE_UNUSED; *err = OS_NO_ERR; return NULL;}void OSMutexPend(OS_EVENT *pevent, INT16U timeout, INT8U *err){ INT16U next_sleep; // AFAIK there is no such thing as a timeout on a // SysV IPC. I could use a SIGALRM to wake up the // sleeping semop() but I'm nervous about interfering // with an application's possible use of that signal. // // So let's just poll and be happy. // // FIXME -- need way to sleep with timeout on semop() while( 1 ) { if( OSMutexAccept( pevent, err ) ) { return; } next_sleep = min(timeout,POLL_DELAY); OSTimeDly( next_sleep ); timeout -= next_sleep; if( timeout == 0 ) { // failed to claim *err = OS_TIMEOUT; break; } }}INT8U OSMutexPost(OS_EVENT *pevent){ int semid; if( pevent == NULL ) { return OS_ERR_PEVENT_NULL; } if( pevent->OSEventType != OS_EVENT_TYPE_SEM ) { return OS_ERR_EVENT_TYPE; } semid = (int)pevent->OSEventPtr; // attempt to release the semaphore with no wait if( semop( semid, &sem_release, 1 ) < 0 ) { // shouldn't happen PERROR( "semop() failed in OSMutexPost()" ); return OS_ERR_INTERNAL; } return OS_NO_ERR;}// *****************//// Task functions//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -