//-------------------------------------------------------------------------------------- // FUNCTION: RC_SHM_BUFFER_START //-------------------------------------------------------------------------------------- // return (virtual) start address of off-chip shared memory //-------------------------------------------------------------------------------------- t_vcharp RC_SHM_BUFFER_START(){ #ifdef SCC t_vcharp retval; SHMalloc(&retval); //SHMalloc() is in SCC_API.c return retval; #else return RC_shm_buffer; #endif }
/*++ Function: EventWaitOn Check if the event is signaled. If not signaled place the current thread to the list of waiting thread. This function is called by WaitXXXX functions when it's time to wait on a Event. The caller is responsible for blocking the thread, this function does not wait on the event. This function set the last error, if an error occured. Parameters: IN hEvent: handle of the event checked for the signaled state. SHMPTR wait_state : shared memory pointer to waiting thread's wait state returns WAITON_CODE value (see thread.h) --*/ int EventWaitOn( IN HANDLE hEvent, SHMPTR wait_state) { Event *pEvent; GLOBAL_EVENT_SYSTEM_OBJECT *pEventInfo; int ret; ThreadWaitingList *pWaitingThread; SHMPTR shmpWaitingThread; pEvent = (Event *) HMGRLockHandle2(hEvent, HOBJ_EVENT); SHMLock(); if ( pEvent == NULL ) { SetLastError(ERROR_INVALID_HANDLE); ERROR("Invalid event handle %p\n", hEvent); SHMRelease(); return WOC_ERROR; } pEventInfo = (GLOBAL_EVENT_SYSTEM_OBJECT*) SHMPTR_TO_PTR(pEvent->info); if (pEventInfo == NULL) { SetLastError(ERROR_INTERNAL_ERROR); ASSERT("Invalid shared memory pointer\n"); SHMRelease(); HMGRUnlockHandle(hEvent,&pEvent->objHeader); return WOC_ERROR; } if (pEventInfo->state) { DWORD *pAwakenState; /* try to flag the thread as awakened, don't add it to the list if it already was. (this happens if an object is signaled while WFMO is still calling WaitOn()) */ pAwakenState = SHMPTR_TO_PTR(wait_state); if(!THREADInterlockedAwaken(pAwakenState,FALSE)) { TRACE("thread is already awake; not waiting on it\n"); ret = WOC_INTERUPTED; } else { TRACE("Event(%p) is signaled, not waiting\n", hEvent); ret = WOC_SIGNALED; /* reset the event, if it's not a manual reset event */ if (pEventInfo->manualReset == FALSE) { pEventInfo->state = FALSE; } } } else { /* this structure needs to be allocated in the shared memory in term of supporting event for inter-process synchronization */ /* add the current thread to the list of waiting threads */ shmpWaitingThread = SHMalloc(sizeof(ThreadWaitingList)); if (shmpWaitingThread == (SHMPTR) NULL) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); ERROR("Not enough memory to allocate a ThreadWaitingList\n"); ret = WOC_ERROR; } else { pWaitingThread = (ThreadWaitingList *) SHMPTR_TO_PTR(shmpWaitingThread); pWaitingThread->threadId = GetCurrentThreadId(); pWaitingThread->processId = GetCurrentProcessId(); pWaitingThread->blockingPipe = THREADGetPipe(); pWaitingThread->ptr.shmNext = (SHMPTR) NULL; pWaitingThread->state.shmAwakened = wait_state; TRACE("ThreadId=%#x will wait on hEvent=%p\n", pWaitingThread->threadId, hEvent); /* place the thread at the end of the list */ if (pEventInfo->waitingThreads == (SHMPTR) NULL) { pEventInfo->waitingThreads = shmpWaitingThread; } else { ThreadWaitingList *pIter; ThreadWaitingList *pNext; pIter = (ThreadWaitingList *) SHMPTR_TO_PTR(pEventInfo->waitingThreads); while (pIter && pIter->ptr.shmNext) { pNext = (ThreadWaitingList *) SHMPTR_TO_PTR(pIter->ptr.shmNext); if (NULL == pNext) { ERROR("Invalid shared memory pointer\n"); /* the list is corrupted, but let's try to keep going anyway with the part that's still good */ pIter->ptr.shmNext = 0; } else { pIter = pNext; } } if(NULL == pIter) { ERROR("Invalid shared memory pointer\n"); /* the list is completely corrupted... start a new one */ pEventInfo->waitingThreads = shmpWaitingThread; } else { pIter->ptr.shmNext = shmpWaitingThread; } } TRACE("Event(%p) is not signaled," " current thread added to the waiting list\n", hEvent); ret = WOC_WAITING; } } SHMRelease(); HMGRUnlockHandle(hEvent,&pEvent->objHeader); return ret; }
/*++ Function: CreateEventW Note: Events could be used for cross-process synchroniztion. Security Attributes could be ignored. lpName could be non NULL. See MSDN doc. --*/ HANDLE PALAPI CreateEventW( IN LPSECURITY_ATTRIBUTES lpEventAttributes, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName) { HANDLE hEvent = NULL; Event *pEvent; GLOBAL_EVENT_SYSTEM_OBJECT *pEventInfo; SHMPTR newEvent; DWORD OldLastError; BOOL need_unlock = FALSE; LPCWSTR lpObjectName = NULL; WCHAR MangledObjectName[MAX_PATH]; PERF_ENTRY(CreateEventW); ENTRY("CreateEventW(lpEventAttr=%p, bManualReset=%d, " "bInitialState=%d, lpName=%p (%S)\n", lpEventAttributes, bManualReset, bInitialState, lpName?lpName:W16_NULLSTRING, lpName?lpName:W16_NULLSTRING); /* Validate parameters */ if (lpEventAttributes != NULL) { ASSERT("lpEventAttributes must be NULL\n"); SetLastError(ERROR_INVALID_PARAMETER); goto CreateEventExit; } if (lpName) { lpObjectName=lpName; if (!MangleObjectNameW(&lpObjectName, MangledObjectName)) { goto CreateEventExit; } /* take the shared memory lock to prevent other threads/processes from creating/deleting the object behind our back*/ SHMLock(); need_unlock = TRUE; /* Verify if there's an Event already created with that name */ OldLastError = GetLastError(); /* Try to open the event, using its unmangled name, as OpenEventW will mangle it */ hEvent = OpenEventW(EVENT_ALL_ACCESS, FALSE, lpName); if (hEvent != NULL) { TRACE("Event (%S) already exist.\n", lpName); SetLastError(ERROR_ALREADY_EXISTS); goto CreateEventExit; } if (GetLastError() == ERROR_INVALID_HANDLE) { ERROR("Another kernel object is using that name\n"); SetLastError(ERROR_INVALID_HANDLE); goto CreateEventExit; } SetLastError(OldLastError); } /* Allocate the event object */ pEvent = (Event *) malloc(sizeof(Event)); if (pEvent == NULL) { ERROR("Unable to allocate memory\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto CreateEventExit; } /* Allocate the EventInfo in shared memory, so it can be accessible by other processes */ newEvent = SHMalloc(sizeof(GLOBAL_EVENT_SYSTEM_OBJECT)); if (newEvent == (SHMPTR) NULL) { ERROR("Unable to allocate shared memory\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); free( pEvent ); goto CreateEventExit; } pEvent->objHeader.type = HOBJ_EVENT; pEvent->objHeader.close_handle = CloseEventHandle; pEvent->objHeader.dup_handle = DupEventHandle; pEvent->refCount = 1; pEvent->info = newEvent; pEventInfo = (GLOBAL_EVENT_SYSTEM_OBJECT*) SHMPTR_TO_PTR(newEvent); pEventInfo->refCount = 1; pEventInfo->state = bInitialState; pEventInfo->manualReset = bManualReset; pEventInfo->waitingThreads = (SHMPTR) NULL; pEventInfo->next = (SHMPTR) NULL; pEventInfo->ShmHeader.ObjectType = SHM_NAMED_EVENTS; pEventInfo->ShmHeader.ShmSelf = newEvent; if (lpName) { if ((pEventInfo->ShmHeader.ShmObjectName = SHMWStrDup( lpObjectName )) == 0) { ERROR( "Unable to allocate shared memory!\n " ); SetLastError(ERROR_INTERNAL_ERROR); SHMfree(newEvent); free(pEvent); goto CreateEventExit; } } else { pEventInfo->ShmHeader.ShmObjectName = 0; } hEvent = HMGRGetHandle((HOBJSTRUCT *) pEvent); if (hEvent == INVALID_HANDLE_VALUE) { if (lpName != NULL) { SHMfree(pEventInfo->ShmHeader.ShmObjectName); } SHMfree(newEvent); free(pEvent); ERROR("Unable to get a free handle\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto CreateEventExit; } /* Save the EventInfo into the global link list in shared memory. (Only if it has a name) */ if (lpName) { SHMAddNamedObject(newEvent); } TRACE("Event created (HANDLE=%p)\n", hEvent); CreateEventExit: if(need_unlock) { /* release the lock taken before OpenEventW */ SHMRelease(); } LOGEXIT("CreateEventW returns HANDLE %p\n", hEvent); PERF_EXIT(CreateEventW); return hEvent; }