void cm_InitCell(int newFile, long maxCells) { static osi_once_t once; if (osi_Once(&once)) { cm_cell_t * cellp; lock_InitializeRWLock(&cm_cellLock, "cell global lock", LOCK_HIERARCHY_CELL_GLOBAL); if ( newFile ) { cm_data.allCellsp = NULL; cm_data.currentCells = 0; cm_data.maxCells = maxCells; memset(cm_data.cellNameHashTablep, 0, sizeof(cm_cell_t *) * cm_data.cellHashTableSize); memset(cm_data.cellIDHashTablep, 0, sizeof(cm_cell_t *) * cm_data.cellHashTableSize); #ifdef AFS_FREELANCE_CLIENT /* Generate a dummy entry for the Freelance cell whether or not * freelance mode is being used in this session */ cellp = &cm_data.cellBaseAddress[cm_data.currentCells++]; memset(cellp, 0, sizeof(cm_cell_t)); cellp->magic = CM_CELL_MAGIC; lock_InitializeMutex(&cellp->mx, "cm_cell_t mutex", LOCK_HIERARCHY_CELL); lock_ObtainMutex(&cellp->mx); lock_ObtainWrite(&cm_cellLock); /* copy in name */ strncpy(cellp->name, "Freelance.Local.Cell", CELL_MAXNAMELEN); /*safe*/ cellp->name[CELL_MAXNAMELEN-1] = '\0'; /* thread on global list */ cellp->allNextp = cm_data.allCellsp; cm_data.allCellsp = cellp; cellp->cellID = AFS_FAKE_ROOT_CELL_ID; cellp->vlServersp = NULL; _InterlockedOr(&cellp->flags, CM_CELLFLAG_FREELANCE); cm_AddCellToNameHashTable(cellp); cm_AddCellToIDHashTable(cellp); lock_ReleaseWrite(&cm_cellLock); lock_ReleaseMutex(&cellp->mx); #endif } else { lock_ObtainRead(&cm_cellLock); for (cellp = cm_data.allCellsp; cellp; cellp=cellp->allNextp) { lock_InitializeMutex(&cellp->mx, "cm_cell_t mutex", LOCK_HIERARCHY_CELL); cellp->vlServersp = NULL; _InterlockedOr(&cellp->flags, CM_CELLFLAG_VLSERVER_INVALID); } lock_ReleaseRead(&cm_cellLock); } osi_EndOnce(&once); } }
/* must be called with sleep bucket locked. * Frees the structure if it has a 0 reference count (and removes it * from the hash bucket). Otherwise, we simply mark the item * for deleting when the ref count hits zero. */ void osi_FreeSleepInfo(osi_sleepInfo_t *sp) { LONG_PTR idx; if (sp->refCount > 0) { TlsSetValue(osi_SleepSlot, NULL); /* don't reuse me */ _InterlockedOr(&sp->states, OSI_SLEEPINFO_DELETED); return; } /* remove from hash if still there */ if (sp->states & OSI_SLEEPINFO_INHASH) { idx = osi_SLEEPHASH(sp->value); osi_QRemoveHT((osi_queue_t **) &osi_sleepers[idx], (osi_queue_t **) &osi_sleepersEnd[idx], &sp->q); _InterlockedAnd(&sp->states, ~OSI_SLEEPINFO_INHASH); } if (sp->states & OSI_SLEEPINFO_DELETED) { EnterCriticalSection(&osi_sleepInfoAllocCS); sp->q.nextp = (osi_queue_t *) osi_sleepInfoFreeListp; osi_sleepInfoFreeListp = sp; _InterlockedAnd(&sp->states, ~OSI_SLEEPINFO_DELETED); InterlockedIncrement(&osi_sleepInfoCount); LeaveCriticalSection(&osi_sleepInfoAllocCS); } }
/*----------------------------------------------------------------------------*/ VOID sdioINTerruptCallback(IN PVOID context, IN UINT_32 u4INTerruptType) { P_GLUE_INFO_T prGlueInfo; PDEVICE_EXTENSION prDevExt; NTSTATUS rStatus; ASSERT(context); prGlueInfo = (P_GLUE_INFO_T) context; prDevExt = (PDEVICE_EXTENSION) &prGlueInfo->rHifInfo.dx; if (prGlueInfo->rHifInfo.u4ReqFlag & REQ_FLAG_HALT) { if (prDevExt->BusInterface.AcknowledgeInterrupt) rStatus = (prDevExt->BusInterface.AcknowledgeInterrupt) (prDevExt->BusInterface.Context); return; } wlanISR(prGlueInfo->prAdapter, TRUE); if (prDevExt->BusInterface.AcknowledgeInterrupt) rStatus = (prDevExt->BusInterface.AcknowledgeInterrupt) (prDevExt->BusInterface.Context); _InterlockedOr(&prGlueInfo->rHifInfo.u4ReqFlag, REQ_FLAG_INT); /* KeSetEvent(&prGlueInfo->rHifInfo.rOidReqEvent, EVENT_INCREMENT, FALSE); */ /* Set EVENT */ NdisSetEvent(&prGlueInfo->rTxReqEvent); return; } /* end of sdioINTerruptCallback() */
// This is meant to be called from the main thread only. void RequestSuspension() { if (!g_SuspensionRequested) { if (!ResetEvent(g_hResumeFromSuspension)) { exit(GetLastError()); } _InterlockedOr(&g_SuspensionRequested, 1); } }
/* _Atomic_load_4 */ static _Uint4_t _Load_seq_cst_4(volatile _Uint4_t *_Tgt) { /* load from *_Tgt atomically with sequentially consistent memory order */ _Uint4_t _Value; _Value = _InterlockedOr((volatile long *)_Tgt, 0); return (_Value); }
/* like TSignal, only wake *everyone* */ void osi_TBroadcast(osi_turnstile_t *turnp) { osi_sleepInfo_t *sp; while(sp = turnp->lastp) { osi_QRemoveHT((osi_queue_t **) &turnp->firstp, (osi_queue_t **) &turnp->lastp, &sp->q); _InterlockedOr(&sp->states, OSI_SLEEPINFO_SIGNALLED); ReleaseSemaphore(sp->sema, 1, NULL); } /* while someone's still asleep */ }
/* must be called with a critical section held that guards the turnstile * structure. We remove the sleepInfo structure from the queue so we don't * wake the guy again, but we don't free it because we're still using the * semaphore until the guy waiting wakes up. */ void osi_TSignal(osi_turnstile_t *turnp) { osi_sleepInfo_t *sp; if (!turnp->lastp) return; sp = turnp->lastp; osi_QRemoveHT((osi_queue_t **) &turnp->firstp, (osi_queue_t **) &turnp->lastp, &sp->q); _InterlockedOr(&sp->states, OSI_SLEEPINFO_SIGNALLED); ReleaseSemaphore(sp->sema, 1, NULL); }
unsigned Atomic::OR(unsigned value) { #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) return __sync_fetch_and_or(&_value, value); #elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) return _InterlockedOr(&_value, value); #elif defined(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC) return OSAtomicOr32((uint32_t)value, (uint32_t *)&_value); #else # error This implementation should happen inline in the include file #endif }
/* utility function to atomically (with respect to WakeSched) * release an atomic counter spin lock and sleep on an * address (value). * Called with no locks held. */ void osi_SleepSpin(LONG_PTR sleepValue, CRITICAL_SECTION *releasep) { int code; osi_sleepInfo_t *sp; CRITICAL_SECTION *csp; sp = TlsGetValue(osi_SleepSlot); if (sp == NULL) { sp = osi_AllocSleepInfo(); TlsSetValue(osi_SleepSlot, sp); } else { _InterlockedAnd(&sp->states, 0); } sp->waitFor = 0; sp->value = sleepValue; sp->tidp = NULL; sp->idx = osi_SLEEPHASH(sleepValue); csp = &osi_critSec[sp->idx]; EnterCriticalSection(csp); osi_QAddT((osi_queue_t **) &osi_sleepers[sp->idx], (osi_queue_t **) &osi_sleepersEnd[sp->idx], &sp->q); _InterlockedOr(&sp->states, OSI_SLEEPINFO_INHASH); LeaveCriticalSection(csp); LeaveCriticalSection(releasep); InterlockedIncrement(&osi_totalSleeps); /* stats */ while(1) { /* wait */ code = WaitForSingleObject(sp->sema, /* timeout */ INFINITE); /* if the reason for the wakeup was that we were signalled, * break out, otherwise try again, since the semaphore count is * decreased only when we get WAIT_OBJECT_0 back. */ if (code == WAIT_OBJECT_0) break; } /* now clean up */ EnterCriticalSection(csp); /* must be signalled */ osi_assert(sp->states & OSI_SLEEPINFO_SIGNALLED); /* free the sleep structure, must be done under bucket lock * so that we can check reference count and serialize with * those who change it. */ osi_FreeSleepInfo(sp); LeaveCriticalSection(csp); }
void SL_AddUser(uint16_t string, int user) { ScriptStringManagementData* data = slStrings[string].data; if (data) { SL_Debug("SL_AddUser: %i '%s' %i\n", string, slStrings[string].string, user); if (!(data->users & user)) { SL_AddRefToString(string); } _InterlockedOr((long*)&data->users, user); } }
/* call with cell write-locked and mutex held */ void cm_AddCellToIDHashTable(cm_cell_t *cellp) { int i; lock_AssertWrite(&cm_cellLock); lock_AssertMutex(&cellp->mx); if (cellp->flags & CM_CELLFLAG_IN_IDHASH) return; i = CM_CELL_ID_HASH(cellp->cellID); cellp->idNextp = cm_data.cellIDHashTablep[i]; cm_data.cellIDHashTablep[i] = cellp; _InterlockedOr(&cellp->flags, CM_CELLFLAG_IN_IDHASH); }
/* call with volume write-locked and mutex held */ void cm_AddCellToNameHashTable(cm_cell_t *cellp) { int i; lock_AssertWrite(&cm_cellLock); lock_AssertMutex(&cellp->mx); if (cellp->flags & CM_CELLFLAG_IN_NAMEHASH) return; i = CM_CELL_NAME_HASH(cellp->name); cellp->nameNextp = cm_data.cellNameHashTablep[i]; cm_data.cellNameHashTablep[i] = cellp; _InterlockedOr(&cellp->flags, CM_CELLFLAG_IN_NAMEHASH); }
/* utility function to wakeup someone sleeping in SleepSched */ void osi_WakeupSpin(LONG_PTR sleepValue) { LONG_PTR idx; CRITICAL_SECTION *csp; osi_sleepInfo_t *tsp; idx = osi_SLEEPHASH(sleepValue); csp = &osi_critSec[idx]; EnterCriticalSection(csp); for(tsp=osi_sleepers[idx]; tsp; tsp=(osi_sleepInfo_t *) osi_QNext(&tsp->q)) { if ((!(tsp->states & (OSI_SLEEPINFO_DELETED|OSI_SLEEPINFO_SIGNALLED))) && tsp->value == sleepValue) { _InterlockedOr(&tsp->states, OSI_SLEEPINFO_SIGNALLED); ReleaseSemaphore(tsp->sema, 1, NULL); } } LeaveCriticalSection(csp); }
static void cm_MarkServerDown(cm_server_t *tsp, afs_int32 code, int wasDown) { /* mark server as down */ if (!(tsp->flags & CM_SERVERFLAG_DOWN)) { _InterlockedOr(&tsp->flags, CM_SERVERFLAG_DOWN); tsp->downTime = time(NULL); } if (code != VRESTARTING) { lock_ReleaseMutex(&tsp->mx); cm_ForceNewConnections(tsp); lock_ObtainMutex(&tsp->mx); } /* Now update the volume status if necessary */ if (!wasDown) { if (tsp->type == CM_SERVER_FILE) { cm_server_vols_t * tsrvp; cm_volume_t * volp; int i; cm_req_t req; for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) { for (i=0; i<NUM_SERVER_VOLS; i++) { if (tsrvp->ids[i] != 0) { cm_InitReq(&req); lock_ReleaseMutex(&tsp->mx); code = cm_FindVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp, &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp); lock_ObtainMutex(&tsp->mx); if (code == 0) { cm_UpdateVolumeStatus(volp, tsrvp->ids[i]); cm_PutVolume(volp); } } } } } cm_RankServer(tsp); } }
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; }
/* _Atomic_fetch_or_4 */ _Uint4_t _Fetch_or_seq_cst_4(volatile _Uint4_t *_Tgt, _Uint4_t _Value) { /* or _Value with *_Tgt atomically with sequentially consistent memory order */ _Value = _InterlockedOr((volatile long *)_Tgt, _Value); return (_Value); }
cm_cell_t *cm_GetCell_Gen(char *namep, char *newnamep, afs_uint32 flags) { cm_cell_t *cp, *cp2; long code; char fullname[CELL_MAXNAMELEN]=""; char linkedName[CELL_MAXNAMELEN]=""; char name[CELL_MAXNAMELEN]=""; int hasWriteLock = 0; int hasMutex = 0; afs_uint32 hash; cm_cell_rock_t rock; size_t len; if (namep == NULL || !namep[0] || !strcmp(namep,CM_IOCTL_FILENAME_NOSLASH)) return NULL; /* * Strip off any trailing dots at the end of the cell name. * Failure to do so results in an undesireable alias as the * result of DNS AFSDB record lookups where a trailing dot * has special meaning. */ strncpy(name, namep, CELL_MAXNAMELEN); for (len = strlen(namep); len > 0 && namep[len-1] == '.'; len--) { name[len-1] = '\0'; } if (len == 0) return NULL; namep = name; hash = CM_CELL_NAME_HASH(namep); lock_ObtainRead(&cm_cellLock); for (cp = cm_data.cellNameHashTablep[hash]; cp; cp=cp->nameNextp) { if (cm_stricmp_utf8(namep, cp->name) == 0) { strncpy(fullname, cp->name, CELL_MAXNAMELEN); fullname[CELL_MAXNAMELEN-1] = '\0'; break; } } if (!cp) { for (cp = cm_data.allCellsp; cp; cp=cp->allNextp) { if (strnicmp(namep, cp->name, strlen(namep)) == 0) { strncpy(fullname, cp->name, CELL_MAXNAMELEN); fullname[CELL_MAXNAMELEN-1] = '\0'; break; } } } if (cp) { lock_ReleaseRead(&cm_cellLock); cm_UpdateCell(cp, flags); } else if (flags & CM_FLAG_CREATE) { lock_ConvertRToW(&cm_cellLock); hasWriteLock = 1; /* when we dropped the lock the cell could have been added * to the list so check again while holding the write lock */ for (cp = cm_data.cellNameHashTablep[hash]; cp; cp=cp->nameNextp) { if (cm_stricmp_utf8(namep, cp->name) == 0) { strncpy(fullname, cp->name, CELL_MAXNAMELEN); fullname[CELL_MAXNAMELEN-1] = '\0'; break; } } if (cp) goto done; for (cp = cm_data.allCellsp; cp; cp=cp->allNextp) { if (strnicmp(namep, cp->name, strlen(namep)) == 0) { strncpy(fullname, cp->name, CELL_MAXNAMELEN); fullname[CELL_MAXNAMELEN-1] = '\0'; break; } } if (cp) { lock_ReleaseWrite(&cm_cellLock); lock_ObtainMutex(&cp->mx); lock_ObtainWrite(&cm_cellLock); cm_AddCellToNameHashTable(cp); cm_AddCellToIDHashTable(cp); lock_ReleaseMutex(&cp->mx); goto done; } if ( cm_data.freeCellsp != NULL ) { cp = cm_data.freeCellsp; cm_data.freeCellsp = cp->freeNextp; /* * The magic, cellID, and mx fields are already set. */ } else { if ( cm_data.currentCells >= cm_data.maxCells ) osi_panic("Exceeded Max Cells", __FILE__, __LINE__); /* don't increment currentCells until we know that we * are going to keep this entry */ cp = &cm_data.cellBaseAddress[cm_data.currentCells]; memset(cp, 0, sizeof(cm_cell_t)); cp->magic = CM_CELL_MAGIC; /* the cellID cannot be 0 */ cp->cellID = ++cm_data.currentCells; /* otherwise we found the cell, and so we're nearly done */ lock_InitializeMutex(&cp->mx, "cm_cell_t mutex", LOCK_HIERARCHY_CELL); } lock_ReleaseWrite(&cm_cellLock); hasWriteLock = 0; rock.cellp = cp; rock.flags = flags; code = cm_SearchCellRegistry(1, namep, fullname, linkedName, cm_AddCellProc, &rock); if (code && code != CM_ERROR_FORCE_DNS_LOOKUP) code = cm_SearchCellFileEx(namep, fullname, linkedName, cm_AddCellProc, &rock); if (code) { osi_Log4(afsd_logp,"in cm_GetCell_gen cm_SearchCellFileEx(%s) returns code= %d fullname= %s linkedName= %s", osi_LogSaveString(afsd_logp,namep), code, osi_LogSaveString(afsd_logp,fullname), osi_LogSaveString(afsd_logp,linkedName)); if (cm_dnsEnabled) { int ttl; code = cm_SearchCellByDNS(namep, fullname, &ttl, cm_AddCellProc, &rock); if ( code ) { osi_Log3(afsd_logp,"in cm_GetCell_gen cm_SearchCellByDNS(%s) returns code= %d fullname= %s", osi_LogSaveString(afsd_logp,namep), code, osi_LogSaveString(afsd_logp,fullname)); lock_ObtainMutex(&cp->mx); lock_ObtainWrite(&cm_cellLock); hasWriteLock = 1; cm_RemoveCellFromIDHashTable(cp); cm_RemoveCellFromNameHashTable(cp); lock_ReleaseMutex(&cp->mx); cm_FreeCell(cp); cp = NULL; goto done; } else { /* got cell from DNS */ lock_ObtainMutex(&cp->mx); hasMutex = 1; _InterlockedOr(&cp->flags, CM_CELLFLAG_DNS); _InterlockedAnd(&cp->flags, ~CM_CELLFLAG_VLSERVER_INVALID); cp->timeout = time(0) + ttl; } } else { lock_ObtainMutex(&cp->mx); lock_ObtainWrite(&cm_cellLock); hasWriteLock = 1; cm_RemoveCellFromIDHashTable(cp); cm_RemoveCellFromNameHashTable(cp); lock_ReleaseMutex(&cp->mx); cm_FreeCell(cp); cp = NULL; goto done; } } else { lock_ObtainMutex(&cp->mx); hasMutex = 1; cp->timeout = time(0) + 7200; /* two hour timeout */ } /* we have now been given the fullname of the cell. It may * be that we already have a cell with that name. If so, * we should use it instead of completing the allocation * of a new cm_cell_t */ lock_ObtainRead(&cm_cellLock); hash = CM_CELL_NAME_HASH(fullname); for (cp2 = cm_data.cellNameHashTablep[hash]; cp2; cp2=cp2->nameNextp) { if (cm_stricmp_utf8(fullname, cp2->name) == 0) { break; } } if (cp2) { if (!hasMutex) { lock_ObtainMutex(&cp->mx); hasMutex = 1; } lock_ConvertRToW(&cm_cellLock); hasWriteLock = 1; cm_RemoveCellFromIDHashTable(cp); cm_RemoveCellFromNameHashTable(cp); lock_ReleaseMutex(&cp->mx); hasMutex = 0; cm_FreeCell(cp); cp = cp2; goto done; } lock_ReleaseRead(&cm_cellLock); /* randomise among those vlservers having the same rank*/ cm_RandomizeServer(&cp->vlServersp); if (!hasMutex) lock_ObtainMutex(&cp->mx); /* copy in name */ strncpy(cp->name, fullname, CELL_MAXNAMELEN); cp->name[CELL_MAXNAMELEN-1] = '\0'; strncpy(cp->linkedName, linkedName, CELL_MAXNAMELEN); cp->linkedName[CELL_MAXNAMELEN-1] = '\0'; lock_ObtainWrite(&cm_cellLock); hasWriteLock = 1; cm_AddCellToNameHashTable(cp); cm_AddCellToIDHashTable(cp); lock_ReleaseMutex(&cp->mx); hasMutex = 0; /* append cell to global list */ if (cm_data.allCellsp == NULL) { cm_data.allCellsp = cp; } else { for (cp2 = cm_data.allCellsp; cp2->allNextp; cp2=cp2->allNextp) ; cp2->allNextp = cp; } cp->allNextp = NULL; } else { lock_ReleaseRead(&cm_cellLock); } done: if (hasMutex && cp) lock_ReleaseMutex(&cp->mx); if (hasWriteLock) lock_ReleaseWrite(&cm_cellLock); /* fullname is not valid if cp == NULL */ if (newnamep) { if (cp) { strncpy(newnamep, fullname, CELL_MAXNAMELEN); newnamep[CELL_MAXNAMELEN-1]='\0'; } else { newnamep[0] = '\0'; } } if (cp && cp->linkedName[0]) { cm_cell_t * linkedCellp = NULL; if (!strcmp(cp->name, cp->linkedName)) { cp->linkedName[0] = '\0'; } else if (!(flags & CM_FLAG_NOMOUNTCHASE)) { linkedCellp = cm_GetCell(cp->linkedName, CM_FLAG_CREATE|CM_FLAG_NOPROBE|CM_FLAG_NOMOUNTCHASE); lock_ObtainWrite(&cm_cellLock); if (!linkedCellp || (linkedCellp->linkedName[0] && strcmp(cp->name, linkedCellp->linkedName))) { cp->linkedName[0] = '\0'; } else { strncpy(linkedCellp->linkedName, cp->name, CELL_MAXNAMELEN); linkedCellp->linkedName[CELL_MAXNAMELEN-1]='\0'; } lock_ReleaseWrite(&cm_cellLock); } } return cp; }
BOOLEAN AmccPciEvtInterruptIsr( __in WDFINTERRUPT Interrupt, __in ULONG MessageID ) /*++ Routine Description: This routine assumes that only a single I/O can be completed at a time on the hardware (i.e. at most one I/O completed per interrupt). Arguments: Interupt - Address of the framework interrupt object MessageID - Return Value: TRUE - Interrupt belongs to this device. --*/ { PAMCC_DEVICE_EXTENSION devExt = NULL; WDFDEVICE hDevice; union { ULONG ulong; INTCSR_REG bits; } intcsr; union { ULONG ulong; MCSR_REG bits; } mcsr; UNREFERENCED_PARAMETER( MessageID ); hDevice = WdfInterruptGetDevice(Interrupt); devExt = AmccPciGetDevExt(hDevice); // // Read interrupt control/status register and see if an interrupt is pending. // If not, return FALSE immediately. // intcsr.ulong = READ_PORT_ULONG((PULONG) &devExt->Regs->INTCSR); if (!intcsr.bits.InterruptAsserted) { return FALSE; } // // Disable bus-mastering // mcsr.ulong = READ_PORT_ULONG((PULONG) &devExt->Regs->MCSR); mcsr.bits.WriteTransferEnable = FALSE; mcsr.bits.ReadTransferEnable = FALSE; WRITE_PORT_ULONG((PULONG) &devExt->Regs->MCSR, mcsr.ulong ); // // This will take effect when INTCSR is rewritten later. // intcsr.bits.IntOnWriteTransferComplete = FALSE; intcsr.bits.IntOnReadTransferComplete = FALSE; // // Process pending interrupts. We're expecting an interrupt due // to a transfer count going to zero, but we might be getting a // master or target abort instead. // while (intcsr.bits.InterruptAsserted) { // // Merge new interrupts with old // _InterlockedOr((PLONG) &devExt->Intcsr, (LONG) intcsr.ulong ); // // Interrupt flags on the S5933 are cleared by writing a "1" bit // to them, so clear all the interrupts just examined. // WRITE_PORT_ULONG((PULONG) &devExt->Regs->INTCSR, intcsr.ulong); // // Check for additional interrupts // intcsr.ulong = READ_PORT_ULONG((PULONG) &devExt->Regs->INTCSR); } // // Check if there is a current Request. If not, then this interrupt cannot // do anything. This driver design requires an I/O to be pending in order // to queue the DPC. If there is no I/O current, then there is no need // to have a DPC queued. This driver also assumes one I/O per interrupt. // // IMPORTANT: Before returning TRUE, the interrupt must have been cleared // on the device or the system will hang trying to service this level // sensitive interrupt. // if (!devExt->CurrentRequest) { TraceEvents(TRACE_LEVEL_WARNING, AMCC_TRACE_IO, "Hardware generated interrupt with no request pending"); return TRUE; } // // Request the DPC to complete the transfer. // WdfInterruptQueueDpcForIsr( Interrupt ); // // Indicate that this adapter was interrupting. // return TRUE; }
/* special turnstile signal for mutexes and locks. Wakes up only those who * will really be able to lock the lock. The assumption is that everyone who * already can use the lock has already been woken (and is thus not in the * turnstile any longer). * * The stillHaveReaders parm is set to 1 if this is a convert from write to read, * indicating that there is still at least one reader, and we should only wake * up other readers. We use it in a tricky manner: we just pretent we already woke * a reader, and that is sufficient to prevent us from waking a writer. * * The crit sec. csp is released before the threads are woken, but after they * are removed from the turnstile. It helps ensure that we won't have a spurious * context swap back to us if the release performs a context swap for some reason. */ void osi_TSignalForMLs(osi_turnstile_t *turnp, int stillHaveReaders, CRITICAL_SECTION *csp) { osi_sleepInfo_t *tsp; /* a temp */ osi_sleepInfo_t *nsp; /* a temp */ osi_queue_t *wakeupListp; /* list of dudes to wakeup after dropping lock */ int wokeReader; unsigned short *sp; unsigned char *cp; wokeReader = stillHaveReaders; wakeupListp = NULL; while(tsp = turnp->lastp) { /* look at each sleepInfo until we find someone we're not supposed to * wakeup. */ if (tsp->waitFor & OSI_SLEEPINFO_W4WRITE) { if (wokeReader) break; } else wokeReader = 1; /* otherwise, we will wake this guy. For now, remove from this list * and move to private one, so we can do the wakeup after releasing * the crit sec. */ osi_QRemoveHT((osi_queue_t **) &turnp->firstp, (osi_queue_t **) &turnp->lastp, &tsp->q); /* do the patching required for lock obtaining */ if (tsp->waitFor & OSI_SLEEPINFO_W4WRITE) { cp = (void *) tsp->value; (*cp) |= OSI_LOCKFLAG_EXCL; tsp->tidp[0] = tsp->tid; } else if (tsp->waitFor & OSI_SLEEPINFO_W4READ) { sp = (void *) tsp->value; #ifdef DEBUG if ((*sp) < OSI_RWLOCK_THREADS) tsp->tidp[*sp] = tsp->tid; #endif (*sp)++; } /* and add to our own list */ tsp->q.nextp = wakeupListp; wakeupListp = &tsp->q; /* now if we woke a writer, we're done, since it is pointless * to wake more than one writer. */ if (!wokeReader) break; } /* hit end, or found someone we're not supposed to wakeup */ if (csp) LeaveCriticalSection(csp); /* finally, wakeup everyone we found. Don't free things since the sleeper * will free the sleepInfo structure. */ for(tsp = (osi_sleepInfo_t *) wakeupListp; tsp; tsp = nsp) { /* pull this out first, since *tsp *could* get freed immediately * after the ReleaseSemaphore, if a context swap occurs. */ nsp = (osi_sleepInfo_t *) tsp->q.nextp; _InterlockedOr(&tsp->states, OSI_SLEEPINFO_SIGNALLED); ReleaseSemaphore(tsp->sema, 1, NULL); } }
LONG test_InterlockedOr(LONG volatile *value, LONG mask) { return _InterlockedOr(value, mask); }
long test_InterlockedOr(long volatile *value, long mask) { return _InterlockedOr(value, mask); }
static void cm_CheckServersMulti(afs_uint32 flags, cm_cell_t *cellp) { /* * The goal of this function is to probe simultaneously * probe all of the up/down servers (vldb/file) as * specified by flags in the minimum number of RPCs. * Effectively that means use one multi_RXAFS_GetCapabilities() * followed by possibly one multi_RXAFS_GetTime() and * one multi_VL_ProbeServer(). * * To make this work we must construct the list of vldb * and file servers that are to be probed as well as the * associated data structures. */ int srvAddrCount = 0; struct srvAddr **addrs = NULL; cm_conn_t **conns = NULL; struct rx_connection **rxconns = NULL; cm_req_t req; afs_int32 i, nconns = 0, maxconns; afs_int32 *conntimer, *results; Capabilities *caps = NULL; cm_server_t ** serversp, *tsp; afs_uint32 isDown, wasDown; afs_uint32 code; time_t start; char hoststr[16]; cm_InitReq(&req); maxconns = max(cm_numFileServers,cm_numVldbServers); if (maxconns == 0) return; conns = (cm_conn_t **)malloc(maxconns * sizeof(cm_conn_t *)); rxconns = (struct rx_connection **)malloc(maxconns * sizeof(struct rx_connection *)); conntimer = (afs_int32 *)malloc(maxconns * sizeof (afs_int32)); results = (afs_int32 *)malloc(maxconns * sizeof (afs_int32)); serversp = (cm_server_t **)malloc(maxconns * sizeof(cm_server_t *)); caps = (Capabilities *)malloc(maxconns * sizeof(Capabilities)); memset(caps, 0, maxconns * sizeof(Capabilities)); if ((flags & CM_FLAG_CHECKFILESERVERS) || !(flags & (CM_FLAG_CHECKFILESERVERS|CM_FLAG_CHECKVLDBSERVERS))) { lock_ObtainRead(&cm_serverLock); for (nconns=0, tsp = cm_serversAllFirstp; tsp != NULL && nconns < maxconns; tsp = (cm_server_t *)osi_QNext(&tsp->allq)) { if (tsp->type != CM_SERVER_FILE || tsp->cellp == NULL || /* SetPref only */ cellp && cellp != tsp->cellp) continue; cm_GetServerNoLock(tsp); lock_ReleaseRead(&cm_serverLock); lock_ObtainMutex(&tsp->mx); isDown = tsp->flags & CM_SERVERFLAG_DOWN; if ((tsp->flags & CM_SERVERFLAG_PINGING) || !((isDown && (flags & CM_FLAG_CHECKDOWNSERVERS)) || (!isDown && (flags & CM_FLAG_CHECKUPSERVERS)))) { lock_ReleaseMutex(&tsp->mx); lock_ObtainRead(&cm_serverLock); cm_PutServerNoLock(tsp); continue; } _InterlockedOr(&tsp->flags, CM_SERVERFLAG_PINGING); lock_ReleaseMutex(&tsp->mx); serversp[nconns] = tsp; if (cm_noIPAddr > 0) code = cm_ConnByServer(tsp, cm_rootUserp, FALSE, &conns[nconns]); else code = RX_CALL_DEAD; if (code) { if (code == RX_CALL_DEAD) { lock_ObtainMutex(&tsp->mx); cm_MarkServerDown(tsp, code, isDown); lock_ReleaseMutex(&tsp->mx); } lock_ObtainRead(&cm_serverLock); cm_PutServerNoLock(tsp); continue; } lock_ObtainRead(&cm_serverLock); rxconns[nconns] = cm_GetRxConn(conns[nconns]); if (conntimer[nconns] = (isDown ? 1 : 0)) rx_SetConnHardDeadTime(rxconns[nconns], 10); nconns++; } lock_ReleaseRead(&cm_serverLock); if (nconns) { /* Perform the multi call */ start = time(NULL); multi_Rx(rxconns,nconns) { multi_RXAFS_GetCapabilities(&caps[multi_i]); results[multi_i]=multi_error; } multi_End; }
long cm_CreateCellWithInfo( char * cellname, char * linked_cellname, unsigned short vlport, afs_uint32 host_count, char *hostname[], afs_uint32 flags) { afs_uint32 code = 0; cm_cell_rock_t rock; struct hostent *thp; struct sockaddr_in vlSockAddr; afs_uint32 i, j; rock.cellp = cm_GetCell(cellname, CM_FLAG_CREATE | CM_FLAG_NOPROBE); rock.flags = 0; cm_FreeServerList(&rock.cellp->vlServersp, CM_FREESERVERLIST_DELETE); if (!(flags & CM_CELLFLAG_DNS)) { for (i = 0; i < host_count; i++) { thp = gethostbyname(hostname[i]); if (thp) { int foundAddr = 0; for (j=0 ; thp->h_addr_list[j]; j++) { if (thp->h_addrtype != AF_INET) continue; memcpy(&vlSockAddr.sin_addr.s_addr, thp->h_addr_list[j], sizeof(long)); vlSockAddr.sin_port = htons(vlport ? vlport : 7003); vlSockAddr.sin_family = AF_INET; cm_AddCellProc(&rock, &vlSockAddr, hostname[i], CM_FLAG_NOPROBE); } } } lock_ObtainMutex(&rock.cellp->mx); _InterlockedAnd(&rock.cellp->flags, ~CM_CELLFLAG_DNS); } else if (cm_dnsEnabled) { int ttl; code = cm_SearchCellByDNS(rock.cellp->name, NULL, &ttl, cm_AddCellProc, &rock); lock_ObtainMutex(&rock.cellp->mx); if (code == 0) { /* got cell from DNS */ _InterlockedOr(&rock.cellp->flags, CM_CELLFLAG_DNS); rock.cellp->timeout = time(0) + ttl; #ifdef DEBUG fprintf(stderr, "cell %s: ttl=%d\n", rock.cellp->name, ttl); #endif } } else { lock_ObtainMutex(&rock.cellp->mx); rock.cellp->flags &= ~CM_CELLFLAG_DNS; } _InterlockedOr(&rock.cellp->flags, CM_CELLFLAG_VLSERVER_INVALID); StringCbCopy(rock.cellp->linkedName, CELL_MAXNAMELEN, linked_cellname); lock_ReleaseMutex(&rock.cellp->mx); if (rock.cellp->vlServersp) cm_RandomizeServer(&rock.cellp->vlServersp); return code; }
Int32 KInterlockedOr(Int32 volatile* var, Int32 add) { return _InterlockedOr((volatile long*)var, add); }
/* if it's from DNS, see if it has expired * and check to make sure we have a valid set of volume servers * this function must not be called with a lock on cm_cellLock */ cm_cell_t *cm_UpdateCell(cm_cell_t * cp, afs_uint32 flags) { long code = 0; cm_cell_rock_t rock; afs_uint32 mxheld = 0; if (cp == NULL) return NULL; lock_ObtainMutex(&cp->mx); mxheld = 1; #ifdef AFS_FREELANCE_CLIENT if (cp->flags & CM_CELLFLAG_FREELANCE) { lock_ReleaseMutex(&cp->mx); return cp; } #endif if (cm_IsServerListEmpty(cp->vlServersp) || (time(0) > cp->timeout) || (cm_dnsEnabled && (cp->flags & CM_CELLFLAG_DNS) && ((cp->flags & CM_CELLFLAG_VLSERVER_INVALID)))) { lock_ReleaseMutex(&cp->mx); mxheld = 0; /* must empty cp->vlServersp */ if (cp->vlServersp) cm_FreeServerList(&cp->vlServersp, CM_FREESERVERLIST_DELETE); rock.cellp = cp; rock.flags = flags; code = cm_SearchCellRegistry(1, cp->name, NULL, cp->linkedName, cm_AddCellProc, &rock); if (code && code != CM_ERROR_FORCE_DNS_LOOKUP) code = cm_SearchCellFileEx(cp->name, NULL, cp->linkedName, cm_AddCellProc, &rock); if (code == 0) { lock_ObtainMutex(&cp->mx); mxheld = 1; cp->timeout = time(0) + 7200; } else { if (cm_dnsEnabled) { int ttl; code = cm_SearchCellByDNS(cp->name, NULL, &ttl, cm_AddCellProc, &rock); if (code == 0) { /* got cell from DNS */ lock_ObtainMutex(&cp->mx); mxheld = 1; _InterlockedOr(&cp->flags, CM_CELLFLAG_DNS); _InterlockedAnd(&cp->flags, ~CM_CELLFLAG_VLSERVER_INVALID); cp->timeout = time(0) + ttl; #ifdef DEBUG fprintf(stderr, "cell %s: ttl=%d\n", cp->name, ttl); #endif } else { /* if we fail to find it this time, we'll just do nothing and leave the * current entry alone */ lock_ObtainMutex(&cp->mx); mxheld = 1; _InterlockedOr(&cp->flags, CM_CELLFLAG_VLSERVER_INVALID); } } } } if (code == 0) cm_RandomizeServer(&cp->vlServersp); if (mxheld) lock_ReleaseMutex(&cp->mx); return code ? NULL : cp; }
void cm_PingServer(cm_server_t *tsp) { long code; int wasDown = 0; cm_conn_t *connp; struct rx_connection * rxconnp; Capabilities caps = {0, 0}; char hoststr[16]; cm_req_t req; lock_ObtainMutex(&tsp->mx); if (tsp->flags & CM_SERVERFLAG_PINGING) { tsp->waitCount++; osi_SleepM((LONG_PTR)tsp, &tsp->mx); lock_ObtainMutex(&tsp->mx); tsp->waitCount--; if (tsp->waitCount == 0) _InterlockedAnd(&tsp->flags, ~CM_SERVERFLAG_PINGING); else osi_Wakeup((LONG_PTR)tsp); lock_ReleaseMutex(&tsp->mx); return; } _InterlockedOr(&tsp->flags, CM_SERVERFLAG_PINGING); wasDown = tsp->flags & CM_SERVERFLAG_DOWN; afs_inet_ntoa_r(tsp->addr.sin_addr.S_un.S_addr, hoststr); lock_ReleaseMutex(&tsp->mx); if (cm_noIPAddr > 0) code = cm_ConnByServer(tsp, cm_rootUserp, FALSE, &connp); else code = RX_CALL_DEAD; /* No network */ if (code == 0) { /* now call the appropriate ping call. Drop the timeout if * the server is known to be down, so that we don't waste a * lot of time retiming out down servers. */ osi_Log4(afsd_logp, "cm_PingServer server %s (%s) was %s with caps 0x%x", osi_LogSaveString(afsd_logp, hoststr), tsp->type == CM_SERVER_VLDB ? "vldb" : "file", wasDown ? "down" : "up", tsp->capabilities); rxconnp = cm_GetRxConn(connp); if (wasDown) rx_SetConnHardDeadTime(rxconnp, 10); if (tsp->type == CM_SERVER_VLDB) { code = VL_ProbeServer(rxconnp); } else { /* file server */ code = RXAFS_GetCapabilities(rxconnp, &caps); } if (wasDown) rx_SetConnHardDeadTime(rxconnp, HardDeadtimeout); rx_PutConnection(rxconnp); cm_PutConn(connp); } /* got an unauthenticated connection to this server */ lock_ObtainMutex(&tsp->mx); if (code >= 0 || code == RXGEN_OPCODE || code == RX_CALL_BUSY) { /* mark server as up */ _InterlockedAnd(&tsp->flags, ~CM_SERVERFLAG_DOWN); tsp->downTime = 0; /* we currently handle 32-bits of capabilities */ if (code != RXGEN_OPCODE && code != RX_CALL_BUSY && caps.Capabilities_len > 0) { tsp->capabilities = caps.Capabilities_val[0]; xdr_free((xdrproc_t) xdr_Capabilities, &caps); caps.Capabilities_len = 0; caps.Capabilities_val = 0; } else { tsp->capabilities = 0; } osi_Log3(afsd_logp, "cm_PingServer server %s (%s) is up with caps 0x%x", osi_LogSaveString(afsd_logp, hoststr), tsp->type == CM_SERVER_VLDB ? "vldb" : "file", tsp->capabilities); /* Now update the volume status if necessary */ if (wasDown) { cm_server_vols_t * tsrvp; cm_volume_t * volp; int i; for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) { for (i=0; i<NUM_SERVER_VOLS; i++) { if (tsrvp->ids[i] != 0) { cm_InitReq(&req); lock_ReleaseMutex(&tsp->mx); code = cm_FindVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp, &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp); lock_ObtainMutex(&tsp->mx); if (code == 0) { cm_UpdateVolumeStatus(volp, tsrvp->ids[i]); cm_PutVolume(volp); } } } } cm_RankServer(tsp); } } else { cm_MarkServerDown(tsp, code, wasDown); osi_Log3(afsd_logp, "cm_PingServer server %s (%s) is down with caps 0x%x", osi_LogSaveString(afsd_logp, hoststr), tsp->type == CM_SERVER_VLDB ? "vldb" : "file", tsp->capabilities); } if (tsp->waitCount == 0) _InterlockedAnd(&tsp->flags, ~CM_SERVERFLAG_PINGING); else osi_Wakeup((LONG_PTR)tsp); lock_ReleaseMutex(&tsp->mx); }