bool mp_create() { size_t total = 0; for( int i = 0; i < MP_MAX_OBJECT_TYPE; ++i ) total += s_entries[i].count * s_entries[i].size; s_base = VirtualAlloc( NULL, total, MEM_COMMIT, PAGE_READWRITE ); if( s_base == NULL ) return false; char* base = reinterpret_cast<char*>( s_base ); for( int i = 0; i < MP_MAX_OBJECT_TYPE; ++i ) { MP_OBJECT_ENTRY* entry = s_entries + i; InitializeSListHead( &entry->lsthdr ); char* addr = base + entry->size * entry->count; addr -= MEMORY_ALLOCATION_ALIGNMENT; for( size_t j = 0; j < entry->count; ++j ) { SLIST_ENTRY* node = reinterpret_cast<SLIST_ENTRY*>( addr ); InterlockedPushEntrySList( &entry->lsthdr, node ); addr -= entry->size; } base += entry->count * entry->size; } return true; }
void ReturnIOContext( PHTTP_IO_CONTEXT context ) { PLOOKASIDE cacheEntry = &IoContextCacheList[IO_CONTEXT_PROC_INDEX]; InterlockedPushEntrySList(&cacheEntry->Header, &context->LookAsideEntry); }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT printer_irp_request(DEVICE* device, IRP* irp) { PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*) device; InterlockedPushEntrySList(printer_dev->pIrpList, &(irp->ItemEntry)); SetEvent(printer_dev->event); return CHANNEL_RC_OK; }
VOID BtrFreeLookaside( __in BTR_LOOKASIDE_TYPE Type, __in PVOID Ptr ) { PBTR_LOOKASIDE Lookaside; PSLIST_ENTRY ListEntry; USHORT Depth; if (!Ptr) { return; } Lookaside = &BtrLookaside[Type]; InterlockedIncrement(&Lookaside->TotalFrees); Depth = QueryDepthSList(&Lookaside->ListHead); ListEntry = (PSLIST_ENTRY)((PUCHAR)Ptr - MEMORY_ALLOCATION_ALIGNMENT); if (Depth < Lookaside->MaximumDepth) { InterlockedPushEntrySList(&Lookaside->ListHead, ListEntry); } else { InterlockedIncrement(&Lookaside->FreeMisses); BtrAlignedFree(ListEntry); } }
/* can be called from any thread */ static UINT32 FREERDP_CC MyVirtualChannelWrite(UINT32 openHandle, void* pData, UINT32 dataLength, void* pUserData) { int index; SYNC_DATA* item; rdpChannels* channels; struct channel_data* lchannel_data; channels = freerdp_channels_find_by_open_handle(openHandle, &index); if ((channels == NULL) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) { DEBUG_CHANNELS("error bad channel handle"); return CHANNEL_RC_BAD_CHANNEL_HANDLE; } if (!channels->is_connected) { DEBUG_CHANNELS("error not connected"); return CHANNEL_RC_NOT_CONNECTED; } if (pData == 0) { DEBUG_CHANNELS("error bad pData"); return CHANNEL_RC_NULL_DATA; } if (dataLength == 0) { DEBUG_CHANNELS("error bad dataLength"); return CHANNEL_RC_ZERO_LENGTH; } lchannel_data = channels->channels_data + index; if (lchannel_data->flags != 2) { DEBUG_CHANNELS("error not open"); return CHANNEL_RC_NOT_OPEN; } if (!channels->is_connected) { DEBUG_CHANNELS("error not connected"); return CHANNEL_RC_NOT_CONNECTED; } item = (SYNC_DATA*) _aligned_malloc(sizeof(SYNC_DATA), MEMORY_ALLOCATION_ALIGNMENT); item->Data = pData; item->DataLength = dataLength; item->UserData = pUserData; item->Index = index; InterlockedPushEntrySList(channels->pSyncDataList, &(item->ItemEntry)); /* set the event */ SetEvent(channels->signal); return CHANNEL_RC_OK; }
static void printer_irp_request(DEVICE* device, IRP* irp) { PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*) device; InterlockedPushEntrySList(printer_dev->pIrpList, &(irp->ItemEntry)); freerdp_thread_signal(printer_dev->thread); }
static void drive_irp_request(DEVICE* device, IRP* irp) { DRIVE_DEVICE* disk = (DRIVE_DEVICE*) device; InterlockedPushEntrySList(disk->pIrpList, &(irp->ItemEntry)); SetEvent(disk->irpEvent); }
void Deallocate(OVERLAPPED* ovl) { cpu_AtomicAdd(&extant, -1); const uintptr_t address = uintptr_t(ovl); ENSURE(uintptr_t(storage) <= address && address < uintptr_t(storage)+storageSize); InterlockedPushEntrySList(&freelist, (PSLIST_ENTRY)(address - offsetof(Entry, ovl))); }
static void parallel_irp_request(DEVICE* device, IRP* irp) { PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) device; InterlockedPushEntrySList(parallel->pIrpList, &(irp->ItemEntry)); freerdp_thread_signal(parallel->thread); }
DWORD InterfaceUtils::AddEntry(ULONG NTEContext) { pProgramItem = (PPROGRAM_ITEM)_aligned_malloc(sizeof(PROGRAM_ITEM), MEMORY_ALLOCATION_ALIGNMENT); if (NULL == pProgramItem) { printf("Memory allocation failed.\n"); return -1; } pProgramItem->NTEContext = NTEContext; pFirstEntry = InterlockedPushEntrySList(pListHead, &(pProgramItem->ItemEntry)); return NO_ERROR; }
void mp_free( int objtype, void* mem ) { if( mem == NULL ) return; MP_OBJECT_ENTRY* entry = s_entries + objtype; char* p = reinterpret_cast<char*>( mem ); p += entry->size - MEMORY_ALLOCATION_ALIGNMENT; SLIST_ENTRY* node = reinterpret_cast<SLIST_ENTRY*>( p ); InterlockedPushEntrySList( &s_entries[objtype].lsthdr, node ); }
void IConcurrentPool::Init() { mWork = std::make_shared<boost::asio::io_service::work>( mDispatcher ); const auto f = [ = ]() { LThreadId = GetCurrentThreadId(); LThreadCallHistory = std::make_shared<ThreadCallHistory>( LThreadId ); InterlockedPushEntrySList( >hreadCallHistory, reinterpret_cast<PSLIST_ENTRY>(LThreadCallHistory.get()) ); LThreadCallElapsedRecord = std::make_shared<ThreadCallElapsedRecord>( LThreadId ); InterlockedPushEntrySList( >hreadCallElapsedRecord, reinterpret_cast<PSLIST_ENTRY>(LThreadCallElapsedRecord.get()) ); InitThread(); Run(); }; for( std::size_t i = 0; i < mPoolSize; ++i ) { mGroup.create_thread( f ); } }
// ****************************************************************** // * 0x003A - InterlockedPushEntrySList() // ****************************************************************** // Source:ReactOS XBSYSAPI EXPORTNUM(58) xboxkrnl::PSLIST_ENTRY FASTCALL xboxkrnl::KRNL(InterlockedPushEntrySList) ( IN PSLIST_HEADER ListHead, IN PSLIST_ENTRY ListEntry ) { LOG_FUNC_BEGIN LOG_FUNC_ARG(ListHead) LOG_FUNC_ARG(ListEntry) LOG_FUNC_END; PSLIST_ENTRY res = (PSLIST_ENTRY)InterlockedPushEntrySList((::PSLIST_HEADER)ListHead, (::PSLIST_ENTRY)ListEntry); RETURN(res); }
static void CALLBACK cubeb_buffer_callback(HWAVEOUT waveout, UINT msg, DWORD_PTR user_ptr, DWORD_PTR p1, DWORD_PTR p2) { cubeb_stream * stm = (cubeb_stream *) user_ptr; struct cubeb_stream_item * item; if (msg != WOM_DONE) { return; } item = _aligned_malloc(sizeof(struct cubeb_stream_item), MEMORY_ALLOCATION_ALIGNMENT); assert(item); item->stream = stm; InterlockedPushEntrySList(stm->context->work, &item->head); SetEvent(stm->context->event); }
void cp_parallelized_crypt( int is_encrypt, xts_key *key, fc_callback on_complete, void *param, const unsigned char *in, unsigned char *out, u32 len, u64 offset) { req_item *item; req_part *part; u32 part_sz; u32 part_of; if ( (len < F_OP_THRESOLD) || ((item = ExAllocateFromNPagedLookasideList(&pool_req_mem)) == NULL) ) { if (is_encrypt != 0) { xts_encrypt(in, out, len, offset, key); } else { xts_decrypt(in, out, len, offset, key); } on_complete(param); return; } item->is_encrypt = is_encrypt; item->length = len; item->in = in; item->out = out; item->offset = offset; item->on_complete = on_complete; item->param = param; item->key = key; part_sz = _align(len / dc_cpu_count, F_MIN_REQ); part_of = 0; part = &item->parts[0]; do { part_sz = min(part_sz, len); part->item = item; part->offset = part_of; part->length = part_sz; InterlockedPushEntrySList(&pool_head, &part->entry); part_of += part_sz; len -= part_sz; part++; } while (len != 0); KeSetEvent(&pool_signal_event, IO_NO_INCREMENT, FALSE); }
static void smartcard_irp_request(DEVICE* device, IRP* irp) { COMPLETIONIDINFO* CompletionIdInfo; SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device; /* Begin TS Client defect workaround. */ CompletionIdInfo = (COMPLETIONIDINFO*) malloc(sizeof(COMPLETIONIDINFO)); ZeroMemory(CompletionIdInfo, sizeof(COMPLETIONIDINFO)); CompletionIdInfo->ID = irp->CompletionId; WaitForSingleObject(smartcard->CompletionIdsMutex, INFINITE); smartcard_mark_duplicate_id(smartcard, irp->CompletionId); list_enqueue(smartcard->CompletionIds, CompletionIdInfo); ReleaseMutex(smartcard->CompletionIdsMutex); /* Overwrite the previous assignment made in irp_new() */ irp->Complete = smartcard_irp_complete; /* End TS Client defect workaround. */ if ((irp->MajorFunction == IRP_MJ_DEVICE_CONTROL) && smartcard_async_op(irp)) { /* certain potentially long running operations get their own thread */ SMARTCARD_IRP_WORKER* irpWorker = malloc(sizeof(SMARTCARD_IRP_WORKER)); irpWorker->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) smartcard_process_irp_thread_func, irpWorker, CREATE_SUSPENDED, NULL); irpWorker->smartcard = smartcard; irpWorker->irp = irp; ResumeThread(irpWorker->thread); return; } InterlockedPushEntrySList(smartcard->pIrpList, &(irp->ItemEntry)); SetEvent(smartcard->irpEvent); }
VOID NTAPI DbgLogEvent(PSLIST_HEADER pslh, LOG_EVENT_TYPE nEventType, LPARAM lParam) { PLOGENTRY pLogEntry; /* Log a maximum of 100 events */ if (QueryDepthSList(pslh) >= 1000) return; /* Allocate a logentry */ pLogEntry = EngAllocMem(0, sizeof(LOGENTRY), 'golG'); if (!pLogEntry) return; /* Set type */ pLogEntry->nEventType = nEventType; pLogEntry->ulUnique = InterlockedIncrement((LONG*)&gulLogUnique); pLogEntry->dwProcessId = HandleToUlong(PsGetCurrentProcessId()); pLogEntry->dwThreadId = HandleToUlong(PsGetCurrentThreadId()); pLogEntry->lParam = lParam; /* Capture a backtrace */ DbgCaptureStackBackTace(pLogEntry->apvBackTrace, 20); switch (nEventType) { case EVENT_ALLOCATE: case EVENT_CREATE_HANDLE: case EVENT_REFERENCE: case EVENT_DEREFERENCE: case EVENT_LOCK: case EVENT_UNLOCK: case EVENT_DELETE: case EVENT_FREE: case EVENT_SET_OWNER: default: break; } /* Push it on the list */ InterlockedPushEntrySList(pslh, &pLogEntry->sleLink); }
void Push( __out_opt SNI_Packet *pPacket) { if( QueryDepthSList(&m_SListHeader) < MAX_PACKET_CACHE_SIZE - 1 ) { SLIST_ENTRY* pEntry = static_cast<SLIST_ENTRY*>(SNIPacketGetDescriptor(pPacket)); InterlockedPushEntrySList(&m_SListHeader, pEntry); } else { // Strategy: Don't make an effort to clean up the "extra" entries, but don't push this one onto the stack // if it will go over. This guarantees an *approximate* maximum // (bounded above by MAX_PACKET_CACHE_SIZE + ConcurrentThreadsAccessingTheStack) // It would cost a lot of performance to put a stronger guarantee on the maximal size, since // we would need to synchronize access to two variables (stack head, stack size), which we // don't know how to do without using a true [....] primitive, rather than the two separate // Interlocked operations which are all that's required to maintain consistency of the list header and // an *approximate* depth guarantee. SNIPacketDelete(pPacket); } }
HRESULT CConnectionPool::Return(HANDLE connection) { HRESULT hr; PCONNECTION_ENTRY entry = NULL; if (this->count >= this->maxPoolSize) { CloseHandle(connection); } else { ErrorIf(NULL == (entry = (PCONNECTION_ENTRY)_aligned_malloc(sizeof(CONNECTION_ENTRY), MEMORY_ALLOCATION_ALIGNMENT)), ERROR_NOT_ENOUGH_MEMORY); entry->connection = connection; entry->timestamp = GetTickCount(); InterlockedPushEntrySList(this->list, &(entry->listEntry)); InterlockedIncrement(&this->count); } return S_OK; Error: return hr; }
VOID NTAPI IopFreeMiniPacket(PIOP_MINI_COMPLETION_PACKET Packet) { PKPRCB Prcb = KeGetCurrentPrcb(); PNPAGED_LOOKASIDE_LIST List; /* Use the P List */ List = (PNPAGED_LOOKASIDE_LIST)Prcb-> PPLookasideList[LookasideCompletionList].P; List->L.TotalFrees++; /* Check if the Free was within the Depth or not */ if (ExQueryDepthSList(&List->L.ListHead) >= List->L.Depth) { /* Let the balancer know */ List->L.FreeMisses++; /* Use the L List */ List = (PNPAGED_LOOKASIDE_LIST)Prcb-> PPLookasideList[LookasideCompletionList].L; List->L.TotalFrees++; /* Check if the Free was within the Depth or not */ if (ExQueryDepthSList(&List->L.ListHead) >= List->L.Depth) { /* All lists failed, use the pool */ List->L.FreeMisses++; ExFreePool(Packet); return; } } /* The free was within dhe Depth */ InterlockedPushEntrySList(&List->L.ListHead, (PSLIST_ENTRY)Packet); }
/// <summary> /// Handles the completion of a UMS thread. /// </summary> /// <param name="pCompletion"> /// The thread which was noticed on the completion list /// </param> /// <returns> /// An indication as to whether the thread moved to the transfer list (true). If false is returned, the thread was special /// (e.g.: a critically blocked thread) and was handled through a different path. /// </returns> bool UMSSchedulerProxy::HandleCompletion(UMSThreadProxy *pCompletion) { // // We need to make absolutely certain that we know *WHY* the context blocked so we can tell what to do when it comes off the completion list. // This is not known until the primary which was invoked sets appropriate flags and then notifies the proxy that it is blocked. In order to // read those bits, we must spin until the proxy has set those flags. // UMSThreadProxy::BlockingType blockingType = pCompletion->SpinOnAndReturnBlockingType(); // // We are allowing thread termination on the way out of the RM's main loop in order to retire virtual processors and threads simultaneously // (a necessary condition in order to work around a win7 issue). This means that terminated threads can come back on the completion list. We // do not want to pop this back for the scheduler -- the scheduler should already know (this is *NOT* TerminateThread friendly). // // Termination will take the same path as critical blocking. We must ensure elsewhere in the scheduler that threads we allow to terminate in // this manner are in hyper-critical regions. // CONCRT_COREASSERT(!pCompletion->IsTerminated() || blockingType == UMSThreadProxy::BlockingCritical); #if defined(_DEBUG) if (pCompletion->IsTerminated()) { pCompletion->m_UMSDebugBits |= UMS_DEBUGBIT_COMPLETIONTERMINATED; } #endif // _DEBUG RPMTRACE(MTRACE_EVT_PULLEDFROMCOMPLETION, pCompletion, NULL, blockingType); #if defined(_DEBUG) CONCRT_COREASSERT(pCompletion->m_UMSDebugBits != UMS_DEBUGBIT_YIELDED); #endif // _DEBUG if (blockingType == UMSThreadProxy::BlockingCritical) { #if defined(_DEBUG) pCompletion->m_UMSDebugBits |= UMS_DEBUGBIT_CRITICALNOTIFY; #endif // _DEBUG pCompletion->m_pLastRoot->CriticalNotify(); } else if (!pCompletion->MessagedYield()) { #if defined(_DEBUG) pCompletion->m_UMSDebugBits |= UMS_DEBUGBIT_TRANSFERLIST; #endif // _DEBUG // // Right now, just move the entry to the transfer list. // InterlockedPushEntrySList(&m_transferList, &(pCompletion->m_listEntry)); // // Set the transferlist event that should wake up vprocs that are deactivated // if (InterlockedIncrement(&m_pushedBackCount) == 1) { SetEvent(m_hTransferListEvent); } return true; } else { #if defined(_DEBUG) pCompletion->m_UMSDebugBits |= UMS_DEBUGBIT_SKIPPEDCOMPLETION; #endif // _DEBUG } return false; }
VOID EnqueueFreeTransferPacket(PDEVICE_OBJECT Fdo, PTRANSFER_PACKET Pkt) { PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension; PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData; KIRQL oldIrql; ULONG newNumPkts; ASSERT(!Pkt->SlistEntry.Next); InterlockedPushEntrySList(&fdoData->FreeTransferPacketsList, &Pkt->SlistEntry); newNumPkts = InterlockedIncrement(&fdoData->NumFreeTransferPackets); ASSERT(newNumPkts <= fdoData->NumTotalTransferPackets); /* * If the total number of packets is larger than MinWorkingSetTransferPackets, * that means that we've been in stress. If all those packets are now * free, then we are now out of stress and can free the extra packets. * Free down to MaxWorkingSetTransferPackets immediately, and * down to MinWorkingSetTransferPackets lazily (one at a time). */ if (fdoData->NumFreeTransferPackets >= fdoData->NumTotalTransferPackets){ /* * 1. Immediately snap down to our UPPER threshold. */ if (fdoData->NumTotalTransferPackets > MaxWorkingSetTransferPackets){ SINGLE_LIST_ENTRY pktList; PSINGLE_LIST_ENTRY slistEntry; PTRANSFER_PACKET pktToDelete; DBGTRACE(ClassDebugTrace, ("Exiting stress, block freeing (%d-%d) packets.", fdoData->NumTotalTransferPackets, MaxWorkingSetTransferPackets)); /* * Check the counter again with lock held. This eliminates a race condition * while still allowing us to not grab the spinlock in the common codepath. * * Note that the spinlock does not synchronize with threads dequeuing free * packets to send (DequeueFreeTransferPacket does that with a lightweight * interlocked exchange); the spinlock prevents multiple threads in this function * from deciding to free too many extra packets at once. */ SimpleInitSlistHdr(&pktList); KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql); while ((fdoData->NumFreeTransferPackets >= fdoData->NumTotalTransferPackets) && (fdoData->NumTotalTransferPackets > MaxWorkingSetTransferPackets)){ pktToDelete = DequeueFreeTransferPacket(Fdo, FALSE); if (pktToDelete){ SimplePushSlist(&pktList, &pktToDelete->SlistEntry); InterlockedDecrement(&fdoData->NumTotalTransferPackets); } else { DBGTRACE(ClassDebugTrace, ("Extremely unlikely condition (non-fatal): %d packets dequeued at once for Fdo %p. NumTotalTransferPackets=%d (1).", MaxWorkingSetTransferPackets, Fdo, fdoData->NumTotalTransferPackets)); break; } } KeReleaseSpinLock(&fdoData->SpinLock, oldIrql); while (slistEntry = SimplePopSlist(&pktList)){ pktToDelete = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry); DestroyTransferPacket(pktToDelete); } } /* * 2. Lazily work down to our LOWER threshold (by only freeing one packet at a time). */ if (fdoData->NumTotalTransferPackets > MinWorkingSetTransferPackets){ /* * Check the counter again with lock held. This eliminates a race condition * while still allowing us to not grab the spinlock in the common codepath. * * Note that the spinlock does not synchronize with threads dequeuing free * packets to send (DequeueFreeTransferPacket does that with a lightweight * interlocked exchange); the spinlock prevents multiple threads in this function * from deciding to free too many extra packets at once. */ PTRANSFER_PACKET pktToDelete = NULL; DBGTRACE(ClassDebugTrace, ("Exiting stress, lazily freeing one of %d/%d packets.", fdoData->NumTotalTransferPackets, MinWorkingSetTransferPackets)); KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql); if ((fdoData->NumFreeTransferPackets >= fdoData->NumTotalTransferPackets) && (fdoData->NumTotalTransferPackets > MinWorkingSetTransferPackets)){ pktToDelete = DequeueFreeTransferPacket(Fdo, FALSE); if (pktToDelete){ InterlockedDecrement(&fdoData->NumTotalTransferPackets); } else { DBGTRACE(ClassDebugTrace, ("Extremely unlikely condition (non-fatal): %d packets dequeued at once for Fdo %p. NumTotalTransferPackets=%d (2).", MinWorkingSetTransferPackets, Fdo, fdoData->NumTotalTransferPackets)); } } KeReleaseSpinLock(&fdoData->SpinLock, oldIrql); if (pktToDelete){ DestroyTransferPacket(pktToDelete); } } } }
void SmallSizeMemoryPool::Push(MemAllocInfo* ptr) { InterlockedPushEntrySList(&mFreeList, (PSLIST_ENTRY)ptr); InterlockedDecrement(&mAllocCount); }
void HttpInputQueueEnqueue(PHTTP_LISTENER listener, PHTTP_IO_CONTEXT context) { InterlockedPushEntrySList(&listener->HttpInputQueue->Header, &context->LookAsideEntry); }
int TestInterlockedSList(int argc, char* argv[]) { ULONG Count; WINPR_PSLIST_ENTRY pFirstEntry; WINPR_PSLIST_ENTRY pListEntry; WINPR_PSLIST_HEADER pListHead; PPROGRAM_ITEM pProgramItem; /* Initialize the list header to a MEMORY_ALLOCATION_ALIGNMENT boundary. */ pListHead = (WINPR_PSLIST_HEADER) _aligned_malloc(sizeof(WINPR_SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT); if (!pListHead) { printf("Memory allocation failed.\n"); return -1; } InitializeSListHead(pListHead); /* Insert 10 items into the list. */ for (Count = 1; Count <= 10; Count += 1) { pProgramItem = (PPROGRAM_ITEM) _aligned_malloc(sizeof(PROGRAM_ITEM), MEMORY_ALLOCATION_ALIGNMENT); if (!pProgramItem) { printf("Memory allocation failed.\n"); return -1; } pProgramItem->Signature = Count; pFirstEntry = InterlockedPushEntrySList(pListHead, &(pProgramItem->ItemEntry)); } /* Remove 10 items from the list and display the signature. */ for (Count = 10; Count >= 1; Count -= 1) { pListEntry = InterlockedPopEntrySList(pListHead); if (!pListEntry) { printf("List is empty.\n"); return -1; } pProgramItem = (PPROGRAM_ITEM) pListEntry; printf("Signature is %d\n", (int) pProgramItem->Signature); /* * This example assumes that the SLIST_ENTRY structure is the * first member of the structure. If your structure does not * follow this convention, you must compute the starting address * of the structure before calling the free function. */ _aligned_free(pListEntry); } /* Flush the list and verify that the items are gone. */ pListEntry = InterlockedFlushSList(pListHead); pFirstEntry = InterlockedPopEntrySList(pListHead); if (pFirstEntry) { printf("Error: List is not empty.\n"); return -1; } _aligned_free(pListHead); return 0; }
BOOLEAN ExRemoveHeadNBQueue ( IN PVOID Header, OUT PULONG64 Value ) /*++ Routine Description: This function removes a queue entry from the head of the specified non-blocking queue and returns the associated data value. Arguments: Header - Supplies an opaque pointer to a non-blocking queue header. Value - Supplies a pointer to a variable that receives the queue element value. Return Value: If an entry is removed from the specified non-blocking queue, then TRUE is returned as the function value. Otherwise, FALSE is returned. --*/ { NBQUEUE_POINTER Head; PNBQUEUE_NODE HeadNode; NBQUEUE_POINTER Insert; NBQUEUE_POINTER Next; PNBQUEUE_NODE NextNode; PNBQUEUE_HEADER QueueHead; NBQUEUE_POINTER Tail; PNBQUEUE_NODE TailNode; // // The following loop is executed until an entry can be removed from // the specified non-blocking queue or until it can be determined that // the queue is empty. // QueueHead = (PNBQUEUE_HEADER)Header; do { // // Read the head queue pointer, the tail queue pointer, and the // next queue pointer of the head queue pointer making sure the // three pointers are coherent. // Head.Data = ReadForWriteAccess((volatile LONG64 *)(&QueueHead->Head.Data)); Tail.Data = *((volatile LONG64 *)(&QueueHead->Tail.Data)); HeadNode = UnpackNBQPointer(&Head); Next.Data = *((volatile LONG64 *)(&HeadNode->Next.Data)); if (Head.Data == *((volatile LONG64 *)(&QueueHead->Head.Data))) { // // If the queue header node is equal to the queue tail node, // then either the queue is empty or the tail pointer is falling // behind. Otherwise, there is an entry in the queue that can // be removed. // NextNode = UnpackNBQPointer(&Next); TailNode = UnpackNBQPointer(&Tail); if (HeadNode == TailNode) { // // If the next node of head pointer is NULL, then the queue // is empty. Otherwise, attempt to move the tail forward. // if (NextNode == NULL) { return FALSE; } else { PackNBQPointer(&Insert, NextNode); Insert.Count = Tail.Count + 1; InterlockedCompareExchange64(&QueueHead->Tail.Data, Insert.Data, Tail.Data); } } else { // // There is an entry in the queue that can be removed. // *Value = NextNode->Value; PackNBQPointer(&Insert, NextNode); Insert.Count = Head.Count + 1; if (InterlockedCompareExchange64(&QueueHead->Head.Data, Insert.Data, Head.Data) == Head.Data) { break; } } } } while (TRUE); // // Free the node that was removed for the list by inserting the node // in the associated SLIST. // InterlockedPushEntrySList(QueueHead->SlistHead, (PSLIST_ENTRY)HeadNode); return TRUE; }
ULONG NTAPI MiFreePoolPages(IN PVOID StartingVa) { PMMPTE PointerPte, StartPte; PMMPFN Pfn1, StartPfn; PFN_COUNT FreePages, NumberOfPages; KIRQL OldIrql; PMMFREE_POOL_ENTRY FreeEntry, NextEntry, LastEntry; ULONG i, End; ULONG_PTR Offset; // // Handle paged pool // if ((StartingVa >= MmPagedPoolStart) && (StartingVa <= MmPagedPoolEnd)) { // // Calculate the offset from the beginning of paged pool, and convert it // into pages // Offset = (ULONG_PTR)StartingVa - (ULONG_PTR)MmPagedPoolStart; i = (ULONG)(Offset >> PAGE_SHIFT); End = i; // // Now use the end bitmap to scan until we find a set bit, meaning that // this allocation finishes here // while (!RtlTestBit(MmPagedPoolInfo.EndOfPagedPoolBitmap, End)) End++; // // Now calculate the total number of pages this allocation spans. If it's // only one page, add it to the S-LIST instead of freeing it // NumberOfPages = End - i + 1; if ((NumberOfPages == 1) && (ExQueryDepthSList(&MiPagedPoolSListHead) < MiPagedPoolSListMaximum)) { InterlockedPushEntrySList(&MiPagedPoolSListHead, StartingVa); return 1; } /* Delete the actual pages */ PointerPte = MmPagedPoolInfo.FirstPteForPagedPool + i; FreePages = MiDeleteSystemPageableVm(PointerPte, NumberOfPages, 0, NULL); ASSERT(FreePages == NumberOfPages); // // Acquire the paged pool lock // KeAcquireGuardedMutex(&MmPagedPoolMutex); // // Clear the allocation and free bits // RtlClearBit(MmPagedPoolInfo.EndOfPagedPoolBitmap, End); RtlClearBits(MmPagedPoolInfo.PagedPoolAllocationMap, i, NumberOfPages); // // Update the hint if we need to // if (i < MmPagedPoolInfo.PagedPoolHint) MmPagedPoolInfo.PagedPoolHint = i; // // Release the lock protecting the bitmaps // KeReleaseGuardedMutex(&MmPagedPoolMutex); // // And finally return the number of pages freed // return NumberOfPages; }
void SListImpl::push(SListEntry* entry) { InterlockedPushEntrySList(getDetail(this), reinterpret_cast<SLIST_ENTRY*>(entry)); }