os_result os_procUnregisterThread() { os_result rv = os_resultSuccess; os_threadSetValidity(os_threadIdSelf(), thread_ValExit); return (rv); }
c_syncResult c_condTimedWait ( c_cond *cnd, c_mutex *mtx, const c_time time) { os_result result; os_time t; t.tv_sec = time.seconds; t.tv_nsec = time.nanoseconds; #ifdef NDEBUG result = os_condTimedWait(cnd,mtx,&t); #else mtx->owner = OS_THREAD_ID_NONE; result = os_condTimedWait(cnd,&mtx->mtx,&t); mtx->owner = os_threadIdSelf(); #endif #if 1 /* TODO: Remove temporary workaround to prevent spinning * applications and come up with an actual fix. */ wait_on_error(result); #endif if((result != os_resultSuccess) && (result != os_resultTimeout)){ OS_REPORT_1(OS_ERROR, "c_condWait", 0, "os_condWait failed; os_result = %d.", result); assert((result == os_resultSuccess) || (result == os_resultTimeout)); } return result; }
/* This method will lock the user-layer and return the reference to the user-layer object if successful. * If this method returns NULL then the user-layer is either not initialized or * the process is detaching (process termination). */ static u_user u__userLock(void) { u_user u; os_result r = os_resultFail; u = u_user(user); if (u) { r = os_mutexLock(&u->mutex); if (r != os_resultSuccess) { /* The mutex is not valid so apparently the user-layer is either * destroyed or in process of destruction. */ u = NULL; } else if ((os_threadIdToInteger(u->detachThreadId) != 0) && (os_threadIdToInteger(u->detachThreadId) != os_threadIdToInteger(os_threadIdSelf()))) { /* Another thread is busy destroying the user-layer or the user- * layer is already destroyed. No access is allowed (anymore). * The user-layer object will be unlocked and will return null. */ os_mutexUnlock(&u->mutex); u = NULL; } } else { /* The user-layer is not created or destroyed i.e. non existent, therefore return null. */ OS_REPORT(OS_ERROR, "User Layer", 0, "User layer not initialized"); } return u; }
c_syncResult c_mutexLock ( c_mutex *mtx) { os_result result; #ifdef NDEBUG result = os_mutexLock(mtx); #else result = os_mutexLock(&mtx->mtx); if ( result == os_resultSuccess ) { mtx->owner = os_threadIdSelf(); } #endif #if 1 /* TODO: Remove temporary workaround to prevent spinning * applications and come up with an actual fix. */ wait_on_error(result); #endif if(result != os_resultSuccess) { OS_REPORT_1(OS_ERROR, "c_mutexLock", 0, "os_mutexLock failed; os_result = %d.", result); assert(result == os_resultSuccess); } return result; }
/** \brief Terminate the process and return the status * the the parent process * * \b os_procExit terminates the process by calling \b exit. */ void os_procExit( os_exitStatus status) { os_procContextData currentProcContext = (os_procContextData)readTLSVarSelf(procContextData); os_procLocalExit(status); os_threadDeleteTaskVar(taskIdSelf(), os_threadIdSelf()); os_procDeleteTaskVar(taskIdSelf(), "task", currentProcContext); exit(status); }
static void u__userDetach( void) { u_user u; u_domain domain; u_result r; c_long i; u = u__userLock(); if (u) { /* Disable access to user-layer for all other threads except for this thread. * Any following user access from other threads is gracefully * aborted. */ u->detachThreadId = os_threadIdSelf(); /* Unlock the user-layer * Part of following code requires to unlock the user object * This is allowed now all other threads will abort when * trying to claim the lock */ u__userUnlock(); for (i = 1; (i <= u->domainCount); i++) { domain = u->domainList[i].domain; if (domain) { r = u_domainDetachParticipants(domain); if (r != U_RESULT_OK) { OS_REPORT_2(OS_ERROR, "user::u_user::u_userDetach", 0, "Operation u_domainDetachParticipants(0x%x) failed." OS_REPORT_NL "result = %s", domain, u_resultImage(r)); } else { r = u_domainFree(domain); if (r != U_RESULT_OK) { OS_REPORT_2(OS_ERROR, "user::u_user::u_userDetach", 0, "Operation u_domainFree(0x%x) failed." OS_REPORT_NL "result = %s", domain, u_resultImage(r)); } } } } /* user = NULL; * ES: This was set to NULL here by RP, but this causes errors later on * when u_userExit is performed. So commented this out here. As I can * not explain why we would need to set it to NULL here. */ } }
os_result os_procRegisterThread( os_procContextData process_procContextData) { os_result rv; if (os_iterInsert(process_procContextData->procThreadList, (void *)os_threadIdSelf()) != NULL) { rv = os_resultSuccess; } else { rv = os_resultFail; } return (rv); }
/* This method will unlock the user-layer. */ static void u__userUnlock(void) { u_user u; u = u_user(user); if (u) { if ((os_threadIdToInteger(u->detachThreadId) == 0) || (os_threadIdToInteger(u->detachThreadId) == os_threadIdToInteger(os_threadIdSelf()))) { os_mutexUnlock(&u->mutex); } } }
c_syncResult c_lockTryWrite ( c_lock *lck) { os_result result; #ifdef NDEBUG result = os_rwlockTryWrite(lck); #else result = os_rwlockTryWrite(&lck->lck); lck->owner = os_threadIdSelf(); #endif if ((result != os_resultSuccess) && (result != os_resultBusy)) { OS_REPORT_1(OS_ERROR, "c_lockTryWrite", 0, "os_rwlockTryWrite failed; os_result = %d.", result); assert((result == os_resultSuccess) || (result == os_resultBusy)); } return result; }
c_syncResult c_mutexUnlock ( c_mutex *mtx) { os_result result; #ifdef NDEBUG result = os_mutexUnlock(mtx); #else assert( os_threadIdToInteger(mtx->owner) == os_threadIdToInteger(os_threadIdSelf()) ); mtx->owner = OS_THREAD_ID_NONE; result = os_mutexUnlock(&mtx->mtx); #endif if(result != os_resultSuccess){ OS_REPORT_1(OS_ERROR, "c_mutexUnlock", 0, "os_mutexUnlock failed; os_result = %d.", result); assert(result == os_resultSuccess); } return result; }
c_syncResult c_mutexTryLock ( c_mutex *mtx) { os_result result; #ifdef NDEBUG result = os_mutexTryLock(mtx); #else result = os_mutexTryLock(&mtx->mtx); if ( result == os_resultSuccess ) { mtx->owner = os_threadIdSelf(); } #endif if ((result != os_resultSuccess) && (result != os_resultBusy)) { OS_REPORT_1(OS_ERROR, "c_mutexTryLock", 0, "os_mutexTryLock failed; os_result = %d.", result); assert((result == os_resultSuccess) || (result == os_resultBusy)); } return result; }
/** * Returns if the current thread is the signalHandlerThread. * * @remarks Do not perform any signal-handling context unsafe operations in this * function. * * @return OS_TRUE if the current thread is the signalHandlerThread, or * OS_FALSE if it's not. */ static os_boolean inSignalHandlerThread (void) { os_int match; os_signalHandler _this = signalHandlerObj; #ifndef NDEBUG /* Assert preconditions (regular assert may trigger this action, so it * is not used here). */ if (_this == NULL) { const char panicmsg[] = "Assertion failed: _this != NULL in " __FILE__ ":inSignalHandlerThread\n"; panic(panicmsg, sizeof(panicmsg) - 1); /* This line will not be reached anymore */ } #endif match = os_threadIdToInteger (_this->threadId) == os_threadIdToInteger (os_threadIdSelf ()); return match ? OS_TRUE : OS_FALSE; }
static os_result os_procWrapper( os_procContextData process_procContextData, char *executable_file, os_int32 *startRoutine, const char *arguments, TASK_ID parent, os_sem_t *blockParent) { int taskid; os_int32 status = os_resultSuccess; os_int32 routine_status = -1; os_int32 (*this_startRoutine)(const char *); #if ( _WRS_VXWORKS_MAJOR > 6 ) || ( _WRS_VXWORKS_MAJOR == 6 && _WRS_VXWORKS_MINOR > 8 ) envPrivateCreate(taskIdSelf(), parent); os_sem_post(blockParent); #endif taskid = taskIdSelf(); os_procSetTaskId(process_procContextData, taskid); /* create & set context variable for the task */ status = os_procAddTaskVar(taskid, executable_file, process_procContextData, 0); if (status == os_resultSuccess) { status = os_threadNew(process_procContextData->procName); } if (status == os_resultSuccess) { this_startRoutine = (os_int32 *)startRoutine; routine_status = this_startRoutine(arguments); os_procLocalExit(OS_EXIT_SUCCESS); os_threadDeleteTaskVar(taskid, os_threadIdSelf()); os_procDeleteTaskVar(taskid, executable_file, process_procContextData); os_procSetExitValue(process_procContextData, routine_status); } #if ( _WRS_VXWORKS_MAJOR > 6 ) || ( _WRS_VXWORKS_MAJOR > 6 && _WRS_VXWORKS_MINOR > 8 ) envPrivateDestroy(taskIdSelf()); #endif return (status); }
static void os__signalHandlerThreadStop( os_signalHandler _this) { struct sig_context info; void *thread_result; assert(_this); memset (&info, 0, sizeof(info)); info.info.si_signo = SIGNAL_THREAD_STOP; if (write(_this->pipeIn[1], &info, sizeof(info)) < 0) { /* ignore result */ } /* When the signalHandlerThread itself is the exiting thread (this can happen * when an exit call is done in a signalHandler installed by a customer for * example), we should not invoke os_threadWaitExit but just let this call * return immediately. */ if (os_threadIdSelf() != _this->threadId ) { (void) os_threadWaitExit(_this->threadId, &thread_result); } }
void os_signalHandlerFree( void) { #if !defined INTEGRITY && !defined VXWORKS_RTP void *thread_result; int i, r; os_signalHandler _this = signalHandlerObj; struct sig_context info; if (isSignallingSafe(0) && _this) { for (i=0; i<lengthof(exceptions); i++) { const int sig = exceptions[i]; r = os_sigactionSet(sig, &old_signalHandler[sig], NULL); if (r<0) { OS_REPORT_3(OS_ERROR, "os_signalHandlerFree", 0, "os_sigactionSet(%d, 0x%x, NULL) failed, result = %d", sig, &old_signalHandler[sig], r); assert(OS_FALSE); } } memset (&info, 0, sizeof(info)); info.info.si_signo = SIGNAL_THREAD_STOP; r = write(_this->pipeIn[1], &info, sizeof(info)); /* when signalhandler is the exiting thread itself, this can happen when an exit call is done in the signalhandler of the customer * do not call os_threadWaitExit but just let this thread run out of its main function */ if (os_threadIdSelf() != _this->threadId ) { os_threadWaitExit(_this->threadId, &thread_result); } close(_this->pipeIn[0]); close(_this->pipeIn[1]); close(_this->pipeOut[0]); close(_this->pipeOut[1]); os_free(_this); signalHandlerObj = NULL; } #endif }
c_syncResult c_lockWrite ( c_lock *lck) { os_result result; #ifdef NDEBUG result = os_rwlockWrite(lck); #else result = os_rwlockWrite(&lck->lck); lck->owner = os_threadIdSelf(); #endif #if 1 /* TODO: Remove temporary workaround to prevent spinning * applications and come up with an actual fix. */ wait_on_error(result); #endif if(result != os_resultSuccess){ OS_REPORT_1(OS_ERROR, "c_lockWrite", 0, "os_rwlockWrite failed; os_result = %d.", result); assert(result == os_resultSuccess); } return result; }
/** * This is the signal-handler routine that is performed in case of a signal. It * distinguishes: * - synchronous: * - exceptions * - asynchronous: * - exceptions * - quits (termination requests). * * @remarks Do not perform any signal-handling context unsafe operations in this * function. */ static void signalHandler( int sig, siginfo_t *info, void* uap) { struct sig_context sync; struct sig_context sigInfo; os_signalHandlerCallbackInfo *cbInfo = os__signalHandlerGetCallbackInfo(); /* info can be NULL on Solaris */ if (info == NULL) { /* Pretend that it was an SI_USER signal. */ memset(&sigInfo.info, 0, sizeof(siginfo_t)); sigInfo.info.si_signo = sig; sigInfo.info.si_code = SI_USER; sigInfo.info.si_pid = getpid(); sigInfo.info.si_uid = getuid(); } else { sigInfo.info = *info; } sigInfo.ThreadIdSignalRaised = os_threadIdToInteger(os_threadIdSelf()); sigInfo.domainId = os_reportGetDomain(); #ifdef OS_HAS_UCONTEXT_T sigInfo.uc = *(ucontext_t *)uap; #endif /* WARNING: Don't do any async/signalling-unsafe calls here (so refrain from * using OS_REPORT_X and the like). */ if (sigismember(&exceptionsMask, sig) == 1 && sigInfo.info.si_code != SI_USER){ os_sigaction *xo; if (inSignalHandlerThread()) { /* The signalHandlerThread caught an exception (synchronous) * itself. The fact that the signalHandlerThread caught an * exception means there is a bug in the error handling code. */ const char panicmsg[] = "FATAL ERROR: Synchronously trapped signal in signalHandlerThread\n"; panic(panicmsg, sizeof(panicmsg) - 1); /* This line will not be reached anymore */ } /* Grab the Mutex for the ExceptionHandler stack and hold it during * the processing of the exception. This way you avoid handlers * being added or removed right in between writing the exception * context into the pipe and the signal handler thread reading it * and handling it from the pipe. Also you avoid another signal from * another thread overwriting our context. * To visualize the the duration for this mutex claim, the resulting * handler code has been placed in its own (indented) scope. */ { os_mutexLock(&cbInfo->exceptionMtx); /* Obtain the context of the thread that called the signalHandler. * This information will be needed by the callback invoked by the * signalHandlerThread, to decide what kind of action needs to * be taken. */ os__signalHandlerExceptionGetThreadContextCallbackInvoke(cbInfo); /* We have an exception (synchronous) here. The assumption is * that exception don't occur in middleware-code, so we can * synchronously call the signalHandlerThread in order to detach user- * layer from all Domains (kernels). */ signalHandlerThreadNotify(sigInfo, &sync); os_mutexUnlock(&cbInfo->exceptionMtx); } /* BEWARE: This may be an interleaved handling of an exception, so use * sync from now on instead of sigInfo.*/ /* Reset the original signal-handler. If the exception was synchronous, * running out of this handler will regenerate the signal, which will * then be handled by the original signal-handler. Otherwise it needs * to be re-raised. */ xo = &old_signalHandler[sync.info.si_signo]; os_sigactionSet(sync.info.si_signo, xo, NULL); /* Positive values are reserved for kernel-generated signals, i.e., * actual synchronous hard errors. The rest are 'soft' errors and thus * need to be re-raised. */ if(sigInfo.info.si_code <= 0){ raise(sig); } } else { /* Pass signal to signal-handler thread for asynchronous handling */ os_uint32 index = pa_inc32_nv(&cbInfo->exitRequestInsertionIndex) % EXIT_REQUEST_BUFFER_SIZE; os__signalHandlerExitRequestGetThreadContextCallbackInvoke(cbInfo, index); signalHandlerThreadNotify(sigInfo, NULL); } }
void u_userExit( void) { u_user u; u_domain domain; os_result mr = os_resultFail; u_result r; c_long i; u = u__userLock(); if (u) { /* Disable access to user-layer for all other threads except for this thread. * Any following user access from other threads is gracefully * aborted. */ u->detachThreadId = os_threadIdSelf(); /* Unlock the user-layer * Part of following code requires to unlock the user object * This is allowed now all other threads will abort when * trying to claim the lock */ u__userUnlock(); for (i = 1; (i <= u->domainCount); i++) { domain = u->domainList[i].domain; if (domain) { r = u_domainDetachParticipants(domain); if (r != U_RESULT_OK) { OS_REPORT_2(OS_ERROR, "user::u_user::u_userExit", 0, "Operation u_domainDetachParticipants(0x%x) failed." OS_REPORT_NL "result = %s", domain, u_resultImage(r)); } else { r = u_domainFree(domain); if (r != U_RESULT_OK) { OS_REPORT_2(OS_ERROR, "user::u_user::u_userExit", 0, "Operation u_domainFree(0x%x) failed." OS_REPORT_NL "result = %s", domain, u_resultImage(r)); } } } } user = NULL; /* Destroy the user-layer mutex */ mr = os_mutexDestroy(&u->mutex); if(mr != os_resultSuccess){ OS_REPORT_1(OS_ERROR, "user::u_user::u_userExit",0, "Operation os_mutexDestroy(0x%x) failed:" OS_REPORT_NL "os_result == %d.", mr); } /* Free the user-object */ os_free(u); } /* Even if access to the user layer is denied, we still need to cleanup * the signal handler, which includes waiting for the threads to exit * the DDS database */ os_signalHandlerFree(); /* De-init the OS-abstraction layer */ os_osExit(); }