/************************************************************** * constructor/destructor **************************************************************/ u_service u_serviceNew( const c_char *uri, c_long timeout, const c_char *name, const c_char *extendedStateName, u_serviceKind kind, v_qos qos) { u_domain domain; v_kernel kk; v_service ks; v_serviceManager sm; u_service s; u_result r; os_result osr; c_bool serviceTermHandlerRequired = FALSE; ks = NULL; r = u_domainOpen(&domain, uri, timeout); if (r != U_RESULT_OK) { OS_REPORT_1(OS_ERROR,"u_serviceNew",0, "Failure to open the kernel - return code %d", r); return NULL; } s = NULL; if (domain != NULL) { r = u_entityWriteClaim(u_entity(domain),(v_entity*)(&kk)); if (r == U_RESULT_OK) { assert(kk); sm = v_getServiceManager(kk); if (sm != NULL) { #ifndef INTEGRITY if (lockPages(kk, name)) { osr = os_procMLockAll(OS_MEMLOCK_CURRENT|OS_MEMLOCK_FUTURE); } else { osr = os_resultSuccess; } if (osr == os_resultSuccess) { #endif switch(kind){ case U_SERVICE_DDSI: case U_SERVICE_DDSIE: case U_SERVICE_NETWORKING: ks = v_service(v_networkingNew(sm, name, extendedStateName, (v_participantQos)qos)); serviceTermHandlerRequired = TRUE; break; case U_SERVICE_DURABILITY: ks = v_service(v_durabilityNew(sm, name, extendedStateName, (v_participantQos)qos)); serviceTermHandlerRequired = TRUE; break; case U_SERVICE_CMSOAP: ks = v_service(v_cmsoapNew(sm, name, extendedStateName, (v_participantQos)qos)); serviceTermHandlerRequired = TRUE; break; case U_SERVICE_RNR: ks = v_service(v_rnrNew(sm, name, extendedStateName, (v_participantQos)qos)); serviceTermHandlerRequired = TRUE; break; case U_SERVICE_DBMSCONNECT: case U_SERVICE_INCOGNITO: ks = v_serviceNew(sm, name, extendedStateName, (v_participantQos)qos, NULL); serviceTermHandlerRequired = TRUE; break; case U_SERVICE_SPLICED: break; default: OS_REPORT(OS_WARNING,"u_serviceNew",0, "Failed to start an unknown service kind"); break; } } else { OS_REPORT(OS_ERROR,"u_serviceNew",0, "Failed to lock memory pages for current process"); } /* Install the service signal handlers if spliced is not within this * same process. i.e. only do this if each service is in its own * process so signal handlers won't interfere */ if (serviceTermHandlerRequired && !u_splicedInProcess()) { os_procSetTerminationHandler(serviceTermHandler); } #ifndef INTEGRITY } else { OS_REPORT(OS_ERROR,"u_serviceNew",0, "Failed to retrieve the Service Manager"); } #endif if (ks != NULL) { s = u_entityAlloc(NULL,u_service,ks,TRUE); r = u_serviceInit(s, kind, domain); if (r != U_RESULT_OK) { OS_REPORT_1(OS_ERROR,"u_serviceNew",0, "Failed to initialize service: %s", name); u_serviceFree(s); s = NULL; } callbackService = s; (void) os_signalHandlerSetExceptionCallback(u__serviceExceptionCallbackWrapper); } else { OS_REPORT(OS_WARNING,"u_serviceNew",0, "Failed to retrieve the Service Manager"); } r = u_entityRelease(u_entity(domain)); } } return s; }
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; }