void WorkQueue::SetWorkStatusComplete() { _InterlockedDecrement(&m_incompleteWork); // FIXME: No need to acquire the lock while wake up the condition variable ? // If the workqueue is waiting on the condition variable.. wake him up if (0 != _InterlockedExchangeAdd(&m_waitingForCompletion, 0) && 0 == _InterlockedExchangeAdd(&m_incompleteWork, 0)) { SetEvent(m_condCrit); } return; }
void* enAllocResize(void* m, int size) { // Check: if(m == 0) return enAllocMake(size); enAssert(size >= 0); // Update size: Block* b = (Block*) m - 1; #ifdef WIN32 _InterlockedExchangeAdd(&Size, (long) (- b->Size + size)); #else Size += (long) (- b->Size + size); #endif // Realloc block: b = (Block*) realloc(b, sizeof(Block) + size); m = b + 1; b->Size = size; // Return result: return m; }
/* * @implemented */ LONG WINAPI InterlockedExchangeAdd(IN OUT LONG volatile *Addend, IN LONG Value) { return _InterlockedExchangeAdd(Addend, Value); }
/* _Atomic_fetch_add_4, _Atomic_fetch_sub_4 */ static _Uint4_t _Fetch_add_seq_cst_4(volatile _Uint4_t *_Tgt, _Uint4_t _Value) { /* add _Value to *_Tgt atomically with sequentially consistent memory order */ _Value = _InterlockedExchangeAdd((volatile long *)_Tgt, _Value); return (_Value); }
LONG ImScsiCompletePendingSrbs( __in pHW_HBA_EXT pHBAExt // Adapter device-object extension from port driver. ) { pMP_WorkRtnParms pWkRtnParms; LONG done = 0; KdPrint2(("PhDskMnt::ImScsiCompletePendingSrbs start. pHBAExt = 0x%p\n", pHBAExt)); for (;;) { PLIST_ENTRY request = ExInterlockedRemoveHeadList(&pMPDrvInfoGlobal->ResponseList, &pMPDrvInfoGlobal->ResponseListLock); if (request == NULL) { LONG was_pending = _InterlockedExchangeAdd((volatile LONG*)&pHBAExt->WorkItems, -done); KdPrint2(("PhDskMnt::ImScsiCompletePendingSrbs finished.\n")); return was_pending - done; } ++done; pWkRtnParms = (pMP_WorkRtnParms)CONTAINING_RECORD(request, MP_WorkRtnParms, ResponseListEntry); KdPrint2(("PhDskMnt::ImScsiCompletePendingSrbs: Completing pWkRtnParms = 0x%p, pSrb = 0x%p\n", pWkRtnParms, pWkRtnParms->pSrb)); ScsiPortNotification(RequestComplete, pWkRtnParms->pHBAExt, pWkRtnParms->pSrb); ScsiPortNotification(NextRequest, pWkRtnParms->pHBAExt); ExFreePoolWithTag(pWkRtnParms, MP_TAG_GENERAL); // Free parm list. } }
// Adds a task set to the work queue VOID TaskScheduler::AddTaskSet( TASKSETHANDLE hSet, INT iTaskCount ) { // Increase the Task Count before adding the tasks to keep the // workers from going to sleep during this process _InterlockedExchangeAdd((LONG*)&miTaskCount,iTaskCount); // Looks for an open slot starting at the end of the queue INT iWriter = miWriter; do { while(mhActiveTaskSets[iWriter] != TASKSETHANDLE_INVALID) iWriter = (iWriter + 1) & (MAX_TASKSETS - 1); // verify that another thread hasn't already written to this slot } while(_InterlockedCompareExchange((LONG*)&mhActiveTaskSets[iWriter],hSet,TASKSETHANDLE_INVALID) != TASKSETHANDLE_INVALID); // Wake up all suspended threads LONG sleep_count = 0; ReleaseSemaphore(mhTaskAvailable,1,&sleep_count); INT iCountToWake = iTaskCount < (miThreadCount - sleep_count - 1) ? iTaskCount : miThreadCount - sleep_count - 1; ReleaseSemaphore(mhTaskAvailable,iCountToWake,&sleep_count); // reset the end of the queue miWriter = iWriter; }
void* enAllocMake(int size) { // Check: enAssert(size >= 0); // Alloc block: Block* b = (Block*) malloc(sizeof(Block) + size); void* m = b + 1; b->Size = size; // Update size: #ifdef WIN32 _InterlockedExchangeAdd(&Size, (long) size); #else Size += (long) size; #endif // Return result: return m; }
NTKERNELAPI LONG FASTCALL InterlockedExchangeAdd( LONG volatile *Target, LONG Value) { return _InterlockedExchangeAdd(Target, Value); }
long atomic_exchange_add(volatile long* value, long param) { #ifdef __GNUC__ return __sync_add_and_fetch(value, param); #else return _InterlockedExchangeAdd(value, param); #endif }
static ETHR_INLINE int wait(ethr_event *e, int spincount) { LONG state; DWORD code; int sc, res, until_yield = ETHR_YIELD_AFTER_BUSY_LOOPS; if (spincount < 0) ETHR_FATAL_ERROR__(EINVAL); sc = spincount; while (1) { long on; while (1) { #if ETHR_READ_AND_SET_WITHOUT_INTERLOCKED_OP__ state = e->state; #else state = _InterlockedExchangeAdd(&e->state, (LONG) 0); #endif if (state == ETHR_EVENT_ON__) return 0; if (sc == 0) break; sc--; ETHR_SPIN_BODY; if (--until_yield == 0) { until_yield = ETHR_YIELD_AFTER_BUSY_LOOPS; res = ETHR_YIELD(); if (res != 0) ETHR_FATAL_ERROR__(res); } } if (state != ETHR_EVENT_OFF_WAITER__) { state = _InterlockedCompareExchange(&e->state, ETHR_EVENT_OFF_WAITER__, ETHR_EVENT_OFF__); if (state == ETHR_EVENT_ON__) return 0; ETHR_ASSERT(state == ETHR_EVENT_OFF__); } code = WaitForSingleObject(e->handle, INFINITE); if (code != WAIT_OBJECT_0) ETHR_FATAL_ERROR__(ethr_win_get_errno__()); } }
LONG ImScsiCompletePendingSrbs( __in pHW_HBA_EXT pHBAExt, // Adapter device-object extension from port driver. __inout __deref PKIRQL LowestAssumedIrql ) { pMP_WorkRtnParms pWkRtnParms; LONG done = 0; KdPrint2(("PhDskMnt::ImScsiCompletePendingSrbs start. pHBAExt = 0x%p\n", pHBAExt)); for (;;) { KLOCK_QUEUE_HANDLE lock_handle; PLIST_ENTRY request; ImScsiAcquireLock(&pMPDrvInfoGlobal->ResponseListLock, &lock_handle, *LowestAssumedIrql); request = RemoveHeadList(&pMPDrvInfoGlobal->ResponseList); if (request == &pMPDrvInfoGlobal->ResponseList) { request = NULL; } ImScsiReleaseLock(&lock_handle, LowestAssumedIrql); if (request == NULL) { LONG was_pending = _InterlockedExchangeAdd((volatile LONG*)&pHBAExt->WorkItems, -done); KdPrint2(("PhDskMnt::ImScsiCompletePendingSrbs finished.\n")); return was_pending - done; } ++done; pWkRtnParms = (pMP_WorkRtnParms)CONTAINING_RECORD(request, MP_WorkRtnParms, ResponseListEntry); KdPrint2(("PhDskMnt::ImScsiCompletePendingSrbs: Completing pWkRtnParms = 0x%p, pSrb = 0x%p\n", pWkRtnParms, pWkRtnParms->pSrb)); ScsiPortNotification(RequestComplete, pWkRtnParms->pHBAExt, pWkRtnParms->pSrb); ScsiPortNotification(NextRequest, pWkRtnParms->pHBAExt); ExFreePoolWithTag(pWkRtnParms, MP_TAG_GENERAL); // Free parm list. } }
void DB_LoadXAssets_Hook(XZoneInfo *zoneinfo, unsigned int assetscount) { int i; DB_FreeUnusedResources(); for(i = 0; i < assetscount; i++) { DB_UnloadFastFile( zoneinfo[i].notknown ); } _InterlockedExchangeAdd(&g_unknownVar_1, -1); g_archiveBuf = 0; DB_LoadSounds(); DB_LoadDObjs(); Material_DirtyTechniqueSetOverrides(); BG_FillInAllWeaponItems(); }
/** * Dereferences the specified object. * The object will be freed if its reference count reaches 0. * * \param Object A pointer to the object to dereference. * \param RefCount The number of references to remove. * \param DeferDelete Whether to defer deletion of the object. * * \return The new reference count of the object. */ __mayRaise LONG PhDereferenceObjectEx( __in PVOID Object, __in LONG RefCount, __in BOOLEAN DeferDelete ) { PPH_OBJECT_HEADER objectHeader; LONG oldRefCount; LONG newRefCount; #ifdef PHOBJ_STRICT_CHECKS /* Make sure we're not subtracting a negative reference count. */ if (RefCount < 0) PhRaiseStatus(STATUS_INVALID_PARAMETER_2); #else assert(!(RefCount < 0)); #endif objectHeader = PhObjectToObjectHeader(Object); /* Decrease the reference count. */ oldRefCount = _InterlockedExchangeAdd(&objectHeader->RefCount, -RefCount); newRefCount = oldRefCount - RefCount; /* Free the object if it has 0 references. */ if (newRefCount == 0) { if (DeferDelete) { PhpDeferDeleteObject(objectHeader); } else { /* Free the object. */ PhpFreeObject(objectHeader); } } else if (newRefCount < 0) { PhRaiseStatus(STATUS_INVALID_PARAMETER); } return newRefCount; }
void UCTParallel::search_uct_root(Board& board, const Color color, UCTNode* node, UCTNode* copychild) { // UCBからプレイアウトする手を選択 // rootノードはアトミックに更新するためUCB計算ではロックしない UCTNode* selected_node = select_node_with_ucb(node); // rootでは全て合法手なのでエラーチェックはしない board.move_legal(selected_node->xy, color); // コピーされたノードに変換 UCTNode* selected_node_copy = copychild + (selected_node - node->child); int win; // 閾値以下の場合プレイアウト(全スレッドの合計値) if (selected_node->playout_num < THR) { win = 1 - playout(board, opponent(color)); } else { if (selected_node_copy->child_num == 0) { // ノードを展開 if (selected_node_copy->expand_node(board)) { win = 1 - search_uct(board, opponent(color), selected_node_copy); } else { // ノードプール不足 win = 1 - playout(board, opponent(color)); } } else { win = 1 - search_uct(board, opponent(color), selected_node_copy); } } // 勝率を更新(アトミックに加算) _InterlockedExchangeAdd(&selected_node->win_num, win); _InterlockedIncrement(&selected_node->playout_num); _InterlockedIncrement(&node->playout_num_sum); }
void enAllocKill(void* m) { // Check m: if(m == 0) return; // Update total: Block* b = (Block*) m - 1; #ifdef WIN32 _InterlockedExchangeAdd(&Size, (long) (- b->Size)); #else Size += (long) - b->Size; #endif // Free block: free(b); }
BOOL Condition::Wait(DWORD timeout) { // 参考程度の空き開始位置調査 // (正確な確認は、INIT_EVENT <-> WAIT_EVENT の CAS で) u_int idx = get_ntz(_InterlockedExchangeAdd(&gEventMap, 0)); u_int self_bit = 0; if (idx >= MaxThreads) idx = 0; int count = 0; while (count < MaxThreads) { if (InterlockedCompareExchange(&gEvents[idx].kind, WAIT_EVENT, INIT_EVENT) == INIT_EVENT) { self_bit = 1 << idx; _InterlockedAnd(&gEventMap, ~self_bit); break; } if (++idx == MaxThreads) idx = 0; count++; } if (count >= MaxThreads) { // 通常はありえない MessageBox(0, "Detect too many wait threads", "TLib", MB_OK); return FALSE; } Event &event = gEvents[idx]; if (event.hEvent == NULL) { event.hEvent = ::CreateEvent(0, FALSE, FALSE, NULL); } waitBits |= self_bit; UnLock(); DWORD status = ::WaitForSingleObject(event.hEvent, timeout); Lock(); waitBits &= ~self_bit; InterlockedExchange(&event.kind, INIT_EVENT); _InterlockedOr(&gEventMap, self_bit); return status == WAIT_TIMEOUT ? FALSE : TRUE; }
/** * References the specified object. * * \param Object A pointer to the object to reference. * \param RefCount The number of references to add. * * \return The new reference count of the object. */ __mayRaise LONG PhReferenceObjectEx( __in PVOID Object, __in LONG RefCount ) { PPH_OBJECT_HEADER objectHeader; LONG oldRefCount; #ifdef PHOBJ_STRICT_CHECKS /* Make sure we're not adding a negative reference count. */ if (RefCount < 0) PhRaiseStatus(STATUS_INVALID_PARAMETER_2); #else assert(!(RefCount < 0)); #endif objectHeader = PhObjectToObjectHeader(Object); /* Increase the reference count. */ oldRefCount = _InterlockedExchangeAdd(&objectHeader->RefCount, RefCount); return oldRefCount + RefCount; }
BOOLEAN MpHwStartIo( __in pHW_HBA_EXT pHBAExt, // Adapter device-object extension from port driver. __in __out PSCSI_REQUEST_BLOCK pSrb ) { UCHAR Result = ResultDone; #ifdef USE_SCSIPORT UCHAR PathId = pSrb->PathId; UCHAR TargetId = pSrb->TargetId; UCHAR Lun = pSrb->Lun; #endif KdPrint2(("PhDskMnt::MpHwStartIo: pHBAExt = 0x%p, pSrb = 0x%p, Path=%i, Target=%i, Lun=%i, IRQL=%i\n", pHBAExt, pSrb, (int) pSrb->PathId, (int) pSrb->TargetId, (int) pSrb->Lun, KeGetCurrentIrql())); pSrb->SrbStatus = SRB_STATUS_PENDING; pSrb->ScsiStatus = SCSISTAT_GOOD; ImScsiCompletePendingSrbs(pHBAExt); _InterlockedExchangeAdd((volatile LONG *)&pHBAExt->SRBsSeen, 1); // Bump count of SRBs encountered. // Next, if true, will cause port driver to remove the associated LUNs if, for example, devmgmt.msc is asked "scan for hardware changes." //if (pHBAExt->bDontReport) //{ // Act as though the HBA/path is gone? // pSrb->SrbStatus = SRB_STATUS_INVALID_LUN; // goto done; //} switch (pSrb->Function) { case SRB_FUNCTION_IO_CONTROL: ScsiIoControl(pHBAExt, pSrb, &Result); break; case SRB_FUNCTION_EXECUTE_SCSI: ScsiExecute(pHBAExt, pSrb, &Result); break; case SRB_FUNCTION_RESET_LOGICAL_UNIT: DbgPrint("PhDskMnt::MpHwStartIo: SRB_FUNCTION_RESET_LOGICAL_UNIT.\n"); pSrb->SrbStatus = ScsiResetLun(pHBAExt, pSrb); break; case SRB_FUNCTION_RESET_DEVICE: DbgPrint("PhDskMnt::MpHwStartIo: SRB_FUNCTION_RESET_DEVICE.\n"); pSrb->SrbStatus = ScsiResetDevice(pHBAExt, pSrb); break; case SRB_FUNCTION_RESET_BUS: DbgPrint("PhDskMnt::MpHwStartIo: SRB_FUNCTION_RESET_BUS.\n"); pSrb->SrbStatus = MpHwResetBus(pHBAExt, pSrb->PathId); break; case SRB_FUNCTION_PNP: MpHwHandlePnP(pHBAExt, (PSCSI_PNP_REQUEST_BLOCK)pSrb); break; case SRB_FUNCTION_POWER: KdPrint(("PhDskMnt::MpHwStartIo: SRB_FUNCTION_POWER.\n")); // Do nothing. pSrb->SrbStatus = SRB_STATUS_SUCCESS; break; case SRB_FUNCTION_SHUTDOWN: KdPrint(("PhDskMnt::MpHwStartIo: SRB_FUNCTION_SHUTDOWN.\n")); // Do nothing. pSrb->SrbStatus = SRB_STATUS_SUCCESS; break; default: KdPrint(("PhDskMnt::MpHwStartIo: Unknown pSrb Function = 0x%x\n", pSrb->Function)); ScsiSetCheckCondition(pSrb, SRB_STATUS_ERROR, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ADSENSE_ILLEGAL_COMMAND, 0); break; } // switch (pSrb->Function) if (Result == ResultDone) { // Complete now? // Note: A miniport with real hardware would not always be calling RequestComplete from HwScsiStartIo. Rather, // the miniport would typically be doing real I/O and would call RequestComplete only at the end of that // real I/O, in its HwScsiInterrupt or in a DPC routine. #ifdef USE_SCSIPORT KdPrint2(("PhDskMnt::MpHwStartIo sending 'RequestComplete', 'NextRequest' and 'NextLuRequest' to ScsiPort.\n")); ScsiPortNotification(RequestComplete, pHBAExt, pSrb); ScsiPortNotification(NextRequest, pHBAExt); ScsiPortNotification(NextLuRequest, pHBAExt, 0, 0, 0); #endif #ifdef USE_STORPORT KdPrint2(("PhDskMnt::MpHwStartIo sending 'RequestComplete' to port StorPort.\n")); StorPortNotification(RequestComplete, pHBAExt, pSrb); #endif } else { #ifdef USE_SCSIPORT _InterlockedExchangeAdd((volatile LONG*)&pHBAExt->WorkItems, 1); KdPrint2(("PhDskMnt::MpHwStartIo sending 'RequestTimerCall' and 'NextLuRequest' to ScsiPort.\n")); ScsiPortNotification(RequestTimerCall, pHBAExt, MpHwTimer, (ULONG) 1); ScsiPortNotification(NextLuRequest, pHBAExt, PathId, TargetId, Lun); ScsiPortNotification(NextLuRequest, pHBAExt, 0, 0, 0); #endif } KdPrint2(("PhDskMnt::MpHwStartIo End.\n")); return TRUE; } // End MpHwStartIo().
Int32 KInterlockedExchangeAdd(Int32 volatile* var, Int32 add) { return _InterlockedExchangeAdd((volatile long*)var, add); }
int32_t sk_atomic_add(int32_t* addr, int32_t inc) { return _InterlockedExchangeAdd(reinterpret_cast<LONG*>(addr), static_cast<LONG>(inc)); }
BOOLEAN MpHwStartIo( __in PVOID DeviceExtension, // Adapter device-object extension from port driver. __inout __deref PSCSI_REQUEST_BLOCK pSrb ) { KIRQL lowest_assumed_irql = PASSIVE_LEVEL; ResultType Result = ResultDone; pHW_HBA_EXT pHBAExt = (pHW_HBA_EXT)DeviceExtension; #ifdef USE_SCSIPORT UCHAR PathId = pSrb->PathId; UCHAR TargetId = pSrb->TargetId; UCHAR Lun = pSrb->Lun; #endif KdPrint2(("PhDskMnt::MpHwStartIo: pHBAExt = 0x%p, pSrb = 0x%p, Path=%i, Target=%i, Lun=%i, IRQL=%i\n", pHBAExt, pSrb, (int)pSrb->PathId, (int)pSrb->TargetId, (int)pSrb->Lun, KeGetCurrentIrql())); pSrb->SrbStatus = SRB_STATUS_PENDING; pSrb->ScsiStatus = SCSISTAT_GOOD; ImScsiCompletePendingSrbs(pHBAExt, &lowest_assumed_irql); _InterlockedExchangeAdd((volatile LONG *)&pHBAExt->SRBsSeen, 1); // Bump count of SRBs encountered. // Next, if true, will cause port driver to remove the associated LUNs if, for example, devmgmt.msc is asked "scan for hardware changes." //if (pHBAExt->bDontReport) //{ // Act as though the HBA/path is gone? // pSrb->SrbStatus = SRB_STATUS_NO_DEVICE; // goto done; //} switch (pSrb->Function) { case SRB_FUNCTION_IO_CONTROL: ScsiIoControl(pHBAExt, pSrb, &Result, &lowest_assumed_irql); break; case SRB_FUNCTION_EXECUTE_SCSI: if (pSrb->Cdb[0] == SCSIOP_REPORT_LUNS) { ScsiOpReportLuns(pHBAExt, pSrb, &lowest_assumed_irql); } else { ScsiExecute(pHBAExt, pSrb, &Result, &lowest_assumed_irql); } break; case SRB_FUNCTION_RESET_LOGICAL_UNIT: DbgPrint("PhDskMnt::MpHwStartIo: SRB_FUNCTION_RESET_LOGICAL_UNIT.\n"); pSrb->SrbStatus = ScsiResetLun(pHBAExt, pSrb); break; case SRB_FUNCTION_RESET_DEVICE: DbgPrint("PhDskMnt::MpHwStartIo: SRB_FUNCTION_RESET_DEVICE.\n"); pSrb->SrbStatus = ScsiResetDevice(pHBAExt, pSrb); break; case SRB_FUNCTION_RESET_BUS: DbgPrint("PhDskMnt::MpHwStartIo: SRB_FUNCTION_RESET_BUS.\n"); pSrb->SrbStatus = MpHwResetBus(pHBAExt, pSrb->PathId); break; case SRB_FUNCTION_PNP: ScsiPnP(pHBAExt, (PSCSI_PNP_REQUEST_BLOCK)pSrb, &lowest_assumed_irql); break; case SRB_FUNCTION_POWER: KdPrint(("PhDskMnt::MpHwStartIo: SRB_FUNCTION_POWER.\n")); // Do nothing. pSrb->SrbStatus = SRB_STATUS_SUCCESS; break; case SRB_FUNCTION_SHUTDOWN: KdPrint(("PhDskMnt::MpHwStartIo: SRB_FUNCTION_SHUTDOWN.\n")); // Do nothing. pSrb->SrbStatus = SRB_STATUS_SUCCESS; break; default: KdPrint(("PhDskMnt::MpHwStartIo: Unknown pSrb Function = 0x%X\n", pSrb->Function)); //StorPortLogError(pHBAExt, pSrb, pSrb->PathId, pSrb->TargetId, pSrb->Lun, SP_PROTOCOL_ERROR, 0x0200 | pSrb->Cdb[0]); ScsiSetCheckCondition(pSrb, SRB_STATUS_ERROR, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ADSENSE_ILLEGAL_COMMAND, 0); break; } // switch (pSrb->Function) if (Result == ResultDone) { // Complete now? #ifdef USE_SCSIPORT KdPrint2(("PhDskMnt::MpHwStartIo sending 'RequestComplete', 'NextRequest' and 'NextLuRequest' to ScsiPort.\n")); ScsiPortNotification(RequestComplete, pHBAExt, pSrb); ScsiPortNotification(NextRequest, pHBAExt); ScsiPortNotification(NextLuRequest, pHBAExt, 0, 0, 0); #endif #ifdef USE_STORPORT KdPrint2(("PhDskMnt::MpHwStartIo sending 'RequestComplete' to port StorPort.\n")); StorPortNotification(RequestComplete, pHBAExt, pSrb); #endif } else { #ifdef USE_SCSIPORT _InterlockedExchangeAdd((volatile LONG*)&pHBAExt->WorkItems, 1); KdPrint2(("PhDskMnt::MpHwStartIo sending 'RequestTimerCall' and 'NextLuRequest' to ScsiPort.\n")); ScsiPortNotification(RequestTimerCall, pHBAExt, MpHwTimer, (ULONG)1); ScsiPortNotification(NextLuRequest, pHBAExt, PathId, TargetId, Lun); ScsiPortNotification(NextLuRequest, pHBAExt, 0, 0, 0); #endif } KdPrint2(("PhDskMnt::MpHwStartIo End.\n")); return TRUE; } // End MpHwStartIo().
BOOL TaskMgrSS::CreateTaskSet(TASKSETFUNC pFunc, VOID* pArg, UINT uTaskCount, TASKSETHANDLE* pInDepends, UINT uInDepends, OPTIONAL LPCSTR szSetName, TASKSETHANDLE* pOutHandle ) { TASKSETHANDLE hSet; TASKSETHANDLE hSetParent = TASKSETHANDLE_INVALID; TASKSETHANDLE* pDepends = pInDepends; UINT uDepends = uInDepends; BOOL bResult = FALSE; // Validate incomming parameters if( 0 == uTaskCount || NULL == pFunc ) { return FALSE; } // // Allocate and setup the internal taskset // hSet = AllocateTaskSet(); mSets[ hSet ].muRefCount = 2; mSets[ hSet ].muStartCount = uDepends; mSets[ hSet ].mpvArg = pArg; mSets[ hSet ].muSize = uTaskCount; mSets[ hSet ].muCompletionCount = uTaskCount; mSets[ hSet ].muTaskId = uTaskCount; mSets[ hSet ].mhTaskset = hSet; mSets[ hSet ].mpFunc = pFunc; mSets[ hSet ].mbCompleted = FALSE; //mSets[ hSet ].mhAssignedSlot = TASKSETHANDLE_INVALID; #ifdef PROFILEGPA // // Track task name if profiling is enabled if( szSetName ) { StringCbCopyA( mSets[ hSet ].mszSetName, sizeof( mSets[ hSet ].mszSetName ), szSetName ); } else { StringCbCopyA( mSets[ hSet ].mszSetName, sizeof( mSets[ hSet ].mszSetName ), "Unnamed Task" ); } #else UNREFERENCED_PARAMETER( szSetName ); #endif // PROFILEGPA // // Iterate over the dependency list and setup the successor // pointers in each parent to point to this taskset. // if(uDepends == 0) { mTaskScheduler.AddTaskSet( hSet, uTaskCount ); } else for( UINT uDepend = 0; uDepend < uDepends; ++uDepend ) { TASKSETHANDLE hDependsOn = pDepends[ uDepend ]; if(hDependsOn == TASKSETHANDLE_INVALID) continue; TaskSet *pDependsOn = &mSets[ hDependsOn ]; LONG lPrevCompletion; // // A taskset with a new successor is consider incomplete even if it // already has completed. This mechanism allows us tasksets that are // already done to appear active and capable of spawning successors. // lPrevCompletion = _InterlockedExchangeAdd( (LONG*)&pDependsOn->muCompletionCount, 1 ); pDependsOn->mSuccessorsLock.aquire(); UINT uSuccessor; for( uSuccessor = 0; uSuccessor < MAX_SUCCESSORS; ++uSuccessor ) { if( NULL == pDependsOn->Successors[ uSuccessor ] ) { pDependsOn->Successors[ uSuccessor ] = &mSets[ hSet ]; break; } } // // If the successor list is full we have a problem. The app // needs to give us more space by increasing MAX_SUCCESSORS // if( uSuccessor == MAX_SUCCESSORS ) { printf( "Too many successors for this task set.\nIncrease MAX_SUCCESSORS\n" ); pDependsOn->mSuccessorsLock.release(); goto Cleanup; } pDependsOn->mSuccessorsLock.release(); // // Mark the set as completed for the successor adding operation. // CompleteTaskSet( hDependsOn ); } // Set output taskset handle *pOutHandle = hSet; bResult = TRUE; Cleanup: return bResult; }
long test_InterlockedExchangeAdd(long volatile *value, long mask) { return _InterlockedExchangeAdd(value, mask); }
LONG test_InterlockedExchangeAdd(LONG volatile *value, LONG mask) { return _InterlockedExchangeAdd(value, mask); }
intptr_t cpu_AtomicAdd(volatile intptr_t* location, intptr_t increment) { return _InterlockedExchangeAdd((P32)location, increment); }
ULONG NTAPI SmpApiLoop(IN PVOID Parameter) { HANDLE SmApiPort = (HANDLE)Parameter; NTSTATUS Status; PSMP_CLIENT_CONTEXT ClientContext; PSM_API_MSG ReplyMsg = NULL; SM_API_MSG RequestMsg; PROCESS_BASIC_INFORMATION ProcessInformation; LARGE_INTEGER Timeout; /* Increase the number of API threads for throttling code for later */ _InterlockedExchangeAdd(&SmTotalApiThreads, 1); /* Mark us critical */ RtlSetThreadIsCritical(TRUE, NULL, TRUE); /* Set the PID of the SM process itself for later checking */ NtQueryInformationProcess(NtCurrentProcess(), ProcessBasicInformation, &ProcessInformation, sizeof(ProcessInformation), NULL); SmUniqueProcessId = (HANDLE)ProcessInformation.UniqueProcessId; /* Now process incoming messages */ while (TRUE) { /* Begin waiting on a request */ Status = NtReplyWaitReceivePort(SmApiPort, (PVOID*)&ClientContext, &ReplyMsg->h, &RequestMsg.h); if (Status == STATUS_NO_MEMORY) { /* Ran out of memory, so do a little timeout and try again */ if (ReplyMsg) DPRINT1("SMSS: Failed to reply to calling thread, retrying.\n"); Timeout.QuadPart = -50000000; NtDelayExecution(FALSE, &Timeout); continue; } /* Check what kind of request we received */ switch (RequestMsg.h.u2.s2.Type) { /* A new connection */ case LPC_CONNECTION_REQUEST: /* Create the right structures for it */ SmpHandleConnectionRequest(SmApiPort, (PSB_API_MSG)&RequestMsg); ReplyMsg = NULL; break; /* A closed connection */ case LPC_PORT_CLOSED: /* Destroy any state we had for this client */ DPRINT1("Port closed\n"); //if (ClientContext) SmpPushDeferredClientContext(ClientContext); ReplyMsg = NULL; break; /* An actual API message */ default: if (!ClientContext) { ReplyMsg = NULL; break; } RequestMsg.ReturnValue = STATUS_PENDING; /* Check if the API is valid */ if (RequestMsg.ApiNumber >= SmpMaxApiNumber) { /* It isn't, fail */ DPRINT1("Invalid API: %lx\n", RequestMsg.ApiNumber); Status = STATUS_NOT_IMPLEMENTED; } else if ((RequestMsg.ApiNumber <= SmpTerminateForeignSessionApi) && !(ClientContext->Subsystem)) { /* It's valid, but doesn't have a subsystem with it */ DPRINT1("Invalid session API\n"); Status = STATUS_INVALID_PARAMETER; } else { /* It's totally okay, so call the dispatcher for it */ Status = SmpApiDispatch[RequestMsg.ApiNumber](&RequestMsg, ClientContext, SmApiPort); } /* Write the result valud and return the message back */ RequestMsg.ReturnValue = Status; ReplyMsg = &RequestMsg; break; } } return STATUS_SUCCESS; }