📄 pthreadlib.c
字号:
{ int taskIdList[1]; if (!pCond || pCond->condValid != TRUE) return (EINVAL); INIT_COND(pCond); /* get number of blocked tasks and give the semaphore for each */ while (semInfo(pCond->condSemId, taskIdList, 1)) { if (semGive(pCond->condSemId) == ERROR) return (EINVAL); /* internal error */ } return (_RETURN_PTHREAD_SUCCESS); }/********************************************************************************* pthread_cond_wait - wait for a condition variable (POSIX)** This function atomically releases the mutex <pMutex> and waits for the* condition variable <pCond> to be signalled by another thread. The mutex* must be locked by the calling thread when pthread_cond_wait() is called; if* it is not then this function returns an error ('EINVAL').** Before returning to the calling thread, pthread_cond_wait() re-acquires the* mutex.** RETURNS: On success zero; on failure a non-zero error code.** ERRNOS: 'EINVAL'** SEE ALSO:* pthread_condattr_init(),* pthread_condattr_destroy(),* pthread_cond_broadcast(),* pthread_cond_destroy(),* pthread_cond_init(),* pthread_cond_signal(),* pthread_cond_timedwait()*/int pthread_cond_wait ( pthread_cond_t *pCond, /* condition variable */ pthread_mutex_t *pMutex /* POSIX mutex */ ) { WIND_TCB *mutexTcb; int savtype; if (!pCond || pCond->condValid != TRUE) return (EINVAL); INIT_COND(pCond); if (!pMutex) return (EINVAL); /* * make sure that if anyone else is blocked on this condition variable * that the same mutex was used to guard it. Also verify that mutex is * locked and that we are the owner */ if (((pCond->condMutex != NULL) && (pCond->condMutex != pMutex)) || (!(mutexTcb = (WIND_TCB *) _pthreadSemOwnerGet (pMutex->mutexSemId))) || (mutexTcb != taskIdCurrent)) { return (EINVAL); } else pCond->condMutex = pMutex; pCond->condRefCount++; pCond->condMutex->mutexCondRefCount++; if (semGive(pMutex->mutexSemId) == ERROR) { return (EINVAL); } if (MY_PTHREAD) MY_PTHREAD->cvcond = pCond; pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &savtype); if (semTake(pCond->condSemId, WAIT_FOREVER) == ERROR) { pthread_setcanceltype(savtype, NULL); return (EINVAL); /* internal error */ } pthread_setcanceltype(savtype, NULL); if (MY_PTHREAD) MY_PTHREAD->cvcond = NULL; if (semTake(pMutex->mutexSemId, WAIT_FOREVER) == ERROR) return (EINVAL); pCond->condMutex->mutexCondRefCount--; if (--pCond->condRefCount == 0) pCond->condMutex = NULL; return (_RETURN_PTHREAD_SUCCESS); }/********************************************************************************* pthread_cond_timedwait - wait for a condition variable with a timeout (POSIX)** This function atomically releases the mutex <pMutex> and waits for another* thread to signal the condition variable <pCond>. As with pthread_cond_wait(),* the mutex must be locked by the calling thread when pthread_cond_timedwait()* is called.** If the condition variable is signalled before the system time reaches the* time specified by <pAbsTime>, then the mutex is re-acquired and the calling* thread unblocked.** If the system time reaches or exceeds the time specified by <pAbsTime> before* the condition is signalled, then the mutex is re-acquired, the thread* unblocked and ETIMEDOUT returned.** NOTE* The timeout is specified as an absolute value of the system clock in a* <timespec> structure (see clock_gettime() for more information). This is* different from most VxWorks timeouts which are specified in ticks relative* to the current time.** RETURNS: On success zero; on failure a non-zero error code.** ERRNOS: 'EINVAL', 'ETIMEDOUT'** SEE ALSO:* pthread_condattr_init(),* pthread_condattr_destroy(),* pthread_cond_broadcast(),* pthread_cond_destroy(),* pthread_cond_init(),* pthread_cond_signal(),* pthread_cond_wait()*/int pthread_cond_timedwait ( pthread_cond_t *pCond, /* condition variable */ pthread_mutex_t *pMutex, /* POSIX mutex */ const struct timespec *pAbstime /* timeout time */ ) { int nTicks; struct timespec tmp; struct timespec now; WIND_TCB * mutexTcb; int savtype; if (!pCond || pCond->condValid != TRUE) return (EINVAL); INIT_COND(pCond); if (!pMutex || !pAbstime || !TV_VALID(*pAbstime)) { return (EINVAL); } /* * make sure that if anyone else is blocked on this condition variable * that the same mutex was used to guard it. Also verify that mutex is * locked and that we are the owner */ if (((pCond->condMutex != NULL) && (pCond->condMutex != pMutex)) || (!(mutexTcb = (WIND_TCB *) _pthreadSemOwnerGet (pMutex->mutexSemId))) || (mutexTcb != taskIdCurrent)) { return (EINVAL); } else pCond->condMutex = pMutex; pCond->condMutex->mutexCondRefCount++; pCond->condRefCount++; pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &savtype); /* * convert to number of ticks (relative time) or return if time has * already passed */ if (clock_gettime(CLOCK_REALTIME, &now) != 0) { pthread_setcanceltype(savtype, NULL); return (errno); } TV_SET(tmp, *pAbstime); TV_SUB(tmp, now); if (TV_GT(tmp, *pAbstime)) /* overflow, e.g. too late */ { /* drop and reacquire mutex as per POSIX */ if (semGive(pMutex->mutexSemId) == ERROR) { pthread_setcanceltype(savtype, NULL); return (EINVAL); /* internal error */ } if (semTake(pMutex->mutexSemId, WAIT_FOREVER) == ERROR) { pthread_setcanceltype(savtype, NULL); return (EINVAL); /* internal error */ } pthread_setcanceltype(savtype, NULL); return (ETIMEDOUT); } TV_CONVERT_TO_TICK(nTicks, tmp); if (semGive(pMutex->mutexSemId) == ERROR) { pthread_setcanceltype(savtype, NULL); return (EINVAL); } if (MY_PTHREAD) MY_PTHREAD->cvcond = pCond; if (semTake(pCond->condSemId, nTicks) == ERROR) { if (MY_PTHREAD) MY_PTHREAD->cvcond = NULL; pthread_setcanceltype(savtype, NULL); if (semTake(pMutex->mutexSemId, WAIT_FOREVER) == ERROR) { return (EINVAL); } pCond->condMutex->mutexCondRefCount--; if (--pCond->condRefCount == 0) pCond->condMutex = NULL; return (ETIMEDOUT); } pthread_setcanceltype(savtype, NULL); if (semTake(pMutex->mutexSemId, WAIT_FOREVER) == ERROR) { return (EINVAL); } if (MY_PTHREAD) MY_PTHREAD->cvcond = NULL; pCond->condMutex->mutexCondRefCount--; if (--pCond->condRefCount == 0) pCond->condMutex = NULL; return (_RETURN_PTHREAD_SUCCESS); }/* * Section 13.5 - Thread Scheduling *//********************************************************************************* pthread_attr_setscope - set contention scope for thread attributes (POSIX)** For VxWorks PTHREAD_SCOPE_SYSTEM is the only supported contention scope.* Any other value passed to this function will result in 'EINVAL' being* returned.** RETURNS: On success zero; on failure a non-zero error code.** ERRNOS: 'EINVAL'** SEE ALSO:* pthread_attr_getscope(),* pthread_attr_init()*/int pthread_attr_setscope ( pthread_attr_t *pAttr, /* thread attributes object */ int contentionScope /* new contention scope */ ) { if (!pAttr || pAttr->threadAttrStatus != PTHREAD_INITIALIZED || (contentionScope != PTHREAD_SCOPE_PROCESS && contentionScope != PTHREAD_SCOPE_SYSTEM)) { return (EINVAL); }#if 0 /* * Restriction on VxWorks: no multiprocessor, so all threads * compete for resources, PTHREAD_SCOPE_SYSTEM always in effect */ pAttr->threadAttrContentionscope = contentionScope;#endif return (_RETURN_PTHREAD_SUCCESS); }/********************************************************************************* pthread_attr_getscope - get contention scope from thread attributes (POSIX)** Reads the current contention scope setting from a thread attributes object.* For VxWorks this is always PTHREAD_SCOPE_SYSTEM. If the thread attributes* object is uninitialized then 'EINVAL' will be returned. The contention* scope is returned in the location pointed to by <pContentionScope>.** RETURNS: On success zero; on failure a non-zero error code.** ERRNOS: 'EINVAL'** SEE ALSO:* pthread_attr_init(),* pthread_attr_setscope()*/int pthread_attr_getscope ( const pthread_attr_t *pAttr, /* thread attributes object */ int *pContentionScope /* contention scope (out) */ ) { if (!pAttr || pAttr->threadAttrStatus != PTHREAD_INITIALIZED) return (EINVAL);#if 0 *pContentionScope = pAttr->threadAttrContentionscope;#else /* * Restriction on VxWorks: no multiprocessor, so all threads * compete for resources, PTHREAD_SCOPE_SYSTEM always in effect */ *pContentionScope = PTHREAD_SCOPE_SYSTEM;#endif return (_RETURN_PTHREAD_SUCCESS);}/********************************************************************************* pthread_attr_setinheritsched - set inheritsched attribute in thread attribute object (POSIX)** This routine sets the scheduling inheritance to be used when creating a* thread with the thread attributes object specified by <pAttr>.** Possible values are:* .iP PTHREAD_INHERIT_SCHED 4* Inherit scheduling parameters from parent thread.* .iP PTHREAD_EXPLICIT_SCHED* Use explicitly provided scheduling parameters (i.e. those specified in the* thread attributes object).* .LP** RETURNS: On success zero; on failure a non-zero error code.** ERRNOS: 'EINVAL'** SEE ALSO:* pthread_attr_getinheritsched(),* pthread_attr_init(),* pthread_attr_setschedparam(),* pthread_attr_setschedpolicy()*/int pthread_attr_setinheritsched ( pthread_attr_t *pAttr, /* thread attributes object */ int inheritsched /* inheritance mode */ ) { if (!pAttr || pAttr->threadAttrStatus != PTHREAD_INITIALIZED || (inheritsched != PTHREAD_INHERIT_SCHED && inheritsched != PTHREAD_EXPLICIT_SCHED)) { return (EINVAL); } pAttr->threadAttrInheritsched = inheritsched; return (_RETURN_PTHREAD_SUCCESS); }/********************************************************************************* pthread_attr_getinheritsched - get current value if inheritsched attribute in thread attributes object (POSIX)** This routine gets the scheduling inheritance value from the thread* attributes object <pAttr>.** Possible values are:* .iP PTHREAD_INHERIT_SCHED 4* Inherit scheduling parameters from parent thread.* .iP PTHREAD_EXPLICIT_SCHED* Use explicitly provided scheduling parameters (i.e. those specified in the* thread attributes object).* .LP** RETURNS: On success zero; on failure a non-zero error code.** ERRNOS: 'EINVAL'** SEE ALSO:* pthread_attr_init(),* pthread_attr_getschedparam(),* pthread_attr_getschedpolicy()* pthread_attr_setinheritsched()*/int pthread_attr_getinheritsched ( const pthread_attr_t *pAttr, /* thread attributes object */ int *pInheritsched /* inheritance mode (out) */ ) { if (!pAttr || pAttr->threadAttrStatus != PTHREAD_INITIALIZED) return (EINVAL); *pInheritsched = pAttr->threadAttrInheritsched; return (_RETURN_PTHREAD_SUCCESS); }/********************************************************************************* pthread_attr_setschedpolicy - set schedpolicy attribute in thread attributes object (POSIX)** Select the thread scheduling policy. The default scheduling policy is* to inherit the current system setting. Unlike the POSIX model,* scheduling policies under VxWorks are global. If a scheduling policy is* being set explicitly, the PTHREAD_EXPLICIT_SCHED mode must be set (see* pthread_attr_setinheritsched() for information), and the selected scheduling* policy must match the global scheduling policy in place at* the time; failure to do so will result in pthread_create() failing with* the non-POSIX error 'ENOTTY'.** POSIX defines the following policies:* .iP SCHED_RR 4* Realtime, round-robin scheduling.* .iP SCHED_FIFO* Realtime, first-in first-out scheduling.* .iP SCHED_OTHER
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -