/** * Release the mutex. */ void MUTEX_Unlock(Mutex * m) { if (!ReleaseMutex(m->handle)) { TRACE1("ERROR: thr %08lX can't release mutex\n",GetCurrentThreadId()); ASSMSG1("ReleaseMutex() failed, error %lu", GetLastError()); } }
/** * Win32-specific thread proc */ STATIC DWORD WINAPI WIN32_ThreadProc(LPVOID arg) { ThrData * thr = arg; /* This must succeed since we are not allocating any memory */ VERIFY(VECTOR_Init(&thr->cleanupList,0,NULL,NULL)); #ifdef _USE_EXCEPTION_HANDLING __try { #endif /* _USE_EXCEPTION_HANDLING */ ASSERT(TlsGetValue(WIN32_TLS_ThrID) == NULL); VERIFY(TlsSetValue(WIN32_TLS_ThrID, thr)); if (WIN32_TLS_ThrID != TLS_OUT_OF_INDEXES) { ASSERT(TlsGetValue(WIN32_TLS_Data) == NULL); VERIFY(TlsSetValue(WIN32_TLS_Data, thr)); } (*thr->proc)(thr->arg); #ifdef _USE_EXCEPTION_HANDLING } __except(EXCEPTION_EXECUTE_HANDLER) { ASSMSG1("EXCEPTION %08lX in thread proc!",GetExceptionCode()); } #endif /* _USE_EXCEPTION_HANDLING */ THREAD_Cleanup(thr); return 0; }
/** * Reset state to non-signaled. */ Bool EVENT_Reset(Event * e) { if (!ResetEvent(e->handle)) { ASSMSG1("ResetEvent() failed, error %lu", GetLastError()); return False; } return True; }
/** * Notify all waiters and reset state to non-signaled */ Bool EVENT_Pulse(Event * e) { if (!PulseEvent(e->handle)) { ASSMSG1("PulseEvent() failed, error %lu", GetLastError()); return False; } return True; }
/** * Initialize a mutex. Returns False if initialization fails. */ Bool MUTEX_Init(Mutex * m) { m->handle = CreateMutex(NULL, False, NULL); if (!m) { ASSMSG1("CreateMutex() failed, error %lu", GetLastError()); return False; } return True; }
/** * Sets blocking mode for the socket */ Bool SOCKET_Block(Socket s, Bool block) { unsigned long arg = (!block); if (ioctlsocket(s, FIONBIO, &arg) >= 0) { return True; } else { ASSMSG1("ioctl(FIONBIO) failed, err %d",SOCKET_GetLastError()); return False; } }
/** * Wait for event to become signaled. */ WaitState EVENT_Wait(Event * e) { DWORD status = WaitForSingleObject(e->handle, INFINITE); if (status == WAIT_OBJECT_0) { return WAIT_STATE_OK; } else { TRACE1("WaitForSingleObject() status %08lX\n",status); ASSMSG1("WaitForSingleObject() failed, error %d",GetLastError()); return WAIT_STATE_ERROR; } }
/** * Locks the mutex. If mutex is already locked, waits until it becomes * available. Returns True if mutex has been successfully acquired, * False otherwise. */ Bool MUTEX_Lock(Mutex * m) { DWORD status = WaitForSingleObject(m->handle,INFINITE); switch (status) { case WAIT_ABANDONED_0: ASSMSG("Mutex was abandoned!"); /* fall through */ case WAIT_OBJECT_0: return True; case WAIT_TIMEOUT: return False; } TRACE1("WaitForSingleObject() status %08lX\n",status); ASSMSG1("WaitForSingleObject() failed, error %d",GetLastError()); return False; }
/** * This function is invoked when one of the modules has failed to initialize. * Never returns. Prints an error message and calls abort() */ void SLIB_Abort(Str module) { Error(TEXT("Cannot initialize %s module, exiting...\n"),module); ASSMSG1("Cannot initialize %s module",module); /* should panic in kernel mode? */ #ifndef __KERNEL__ # ifdef _WIN32_WCE exit(-1); # else /* !_WIN32_WCE */ abort(); # endif /* !_WIN32_WCE */ #endif /* __KERNEL__ */ }
/** * Wait for event to become signaled. */ WaitState EVENT_TimeWait(Event * e, long ms) { if (ms < 0) { return EVENT_Wait(e); } else { DWORD status = WaitForSingleObject(e->handle, ms); switch (status) { case WAIT_OBJECT_0: return WAIT_STATE_OK; case WAIT_TIMEOUT: return WAIT_STATE_TIMEOUT; } TRACE1("WaitForSingleObject() status %08lX\n",status); ASSMSG1("WaitForSingleObject() failed, error %d",GetLastError()); return WAIT_STATE_ERROR; } }
/** * Destroys thread local variables, sets exit event and dereferences * the thread handle. */ STATIC void THREAD_Cleanup(ThrData* thr) { /* invoke destructors for thread local variables */ int i, n = 1; for (i=0; i<MAX_DESTRUCTOR_ITERATIONS && n > 0; i++) { int k; n = 0; for (k=0; k<VECTOR_Size(&thr->cleanupList); k++) { ThrKey key = VECTOR_Get(&thr->cleanupList, k); void * value = TlsGetValue(key->index); if (value) { TlsSetValue(key->index, NULL); #ifdef _USE_EXCEPTION_HANDLING __try { #endif /* _USE_EXCEPTION_HANDLING */ key->clean(value); ASSERT(!TlsGetValue(key->index)); #ifdef _USE_EXCEPTION_HANDLING } __except(EXCEPTION_EXECUTE_HANDLER) { TlsSetValue(key->index,NULL); ASSMSG1("EXCEPTION %08lX in cleanup proc!", GetExceptionCode()); } #endif /* _USE_EXCEPTION_HANDLING */ n++; } } } ASSERT(i<MAX_DESTRUCTOR_ITERATIONS); /* Dereference ThrKey structures */ while ((n = VECTOR_Size(&thr->cleanupList)) > 0) { ThrKey key = VECTOR_Remove(&thr->cleanupList, n-1); if (InterlockedDecrement(&key->ref) == 0) { ASSERT(key->index == TLS_OUT_OF_INDEXES); MEM_Free(key); } } InterlockedDecrement(&WIN32_ThreadCount); VECTOR_Destroy(&thr->cleanupList); EVENT_Set(&thr->exitEvent); THREAD_Deref(thr); }
/** * Handles ECMT packet coming from MIDP debug plugin */ STATIC void GWENG_MidpHandleEcmtPacket(EcmtGateway* gw, MidpSession* midp, const I8u* pkt, int pktlen) { I8u opcode = pkt[ECMT_MIDP_DEBUG_HEADER_OPCODE_OFFSET]; switch (opcode) { case ECMT_MIDP_DEBUG_OPCODE_SEND: ASSERT(pktlen >= ECMT_MIDP_DEBUG_SEND_MIN_SIZE); if (pktlen >= ECMT_MIDP_DEBUG_SEND_MIN_SIZE) { I32u cid = htonl(*((I32u*)(pkt+ECMT_MIDP_DEBUG_SEND_CID_OFFSET))); I32u seq = htonl(*((I32u*)(pkt+ECMT_MIDP_DEBUG_SEND_SEQ_OFFSET))); MidpConnection* conn = HASH_Get(&midp->connMap,(HashKey)cid); if (conn) { if (conn->inCount == seq) { XRpcData data; XRpcContainer* params; conn->inCount++; /* increment sequence number */ data.ptr = (I8u*)pkt + ECMT_MIDP_DEBUG_SEND_DATA_OFFSET; data.size = pktlen - ECMT_MIDP_DEBUG_SEND_DATA_OFFSET; TRACE4("GW: MidpReceive(%08x.%08x.%u, %d bytes)\n", midp->key.xrpcSession, midp->key.xrpcSid, cid, data.size); DEBUG_ONLY(PRINT_Dump(DEBUG_Trace,data.ptr,data.size,0)); params = GWENG_CreateXRpcParams(midp, ECMTGW_SEI_SEND_SID_PARAM, ECMTGW_SEI_SEND_CID_PARAM, cid); if (params) { XRpcElement* dataElem = _XRPC_CreateBinaryElement( data.ptr, data.size); if (dataElem) { if (XRPC_SetElementName(dataElem, ECMTGW_SEI_SEND_DATA_PARAM) && XRPC_AddElement(params, dataElem)) { /* submit the call */ GWENG_SubmitAsyncCall(midp, ECMTGW_SEI_SEND_METHOD, params); break; } else { XRPC_FreeElement(dataElem); } } XRPC_FreeContainer(params); } /* Terminate connection? That would probably fail too */ } else { TRACE2("GW: SEQ mismatch (expected %u, found %u)\n", conn->inCount, seq); GWENG_MidpResetConn(gw, midp, cid, True, True); } } else { TRACE1("GW: invalid conn id %u from Ecmt\n",cid); GWENG_MidpResetConn(gw, midp, cid, True, False); } } break; case ECMT_MIDP_DEBUG_OPCODE_CLOSE: ASSERT(pktlen == ECMT_MIDP_DEBUG_CLOSE_SIZE); TRACE1("GW: closing session 0x%08lx (via ECMT)\n",midp->sid); GWENG_SubmitAsyncCall(midp, ECMTGW_SEI_CLOSE_METHOD, GWENG_CreateXRpcParams(midp, ECMTGW_SEI_CLOSE_SID_PARAM, NULL, 0)); break; case ECMT_MIDP_DEBUG_OPCODE_RESET: ASSERT(pktlen == ECMT_MIDP_DEBUG_RESET_SIZE); if (pktlen == ECMT_MIDP_DEBUG_RESET_SIZE) { I32u cid = htonl(*((I32u*)(pkt+ECMT_MIDP_DEBUG_RESET_CID_OFFSET))); GWENG_SubmitAsyncCall(midp, ECMTGW_SEI_RESET_METHOD, GWENG_CreateXRpcParams(midp, ECMTGW_SEI_RESET_SID_PARAM, ECMTGW_SEI_RESET_CID_PARAM, cid)); } break; default: ASSMSG1("GW: unexpected opcode %u",opcode); break; } }