UNDO_DEF *AllocateNewUndoBuffer(GEM_WINDOW *gwnd) { UNDO_DEF *undo ; VXIMAGE *vimage ; vimage = (VXIMAGE *) gwnd->Extension ; if ( ( vimage->NbUndoBuffers >= config.nb_undo ) && !IsListEmpty( &vimage->UndoListHead ) ) { LIST_ENTRY *entry ; entry = RemoveTailList( &vimage->UndoListHead ) ; undo = GET_UNDO_DEF_FROM_LIST_ENTRY( entry ) ; FreeUndoBuffer( undo ) ; } undo = (UNDO_DEF *) calloc( 1, sizeof(UNDO_DEF) ) ; if ( undo ) { undo->undo_num = UndoNum++ ; undo->gwindow = gwnd ; vimage->NbUndoBuffers++ ; } return( undo ) ; }
/* ** Free all the resources allocated in PKT_Init() */ BOOL PKT_Deinit(DWORD dwContext) { NDIS_STATUS Status; PLIST_ENTRY pHead; PLIST_ENTRY pEntry; PADAPTER_NAME pAName; POPEN_INSTANCE pOI; pOI = g_pDeviceExtension->pOpenInstance; if (pOI != NULL) { PKTCloseAdapter (pOI); } //free the names' list if (!IsListEmpty (&g_pDeviceExtension->listAdapterNames)) { pHead = &(g_pDeviceExtension->listAdapterNames); if (pHead != NULL ) { pEntry = RemoveTailList (pHead); while (!IsListEmpty(pEntry)){ pAName = CONTAINING_RECORD (pEntry, ADAPTER_NAME, ListElement); NdisFreeMemory (pAName, sizeof(ADAPTER_NAME), 0); pEntry = RemoveTailList (pHead); } } } //unregister the protocol from NDIS NdisDeregisterProtocol (&Status, g_pDeviceExtension->NdisProtocolHandle); //free the global device extension NdisFreeMemory (g_pDeviceExtension, sizeof (DEVICE_EXTENSION), 0); g_pDeviceExtension = NULL; return TRUE; }
/* * Remove the current PnP event from the tail of the event queue * and signal IopPnpNotifyEvent if there is yet another event in the queue. */ static NTSTATUS IopRemovePlugPlayEvent(VOID) { /* Remove a pnp event entry from the tail of the queue */ if (!IsListEmpty(&IopPnpEventQueueHead)) { ExFreePool(CONTAINING_RECORD(RemoveTailList(&IopPnpEventQueueHead), PNP_EVENT_ENTRY, ListEntry)); } /* Signal the next pnp event in the queue */ if (!IsListEmpty(&IopPnpEventQueueHead)) { KeSetEvent(&IopPnpNotifyEvent, 0, FALSE); } return STATUS_SUCCESS; }
NTSTATUS CImageHardwareSimulation:: CompletePastBuffers() /*++ Routine Description: Find and complete any history frames. Arguments: None Return Value: Success / Failure --*/ { PAGED_CODE(); ULONG ulNumBuffers = m_PastBufferCount; BOOLEAN bContinue = TRUE; LIST_ENTRY *listEntry = NULL; DBG_ENTER("()"); DBG_TRACE("m_PastBufferCount=%d, m_TriggerTime=0x%016llX", m_PastBufferCount, m_TriggerTime ); // If we're in burst mode and have ISP settings, we can't // really support changing the ISP settings in the past... // ... so we'll just treat them all past frames. // Note: The upper layer will determine past frames from the // metadata FrameId. if( m_PinMode == PinBurstMode && !m_pIspSettings ) { // Walk through the entire list of buffers, find the most // recent frame presentation time and put all past buffers // into another list. while( !IsListEmpty(&m_ScatterGatherMappings) ) { listEntry = RemoveTailList(&m_ScatterGatherMappings); m_ScatterGatherMappingsQueued--; PSCATTER_GATHER_ENTRY SGEntry = reinterpret_cast <PSCATTER_GATHER_ENTRY> ( CONTAINING_RECORD ( listEntry, SCATTER_GATHER_ENTRY, ListEntry ) ); NT_ASSERT(SGEntry); NT_ASSERT(SGEntry->CloneEntry); NT_ASSERT(SGEntry->CloneEntry->StreamHeader); // We've found one that's not stamped. We must be at the end. // Push it back and exit the loop. if(SGEntry->CloneEntry->StreamHeader->PresentationTime.Time == 0) { InsertTailList(&m_ScatterGatherMappings, listEntry); m_ScatterGatherMappingsQueued++; DBG_TRACE( "No past frames found." ); bContinue = FALSE; break; } // Since we're walking from the most recent to least recent frame, // This one is a valid "future" frame. DBG_TRACE( "Adding 'future frame' to the list" ); PushCloneList(SGEntry); // If the presentation time is less than the trigger time, stop here // and use this as the first triggered frame. if((ULONGLONG)(SGEntry->CloneEntry->StreamHeader->PresentationTime.Time) < m_TriggerTime) { DBG_TRACE( "First matching frame time=0x%016llX", SGEntry->CloneEntry->StreamHeader->PresentationTime.Time ); break; } // Watch out! We might actually need to pick up multiple frames since // in theory we could have generated several since the trigger time. } } // Grab N past frames from the queue, if we have them. while( bContinue && !IsListEmpty(&m_ScatterGatherMappings) && ulNumBuffers) { listEntry = RemoveTailList(&m_ScatterGatherMappings); m_ScatterGatherMappingsQueued--; PSCATTER_GATHER_ENTRY SGEntry = reinterpret_cast <PSCATTER_GATHER_ENTRY> ( CONTAINING_RECORD ( listEntry, SCATTER_GATHER_ENTRY, ListEntry ) ); if(!(SGEntry -> CloneEntry -> StreamHeader -> OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TIMEVALID) ) { InsertTailList(&m_ScatterGatherMappings, listEntry); m_ScatterGatherMappingsQueued++; DBG_TRACE( "No more past frames found." ); bContinue = FALSE; } else { PushCloneList(SGEntry); ulNumBuffers--; DBG_TRACE( "Past frame #%d found (%p)", ulNumBuffers, SGEntry->CloneEntry->StreamHeader ); } } // If we got all of the past frames we needed and didn't consume the entire queue... if(bContinue && (m_ScatterGatherMappingsQueued > 0)) { //Mark the next tail as Time = 0 so that we don't output any super old frames. listEntry = RemoveTailList(&m_ScatterGatherMappings); m_ScatterGatherMappingsQueued--; PSCATTER_GATHER_ENTRY SGEntry = reinterpret_cast <PSCATTER_GATHER_ENTRY> ( CONTAINING_RECORD ( listEntry, SCATTER_GATHER_ENTRY, ListEntry ) ); // Mark the PTS as invalid. SGEntry->CloneEntry->StreamHeader->PresentationTime.Time = 0; SGEntry->CloneEntry->StreamHeader->OptionsFlags &= ~KSSTREAM_HEADER_OPTIONSF_TIMEVALID; InsertTailList(&m_ScatterGatherMappings, listEntry); m_ScatterGatherMappingsQueued++; } CompleteCloneList(); m_bPastBufferTrigger = FALSE; DBG_LEAVE("()"); return STATUS_SUCCESS; }
VOID CmpDelayCloseWorker( IN PVOID Parameter ) /*++ Routine Description: The fun part. We need to walk the cache and look for kcbs with refcount == 0 Get the oldest one and kick it out of cache. Arguments: Parameter - not used. Return Value: None. --*/ { PCM_DELAYED_CLOSE_ENTRY DelayedEntry; ULONG ConvKey; ULONG MaxIterations = MAX_DELAY_WORKER_ITERATIONS; CM_PAGED_CODE(); UNREFERENCED_PARAMETER (Parameter); ASSERT(CmpDelayCloseWorkItemActive); BEGIN_LOCK_CHECKPOINT; CmpLockRegistry(); // // process kick out every entry with RefCount == 0 && DelayCloseIndex == 0 // ignore the others; we only do this while there is excess of delay - close kcbs // LOCK_DELAY_CLOSE(); while( (CmpDelayedCloseElements > CmpDelayedCloseSize) && (MaxIterations--) ) { ASSERT( !CmpIsListEmpty(&CmpDelayedLRUListHead) ); // // We first need to get the hash entry and attempt to lock it. // DelayedEntry = (PCM_DELAYED_CLOSE_ENTRY)(CmpDelayedLRUListHead.Blink); DelayedEntry = CONTAINING_RECORD( DelayedEntry, CM_DELAYED_CLOSE_ENTRY, DelayedLRUList); ConvKey = DelayedEntry->KeyControlBlock->ConvKey; UNLOCK_DELAY_CLOSE(); // // now lock the hash then recheck if the entry is still first on the list // CmpLockHashEntryExclusive(ConvKey); LOCK_DELAY_CLOSE(); if( CmpDelayedCloseElements <= CmpDelayedCloseSize ) { // // just bail out; no need to kick them out // CmpUnlockHashEntry(ConvKey); break; } DelayedEntry = (PCM_DELAYED_CLOSE_ENTRY)(CmpDelayedLRUListHead.Blink); DelayedEntry = CONTAINING_RECORD( DelayedEntry, CM_DELAYED_CLOSE_ENTRY, DelayedLRUList); if( ConvKey == DelayedEntry->KeyControlBlock->ConvKey ) { // // same hash entry; proceed // pull it out of the list // DelayedEntry = (PCM_DELAYED_CLOSE_ENTRY)RemoveTailList(&CmpDelayedLRUListHead); DelayedEntry = CONTAINING_RECORD( DelayedEntry, CM_DELAYED_CLOSE_ENTRY, DelayedLRUList); CmpClearListEntry(&(DelayedEntry->DelayedLRUList)); if( (DelayedEntry->KeyControlBlock->RefCount == 0) && (DelayedEntry->KeyControlBlock->DelayedCloseIndex == 0) ){ // // free this kcb and the entry // UNLOCK_DELAY_CLOSE(); DelayedEntry->KeyControlBlock->DelayCloseEntry = NULL; CmpCleanUpKcbCacheWithLock(DelayedEntry->KeyControlBlock,FALSE); CmpDelayCloseFreeEntry(DelayedEntry); InterlockedDecrement((PLONG)&CmpDelayedCloseElements); } else { // // put it back at the top // InsertHeadList( &CmpDelayedLRUListHead, &(DelayedEntry->DelayedLRUList) ); UNLOCK_DELAY_CLOSE(); } } else { UNLOCK_DELAY_CLOSE(); } CmpUnlockHashEntry(ConvKey); LOCK_DELAY_CLOSE(); } if( CmpDelayedCloseElements > CmpDelayedCloseSize ) { // // iteration run was too short, there are more elements to process, queue ourselves for later // CmpArmDelayedCloseTimer(); } else { // // signal that we have finished our work. // CmpDelayCloseWorkItemActive = FALSE; } UNLOCK_DELAY_CLOSE(); CmpUnlockRegistry(); END_LOCK_CHECKPOINT; }
int TestInterlockedDList(int argc, char* argv[]) { ULONG Count; PLIST_ITEM pListItem; WINPR_PLIST_ENTRY pListHead; WINPR_PLIST_ENTRY pListEntry; pListHead = (WINPR_PLIST_ENTRY) _aligned_malloc(sizeof(WINPR_LIST_ENTRY), MEMORY_ALLOCATION_ALIGNMENT); if (!pListHead) { printf("Memory allocation failed.\n"); return -1; } InitializeListHead(pListHead); if (!IsListEmpty(pListHead)) { printf("Expected empty list\n"); return -1; } /* InsertHeadList / RemoveHeadList */ printf("InsertHeadList / RemoveHeadList\n"); for (Count = 1; Count <= 10; Count += 1) { pListItem = (PLIST_ITEM) _aligned_malloc(sizeof(LIST_ITEM), MEMORY_ALLOCATION_ALIGNMENT); pListItem->Signature = Count; InsertHeadList(pListHead, &(pListItem->ItemEntry)); } for (Count = 10; Count >= 1; Count -= 1) { pListEntry = RemoveHeadList(pListHead); pListItem = (PLIST_ITEM) pListEntry; _aligned_free(pListEntry); } /* InsertTailList / RemoveTailList */ printf("InsertTailList / RemoveTailList\n"); for (Count = 1; Count <= 10; Count += 1) { pListItem = (PLIST_ITEM) _aligned_malloc(sizeof(LIST_ITEM), MEMORY_ALLOCATION_ALIGNMENT); pListItem->Signature = Count; InsertTailList(pListHead, &(pListItem->ItemEntry)); } for (Count = 10; Count >= 1; Count -= 1) { pListEntry = RemoveTailList(pListHead); pListItem = (PLIST_ITEM) pListEntry; _aligned_free(pListEntry); } _aligned_free(pListHead); return 0; }
HRESULT CMSPThread::QueueWorkItem( LPTHREAD_START_ROUTINE Function, PVOID Context, BOOL fSynchronous ) { LOG((MSP_TRACE, "CMSPThread::QueueWorkItem - enter")); // // Create a command block for this. // COMMAND_QUEUE_ITEM * pItem = new COMMAND_QUEUE_ITEM; if ( ! pItem ) { LOG((MSP_ERROR, "CMSPThread::QueueWorkItem - " "can't allocate new queue item - exit E_OUTOFMEMORY")); return E_OUTOFMEMORY; } // // Create an event to wait on if this is a synchronous work item. // Otherwise the thread proc gets a NULL event handle and it knows not to // signal it since it's an asynchronous work item. // TCHAR *ptczEventName = NULL; #if DBG static LONG lSequenceNumber = 0; // // in debug build, use named events // TCHAR tszEventName[MAX_PATH]; InterlockedIncrement(&lSequenceNumber); // // identify events by the address of the correspoding queue item, and by // the sequence number // _stprintf_s(tszEventName, _T("CMSPThread_QueueWorkitemEvent_pid[0x%lx]_CMSPThread[%p]_Event[%p]_eventNumber[%lu]"), GetCurrentProcessId(), this, pItem, lSequenceNumber); LOG((MSP_TRACE, "CMSPThread::QueueWorkItem - creating event[%S]", tszEventName)); ptczEventName = &tszEventName[0]; #endif HANDLE hEvent = NULL; if (fSynchronous) { hEvent = ::CreateEvent(NULL, FALSE, // flag for manual-reset event FALSE, // initial state is not set. ptczEventName); // No name in release, named in debug if ( hEvent == NULL ) { LOG((MSP_ERROR, "CMSPThread::QueueWorkItem - " "Can't create the Job Done event")); delete pItem; pItem = NULL; return E_FAIL; } } // // we already have the q item, now initialize it. // pItem->node.cmd = WORK_ITEM; pItem->node.pfn = Function; pItem->node.pContext = Context; pItem->node.hEvent = hEvent; // // Put the command block on the queue. The queue is protected by a // critical section. // m_QueueLock.Lock(); InsertTailList(&m_CommandQueue, &(pItem->link)); // // Signal the thread to process the command. // if (SignalThreadProc() == 0) { // // failed to signal processing thread // cleanup and return error // // // remove the queue entry we have submitted // RemoveTailList(&m_CommandQueue); // // unlock the queue so other threads can use it // m_QueueLock.Unlock(); // // close handle and delete pItem that we have created -- // no one else is going to do this for us // if (NULL != hEvent) { ::CloseHandle(hEvent); hEvent = NULL; } delete pItem; pItem = NULL; LOG((MSP_ERROR, "CMSPThread::QueueWorkItem - " "can't signal the thread")); return E_FAIL; } // // unlock the event queue, so it can be used by processing and other // threads // m_QueueLock.Unlock(); // // If this is a sychronous work item, wait for it to complete and // then close the event handle. // // FEATUREFEATURE: Rather than creating and deleting an event for each // work item, have a cache of events that can be reused. // if (fSynchronous) { LOG((MSP_TRACE, "CMSPThread::QueueWorkItem - " "blocked waiting for synchronous work item to complete")); // Wait for the synchronous work item to complete. HANDLE hEvents[2]; DWORD dwEvent; hEvents[0] = hEvent; hEvents[1] = m_hThread; dwEvent = WaitForMultipleObjects( 2, hEvents, FALSE, INFINITE); switch (dwEvent) { case WAIT_OBJECT_0 + 0: break; case WAIT_OBJECT_0 + 1: LOG((MSP_ERROR, "CMSPThread::QueueWorkItem - " "thread exited")); // // if the item is still in the queue, remove it (since the thread // won't) // m_QueueLock.Lock(); if (IsNodeOnList(&m_CommandQueue, &(pItem->link))) { RemoveEntryList(&(pItem->link)); delete pItem; } m_QueueLock.Unlock(); // // time to close event and fail // ::CloseHandle(hEvent); return E_FAIL; default: LOG((MSP_ERROR, "CMSPThread::QueueWorkItem - " "WaitForSingleObject failed")); } ::CloseHandle(hEvent); } LOG((MSP_TRACE, "CMSPThread::QueueWorkItem - exit S_OK")); return S_OK; }
ULONG RspWriteProbeGroup( IN HANDLE FileHandle ) { ULONG CompleteBytes; ULONG OnDiskLength; PRSP_PROBE_GROUP Group; PRSP_PROBE Probe; PLIST_ENTRY ListEntry; PLIST_ENTRY Entry; if (!RspProbeGroupCount) { return 0; } WriteFile(FileHandle, &RspProbeGroupCount, sizeof(ULONG), &CompleteBytes, NULL); ListEntry = RspProbeGroupList.Flink; OnDiskLength = FIELD_OFFSET(RSP_PROBE_GROUP, ListEntry); while (ListEntry != &RspProbeGroupList) { Group = CONTAINING_RECORD(ListEntry, RSP_PROBE_GROUP, ListEntry); WriteFile(FileHandle, Group, OnDiskLength, &CompleteBytes, NULL); ListEntry = ListEntry->Flink; } ListEntry = RspProbeGroupList.Flink; while (ListEntry != &RspProbeGroupList) { Group = CONTAINING_RECORD(ListEntry, RSP_PROBE_GROUP, ListEntry); Entry = Group->ProbeListHead.Flink; while (Entry != &Group->ProbeListHead) { Probe = CONTAINING_RECORD(Entry, RSP_PROBE, Entry); WriteFile(FileHandle, Probe, sizeof(RSP_PROBE), &CompleteBytes, NULL); if (FlagOn(Probe->Flag, BTR_FLAG_MULTIVERSION)) { // // N.B. For multi-version probe, it's written to disk in order of number // while (IsListEmpty(&Probe->VariantList) != TRUE) { PRSP_PROBE Subversion; PLIST_ENTRY Entry2; Entry2 = RemoveTailList(&Probe->VariantList); Subversion = CONTAINING_RECORD(Entry2, RSP_PROBE, VariantList); ASSERT(FlagOn(Subversion->Flag, BTR_FLAG_VARIANT)); WriteFile(FileHandle, Subversion, sizeof(RSP_PROBE), &CompleteBytes, NULL); } } Entry = Entry->Flink; } ListEntry = ListEntry->Flink; } return 0; }