/* We need this on windows to make sure the main thread of MFC applications * calls os_osInit(). */ BOOL WINAPI DllMain( HINSTANCE hinstDLL, /* handle to DLL module */ DWORD fdwReason, /* reason for calling function */ LPVOID lpReserved ) /* reserved */ { /* Perform actions based on the reason for calling.*/ switch( fdwReason ) { case DLL_PROCESS_ATTACH: /* Initialize once for each new process. * Return FALSE to fail DLL load. */ os_osInit(); break; case DLL_THREAD_ATTACH: /* Do thread-specific initialization. */ break; case DLL_THREAD_DETACH: /* Do thread-specific cleanup. */ break; case DLL_PROCESS_DETACH: /* Perform any necessary cleanup. */ os_osExit(); break; } return TRUE; /* Successful DLL_PROCESS_ATTACH.*/ }
os__osExit( void) { os_osExit(); }
u_result u_userInitialise( void) { u_user u; u_result rm = U_RESULT_OK; os_mutexAttr mutexAttr; os_uint32 initCount; void* initUser; os_result osResult; os_signalHandlerExitRequestCallback exitRequestCallback; os_signalHandlerExceptionCallback exceptionCallback; initCount = pa_increment(&_ospl_userInitCount); /* If initCount == 0 then an overflow has occurred. * This can only realistically happen when u_userDetach() * is called more often than u_userInitialize(). */ assert(initCount != 0); os_osInit(); if (initCount == 1) { /* Will start allocating the object, so it should currently be empty. */ assert(user == NULL); /* Use indirection, as user != NULL is a precondition for user-layer * functions, so make sure it only holds true when the user-layer is * initialized. */ initUser = os_malloc(sizeof(C_STRUCT(u_user))); if (initUser == NULL) { /* Initialization failed, so decrement the initialization counter. */ pa_decrement(&_ospl_userInitCount); os_osExit(); OS_REPORT(OS_ERROR, "u_userInitialise", 0, "Allocation of user admin failed: out of memory."); rm = U_RESULT_OUT_OF_MEMORY; } else { u = u_user(initUser); os_mutexAttrInit(&mutexAttr); mutexAttr.scopeAttr = OS_SCOPE_PRIVATE; os_mutexInit(&u->mutex,&mutexAttr); osResult = os_signalHandlerNew(); if(osResult != os_resultSuccess) { /* Initialization did not succeed, undo increment and return error */ initCount = pa_decrement(&_ospl_userInitCount); OS_REPORT(OS_ERROR, "u_userInitialise", 0, "Failed to create the signal handler. No proper signal handling can be performed."); rm = U_RESULT_INTERNAL_ERROR; } else { exitRequestCallback = os_signalHandlerSetExitRequestCallback(u__userExitRequestCallbackWrapper); if(exitRequestCallback && exitRequestCallback != u__userExitRequestCallbackWrapper) { initCount = pa_decrement(&_ospl_userInitCount); OS_REPORT(OS_ERROR, "u_userInitialise", 0, "Replaced an exit request callback on the signal handler while this was not expected."); rm = U_RESULT_INTERNAL_ERROR; } if(rm == U_RESULT_OK){ exceptionCallback = os_signalHandlerSetExceptionCallback(u__userExceptionCallbackWrapper); if(exceptionCallback && exceptionCallback != u__userExceptionCallbackWrapper) { initCount = pa_decrement(&_ospl_userInitCount); OS_REPORT(OS_ERROR, "u_userInitialise", 0, "Replaced an exception callback on the signal handler while this was not expected."); rm = U_RESULT_INTERNAL_ERROR; } } if(rm == U_RESULT_OK) { u->domainCount = 0; u->protectCount = 0; u->detachThreadId = OS_THREAD_ID_NONE; /* This will mark the user-layer initialized */ user = initUser; } } } } else { if(user == NULL){ os_time sleep = {0, 100000}; /* 100ms */ /* Another thread is currently initializing the user-layer. Since * user != NULL is a precondition for calls after u_userInitialise(), * a sleep is performed, to ensure that (if succeeded) successive * user-layer calls will also actually pass.*/ os_nanoSleep(sleep); } if(user == NULL){ /* Initialization did not succeed, undo increment and return error */ initCount = pa_decrement(&_ospl_userInitCount); OS_REPORT_1(OS_ERROR,"u_userInitialise",0, "Internal error: User-layer should be initialized " "(initCount = %d), but user == NULL (waited 100ms).", initCount); rm = U_RESULT_INTERNAL_ERROR; } } return rm; }
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(); }