/****************************************************************************** * * INTEL Corporation Proprietary Information * Copyright (c) 1994, 1995, 1996 Intel Corporation. * * This listing is supplied under the terms of a license agreement * with INTEL Corporation and may not be used, copied, nor disclosed * except in accordance with the terms of that agreement. * *****************************************************************************/ /****************************************************************************** * * $Workfile: h245sys.c $ * $Revision: 1.8 $ * $Modtime: Mar 04 1997 17:38:08 $ * $Log: S:/STURGEON/SRC/H245/SRC/VCS/h245sys.c_v $ * * Rev 1.8 Mar 04 1997 17:51:56 tomitowx * process detach fix * * Rev 1.7 24 Jan 1997 19:40:48 SBELL1 * upgraded to oss 4.2 * * Rev 1.6 21 Jun 1996 18:53:22 unknown * Changed InstUnlock() to fix shutdown re-entrancy bug. * * Rev 1.5 10 Jun 1996 16:59:34 EHOWARDX * Moved init/shutdown of submodules to CreateInstance/InstanceUnlock. * * Rev 1.3 04 Jun 1996 13:57:02 EHOWARDX * Fixed Release build warnings. * * Rev 1.2 28 May 1996 14:25:38 EHOWARDX * Tel Aviv update. * * Rev 1.1 16 May 1996 13:51:26 EHOWARDX * Fixed minor timer/lock count interaction bugs. * * Rev 1.0 09 May 1996 21:06:28 EHOWARDX * Initial revision. * * Rev 1.25 09 May 1996 19:39:04 EHOWARDX * Changed includes. * * Rev 1.24 29 Apr 1996 12:56:58 EHOWARDX * Made timers more accurate & made them use fewer resources. * Note: This is windows-specific. * * Rev 1.18.1.2 15 Apr 1996 15:12:34 EHOWARDX * Kludge to not call H245DeInitTimer() when last timer is stopped. * This will have to be revisited later. * * Rev 1.18.1.1 02 Apr 1996 22:06:22 EHOWARDX * No change. * * Rev 1.18.1.0 27 Mar 1996 16:44:18 EHOWARDX * Changed timer code; decided it would work better if H245InitTimer() * actually got called. * * Rev 1.18 26 Mar 1996 09:46:08 cjutzi * * - ok.. Added Enter&Leave&Init&Delete Critical Sections for Ring 0 * * Rev 1.17 25 Mar 1996 18:30:14 helgebax * - removed H245ASSERT . * . * * * Rev 1.16 25 Mar 1996 18:10:48 cjutzi * * - well .. I broke the build.. had to put back what I did.. * * * Rev 1.15 25 Mar 1996 17:50:02 cjutzi * * - removed critical section.. back step * * Rev 1.14 25 Mar 1996 17:20:34 cjutzi * * - added Remesh's EnterCritical section definitions.. to use * oil layer. * * Rev 1.13 18 Mar 1996 12:44:40 cjutzi * * - put NULL as callback at shutdown * * Rev 1.12 18 Mar 1996 12:41:32 cjutzi * - added timer code for multiple timers queue.. * * Rev 1.11 12 Mar 1996 15:48:46 cjutzi * * - added InstanceTbl Lock * * Rev 1.10 07 Mar 1996 22:47:34 dabrown1 * * Modifications required for ring0/ring3 compatibilty * * Rev 1.9 02 Mar 1996 22:14:52 DABROWN1 * * removed h245_bzero and h245_bcopy (use memset and memcpy instead) * * Rev 1.8 26 Feb 1996 17:10:56 cjutzi * * - removed h245sys.h * * Rev 1.7 26 Feb 1996 12:42:26 cjutzi * * - added bcopy * * Rev 1.6 21 Feb 1996 16:23:38 DABROWN1 * * removed h245_ASN1free * modified malloc and free to save buffer size internally * * Rev 1.5 13 Feb 1996 14:54:12 DABROWN1 * * removed trace/debug files to new debug directory * * Rev 1.4 09 Feb 1996 15:45:08 cjutzi * - added h245trace * - added h245Assert * *****************************************************************************/ #ifndef STRICT #define STRICT #endif #include "precomp.h" #include "h245api.h" #include "h245com.h" #include "h245sys.x" /************************************************************************** * * Instance Table/Instance Lock implementation * **************************************************************************/ CRITICAL_SECTION InstanceCreateLock = {0}; CRITICAL_SECTION InstanceLocks[MAXINST] = {0}; struct InstanceStruct * InstanceTable[MAXINST] = {0}; struct InstanceStruct *InstanceCreate(DWORD dwPhysId, H245_CONFIG_T Configuration) { register struct InstanceStruct *pInstance; register unsigned int uIndex; unsigned int uFirst = (dwPhysId - 1) % MAXINST; HRESULT lError; // Allocate new instance pInstance = (struct InstanceStruct *)MemAlloc(sizeof(*pInstance)); if (pInstance == NULL) { H245TRACE(dwPhysId,1,"InstanceCreate -> Instance malloc failed"); return NULL; } // Make sure no one is trying to simultaneously add same physical Id // (I know this is a stretch...) EnterCriticalSection(&InstanceCreateLock); // Check if instance corresponding to dwPhysId already exists uIndex = uFirst; // Hash start index into table do { // Avoid entering critical section for unused instances if (InstanceTable[uIndex]) { EnterCriticalSection(&InstanceLocks[uIndex]); if (InstanceTable[uIndex] && InstanceTable[uIndex]->dwPhysId == dwPhysId) { LeaveCriticalSection(&InstanceLocks[uIndex]); LeaveCriticalSection(&InstanceCreateLock); MemFree(pInstance); H245TRACE(dwPhysId,1,"InstanceCreate -> Physical Id already in use"); return NULL; } LeaveCriticalSection(&InstanceLocks[uIndex]); } uIndex = (uIndex + 1) % MAXINST; } while (uIndex != uFirst); // Find empty slot for new instance uIndex = uFirst; // Hash start index into table do { // Avoid entering critical section for used instances if (InstanceTable[uIndex] == NULL) { EnterCriticalSection(&InstanceLocks[uIndex]); if (InstanceTable[uIndex] == NULL) { // Initialize new instance // Once the new instance is added to the instance table, // we can relinquish the CreateInstanceLock InstanceTable[uIndex] = pInstance; LeaveCriticalSection(&InstanceCreateLock); memset(pInstance, 0, sizeof(*pInstance)); pInstance->dwPhysId = dwPhysId; pInstance->dwInst = uIndex + 1; pInstance->LockCount = 1; /* API Subsystem Initialization */ pInstance->Configuration = Configuration; lError = api_init(pInstance); if (lError != H245_ERROR_OK) { InstanceTable[uIndex] = NULL; LeaveCriticalSection(&InstanceLocks[uIndex]); MemFree(pInstance); H245TRACE(dwPhysId,1,"InstanceCreate -> api_init failed"); return NULL; } /* Send Receive Subsystem Initialization */ lError = sendRcvInit(pInstance); if (lError != H245_ERROR_OK) { api_deinit(pInstance); InstanceTable[uIndex] = NULL; LeaveCriticalSection(&InstanceLocks[uIndex]); MemFree(pInstance); H245TRACE(dwPhysId,1,"InstanceCreate -> sendRcvInit failed"); return NULL; } /* State Machine Subsystem Initialization */ lError = Fsm_init(pInstance); if (lError != H245_ERROR_OK) { sendRcvShutdown(pInstance); api_deinit(pInstance); InstanceTable[uIndex] = NULL; LeaveCriticalSection(&InstanceLocks[uIndex]); MemFree(pInstance); H245TRACE(dwPhysId,1,"InstanceCreate -> Fsm_init failed"); return NULL; } H245TRACE(pInstance->dwInst,9,"InstanceCreate: ++LockCount=%d", pInstance->LockCount); return pInstance; // Return locked instance } LeaveCriticalSection(&InstanceLocks[uIndex]); } uIndex = (uIndex + 1) % MAXINST; } while (uIndex != uFirst); LeaveCriticalSection(&InstanceCreateLock); MemFree(pInstance); H245TRACE(dwPhysId,1,"InstanceCreate -> Too many instances"); return NULL; } // InstanceCreate() struct InstanceStruct *InstanceLock(register H245_INST_T dwInst) { if (--dwInst >= MAXINST) { H245TRACE(dwInst+1,1,"InstanceLock -> Invalid instance"); return NULL; } if (!InstanceTable[dwInst]) { H245TRACE(dwInst+1,1,"InstanceLock -> Invalid instance"); return NULL; } // Lock instance, then see if it still exists EnterCriticalSection(&InstanceLocks[dwInst]); if (InstanceTable[dwInst]) { InstanceTable[dwInst]->LockCount++; H245TRACE(dwInst+1,9,"InstanceLock: ++LockCount=%d", InstanceTable[dwInst]->LockCount); return InstanceTable[dwInst]; // Return locked instance } LeaveCriticalSection(&InstanceLocks[dwInst]); H245TRACE(dwInst+1,1,"InstanceLock -> Invalid instance"); return NULL; } // InstanceLock() int InstanceUnlock(struct InstanceStruct *pInstance) { register H245_INST_T dwInst = pInstance->dwInst - 1; if (dwInst >= MAXINST || InstanceTable[dwInst] != pInstance) { H245TRACE(pInstance->dwInst,1,"InstanceUnlock -> Invalid instance"); return -1; } if (pInstance->fDelete && pInstance->LockCount == 1) { H245TRACE(pInstance->dwInst,9,"InstanceUnlock: deleting instance"); pInstance->fDelete = FALSE; // InstanceUnlock will be re-entered from H245WS callback! Fsm_shutdown(pInstance); sendRcvShutdown(pInstance); api_deinit(pInstance); InstanceTable[dwInst] = NULL; LeaveCriticalSection(&InstanceLocks[dwInst]); while (pInstance->pTimerList) { register TimerList_T *pTimer = pInstance->pTimerList; pInstance->pTimerList = pTimer->pNext; H245TRACE(pInstance->dwInst,1,"InstanceUnlock: deleting timer"); MemFree(pTimer); } MemFree(pInstance); } else { pInstance->LockCount--; H245TRACE(pInstance->dwInst,9,"InstanceUnlock: --LockCount=%d", pInstance->LockCount); LeaveCriticalSection(&InstanceLocks[dwInst]); } return 0; } // InstanceUnlock() int InstanceDelete(struct InstanceStruct *pInstance) { H245TRACE(pInstance->dwInst,9,"InstanceDelete"); pInstance->fDelete = TRUE; return InstanceUnlock(pInstance); } // InstanceDelete() int InstanceUnlock_ProcessDetach(struct InstanceStruct *pInstance, BOOL fProcessDetach) { register H245_INST_T dwInst = pInstance->dwInst - 1; if (dwInst >= MAXINST || InstanceTable[dwInst] != pInstance) { H245TRACE(pInstance->dwInst,1,"InstanceUnlock -> Invalid instance"); return -1; } if (pInstance->fDelete && pInstance->LockCount == 1) { H245TRACE(pInstance->dwInst,9,"InstanceUnlock: deleting instance"); pInstance->fDelete = FALSE; // InstanceUnlock will be re-entered from H245WS callback! Fsm_shutdown(pInstance); //sendRcvShutdown(pInstance); sendRcvShutdown_ProcessDetach(pInstance,fProcessDetach); api_deinit(pInstance); InstanceTable[dwInst] = NULL; LeaveCriticalSection(&InstanceLocks[dwInst]); while (pInstance->pTimerList) { register TimerList_T *pTimer = pInstance->pTimerList; pInstance->pTimerList = pTimer->pNext; H245TRACE(pInstance->dwInst,1,"InstanceUnlock: deleting timer"); MemFree(pTimer); } MemFree(pInstance); } else { pInstance->LockCount--; H245TRACE(pInstance->dwInst,9,"InstanceUnlock: --LockCount=%d", pInstance->LockCount); LeaveCriticalSection(&InstanceLocks[dwInst]); } return 0; } // InstanceUnlock_ProcessDetach() /***************************************************************************** * * TYPE: TIMER STUFF * *****************************************************************************/ CRITICAL_SECTION TimerLock = {0}; static int TimerInited = 0; #ifndef _IA_SPOX_ static UINT_PTR H245TimerId; #endif /***************************************************************************** * * TYPE: Global System * * PROCEDURE: H245TimerTick - ticks every 1000ms * * DESCRIPTION: * * RETURN: * *****************************************************************************/ void H245TimerTick (void) { DWORD dwTickCount = GetTickCount(); unsigned int uIndex; register struct InstanceStruct *pInstance; register TimerList_T *pTimer; H245TRACE(0,9,"H245TimerTick <-"); if (0 != TimerInited) { for (uIndex = 0; uIndex < MAXINST; ++uIndex) { // Avoid entering critical section for unused instances if (InstanceTable[uIndex]) { pInstance = InstanceLock(uIndex + 1); if (pInstance) { while (pInstance->pTimerList && (pInstance->pTimerList->dwAlarm - dwTickCount) >= 0x80000000) { pTimer = pInstance->pTimerList; pInstance->pTimerList = pTimer->pNext; EnterCriticalSection(&TimerLock); if (--TimerInited == 0) { #ifdef _IA_SPOX_ H223_RegisterTimerCallBack((H223TIMERCB)NULL); #else KillTimer (NULL, H245TimerId); #endif } LeaveCriticalSection(&TimerLock); if (pTimer->pfnCallBack) { // TBD - what if pContext is no longer valid? (pTimer->pfnCallBack)(pInstance, (DWORD_PTR)pTimer, pTimer->pContext); } MemFree (pTimer); } // while InstanceUnlock(pInstance); } // if } // if } // for } H245TRACE(0,9,"H245TimerTick ->"); } // TimerTick() /***************************************************************************** * * TYPE: Global System * * PROCEDURE: H245TimerProc - FOR WINDOWS Ring 3 only * * DESCRIPTION: * * RETURN: * *****************************************************************************/ #ifndef _IA_SPOX_ void CALLBACK H245TimerProc(HWND hwHwnd, UINT uiMessg, UINT_PTR idTimer, DWORD dwTime) { if (idTimer == H245TimerId) H245TimerTick (); } #endif /***************************************************************************** * * TYPE: Global System * * PROCEDURE: H245StartTimer * * DESCRIPTION: * * RETURN: * *****************************************************************************/ DWORD_PTR H245StartTimer (struct InstanceStruct * pInstance, void * pContext, H245TIMERCALLBACK pfnCallBack, DWORD dwTicks) { TimerList_T *pNew; TimerList_T *pLook; TimerList_T *pList; if (!pfnCallBack) { H245TRACE(pInstance->dwInst,1,"H245StartTimer: pfnCallBack == NULL"); return 0; } pNew = (TimerList_T *)MemAlloc(sizeof(TimerList_T)); if (pNew == NULL) { H245TRACE(pInstance->dwInst,1,"H245StartTimer: memory allocation failed"); return 0; } pNew->pNext = NULL; pNew->pContext = pContext; pNew->pfnCallBack = pfnCallBack; pNew->dwAlarm = GetTickCount() + dwTicks; EnterCriticalSection(&TimerLock); if (++TimerInited == 1) { #ifdef _IA_SPOX_ H223_RegisterTimerCallBack((H223TIMERCB)H245TimerTick); #else H245TimerId = SetTimer ((HWND)NULL, (UINT)0, (UINT)1000, H245TimerProc); #endif } LeaveCriticalSection(&TimerLock); /* as you traverse the list.. subtract the delta off the new one */ /* and link it in.. this list is a list of delta's off the time */ /* out that is linked in front of it.. so subtract as you go */ for (pList = NULL, pLook = pInstance->pTimerList; pLook && (pLook->dwAlarm - pNew->dwAlarm) >= 0x80000000; pList = pLook, pLook = pLook->pNext); /* link it in the list */ pNew->pNext = pLook; if (pList) { // Insert new timer after pList and before pLook pList->pNext = pNew; } else { // Insert new timer at front of list pInstance->pTimerList = pNew; } return (DWORD_PTR)pNew; } /***************************************************************************** * * TYPE: Global System * * PROCEDURE: H245StopTimer * * DESCRIPTION: * * RETURN: * *****************************************************************************/ DWORD H245StopTimer(struct InstanceStruct *pInstance, DWORD_PTR dwTimerId) { TimerList_T *pTimer = (TimerList_T *)dwTimerId; TimerList_T *pLook; TimerList_T *pList; ASSERT(TimerInited != 0); EnterCriticalSection(&TimerLock); if (--TimerInited == 0) { #ifdef _IA_SPOX_ H223_RegisterTimerCallBack((H223TIMERCB)NULL); #else KillTimer (NULL, H245TimerId); #endif } LeaveCriticalSection(&TimerLock); if (pInstance->pTimerList == NULL) { H245TRACE(pInstance->dwInst,1,"H245StopTimer: timer list NULL"); return TRUE; } if (pTimer == pInstance->pTimerList) { pInstance->pTimerList = pTimer->pNext; MemFree (pTimer); return FALSE; } pList = pInstance->pTimerList; pLook = pList->pNext; while (pLook && pLook != pTimer) { pList = pLook; pLook = pLook->pNext; } /* if the timer exists.. */ if (pLook == NULL) { H245TRACE(pInstance->dwInst,1,"H245StopTimer: pTimer not in timer list"); return TRUE; } pList->pNext = pTimer->pNext; MemFree (pTimer); return FALSE; } #ifdef _IA_SPOX_ PUBLIC RESULT InitializeCriticalSection(CRITICAL_SECTION * phLock) { return OIL_CreateLock(phLock); } PUBLIC RESULT EnterCriticalSection(CRITICAL_SECTION * phLock) { return OIL_AcquireLock(*phLock); } PUBLIC RESULT LeaveCriticalSection(CRITICAL_SECTION * phLock) { return OIL_ReleaseLock(*phLock); } PUBLIC RESULT DeleteCriticalSection(CRITICAL_SECTION * phLock) { return OIL_DeleteLock(*phLock); } #endif