📄 _pthreadlib.c
字号:
{ strncpy(name, pAttr->threadAttrName, NAME_MAX - 1); name[NAME_MAX - 1] = EOS; } /* * Determine the priority. This is also based on the inheritsched * attribute; we handled the scheduling policy inheritance above. */ if (pAttr->threadAttrInheritsched == PTHREAD_INHERIT_SCHED) { taskPriorityGet(taskIdSelf(), &pMyThread->priority); /* Convert to POSIX format */ pMyThread->priority = PX_VX_PRI_CONV (priNumMode, pMyThread->priority); } else pMyThread->priority = pAttr->threadAttrSchedparam.sched_priority; if (!(pMyThread->flags & STACK_PASSED_IN)) { if (!(pTcb = (WIND_TCB *)taskCreat(name, PX_VX_PRI_CONV(priNumMode, pMyThread->priority), VX_FP_TASK, stacksize, (FUNCPTR) wrapperFunc, (int)start_routine, (int)arg, 0, 0, 0, 0, 0, 0, 0, 0))) { if (pMyThread->flags & JOINABLE) semDelete(pMyThread->exitJoinSemId); semDelete(pMyThread->mutexSemId); free(pMyThread); return (EAGAIN); } } else { /* * Since we have a passed in stack pointer, we need to do what * taskCreat() does, and put the TCB on the stack. */#if (_STACK_DIR == _STACK_GROWS_DOWN) /* * A portion of the very top of the stack is clobbered with a * FREE_BLOCK in the objFree() associated with taskDestroy(). * There is no adverse consequence of this, and is thus not * accounted for. * * Given we set the stacksize above there is no need to check that * there is enough room on the stack for the tcb. There will be */ stackaddr = (char *) STACK_ROUND_DOWN (stackaddr + stacksize - sizeof(WIND_TCB)); pTcb = (WIND_TCB *) stackaddr; /* * We must adjust the stacksize as well. However, because of the * STACK_ROUND_DOWN the cleanest way to calculate this is to compare * the original stack address to the new stack address. */ stacksize = ((UINT) stackaddr - (UINT) pAttr->threadAttrStackaddr);#else /* _STACK_GROWS_UP */#warning "Exception stack growing up not tested" /* * To protect a portion of the WIND_TCB that is clobbered with a * FREE_BLOCK in the objFree() associated with taskDestroy(), * we goose the base of tcb by 16 bytes. * * Given we set the stacksize above there is no need to check that * there is enough room on the stack for the tcb. There will be */ pTcb = (WIND_TCB *) (stackaddr + 16); stackaddr = (char *) STACK_ROUND_UP (stackaddr + 16 + sizeof(WIND_TCB)); /* * We must adjust the stacksize as well. However, because of the * STACK_ROUND_UP the cleanest way to calculate this is to compare * the original stack address to the new stack address before * subtracting from the stacksize. */ stacksize = (stacksize - ((UINT) stackaddr - (UINT) pAttr->threadAttrStackaddr));#endif if (taskInit(pTcb, name, PX_VX_PRI_CONV(priNumMode, pMyThread->priority), (VX_FP_TASK | VX_NO_STACK_FILL), stackaddr, stacksize, (FUNCPTR) wrapperFunc, (int)start_routine, (int)arg, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR) { if (pMyThread->flags & JOINABLE) semDelete(pMyThread->exitJoinSemId); semDelete(pMyThread->mutexSemId); free(pMyThread); return (EAGAIN); } } pTcb->pPthread = pMyThread; pMyThread->privateData = NULL; pMyThread->handlerBase = NULL; pMyThread->cancelstate = PTHREAD_CANCEL_ENABLE; pMyThread->canceltype = PTHREAD_CANCEL_DEFERRED; pMyThread->cancelrequest = 0; pMyThread->taskId = (int)pTcb; pMyThread->flags |= VALID; taskActivate((int)pTcb); *pThread = (pthread_t)pMyThread; return (_RETURN_PTHREAD_SUCCESS); }/* * Section 18 - Thread Cancellation *//********************************************************************************* _pthreadSetCancelType - set cancellation type for calling thread** This is the kernel support routine for pthread_setcanceltype(). It is here* so that kernel libraries (such as the I/O system code) can make calls to it.** The public API, pthread_setcanceltype(), is simply a call to this routine.** RETURNS: On success zero; on failure a non-zero error code.** ERRNOS: EINVAL** SEE ALSO: pthread_setcanceltype(),*/int _pthreadSetCancelType ( int type, /* new type */ int *oldtype /* old type (out) */ ) { internalPthread * pThread = MY_PTHREAD; sigset_t set; sigset_t * pset = &set; if (!pthreadLibInited || !pThread) return (0);#if 0 self_become_pthread();#endif if (type != PTHREAD_CANCEL_ASYNCHRONOUS && type != PTHREAD_CANCEL_DEFERRED) { return (EINVAL); } sigemptyset(pset); sigaddset(pset, SIGCANCEL); sigprocmask(SIG_BLOCK, pset, NULL); CANCEL_LOCK(pThread); /* If the oldtype is required, save it now */ if (oldtype != NULL) *oldtype = pThread->canceltype; pThread->canceltype = type; CANCEL_UNLOCK(pThread); sigprocmask(SIG_UNBLOCK, pset, NULL); return (0); }/********************************************************************************* deleteHook -** Catch all for abnormally terminating pthreads, and those threads that* don't call pthread_exit to terminate.** RETURNS:** NOMANUAL*/LOCAL void deleteHook ( WIND_TCB *pTcb ) { if ((pthreadDeleteTaskEntry == NULL) || /* not initialised */ (pTcb->pPthread == NULL)) /* task not a thread */ return; pthreadDeleteTaskEntry (pTcb->pPthread); }/********************************************************************************* _pthreadSemOwnerGet - return the owner of a WIND semaphore** Returns the owner task ID of a semaphore. This is only valid for mutex and* binary semaphores, but no attempt is made by the routine to check this. It is* the caller's responsibility to ensure that it is only called for correct* type of semaphore.** RETURNS: task ID of owner, NULL if not owned, or ERROR if the semaphore ID* is invalid.** SEE ALSO: _pthreadSemStateGet()** NOMANUAL*/ int _pthreadSemOwnerGet ( SEM_ID semId ) { int owner; int level = intLock (); /* LOCK INTERRUPTS */ if (OBJ_VERIFY (semId, semClassId) != OK) { intUnlock (level); /* UNLOCK INTERRUPTS */ return (ERROR); } owner = (int) semId->semOwner; intUnlock (level); return owner; } /********************************************************************************* _pthreadSemStateGet - return the state of a semaphore** Returns the state of a semaphore. This will be zero or non-zero for mutex and* binary semaphores, meaning empty/not owned and full/owned respectively. For* counting semaphores the current count will be returned.** RETURNS: current state of semaphore** SEE ALSO: _pthreadSemOwnerGet()** NOMANUAL*/ int _pthreadSemStateGet ( SEM_ID semId ) { int state; int level = intLock (); /* LOCK INTERRUPTS */ if (OBJ_VERIFY (semId, semClassId) != OK) { intUnlock (level); /* UNLOCK INTERRUPTS */ return (ERROR); } if ((semId->semType == (UINT8) SEM_TYPE_BINARY) || (semId->semType == (UINT8) SEM_TYPE_MUTEX)) { state = (semId->semOwner == NULL) ? 0 : 1; } else if (semId->semType == (UINT8) SEM_TYPE_COUNTING) { state = semId->state.count; } else { /* "Old" semaphore, or just invalid */ state = ERROR; } intUnlock (level); return state; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -