ULONG HalSetProfileInterval ( IN ULONG Interval ) /*++ Routine Description: This routine sets the profile interrupt interval. Arguments: Interval - Supplies the desired profile interval in 100ns units. Return Value: The actual profile interval. --*/ { LARGE_INTEGER TempValue; // // If the specified profile interval is less that the minimum profile // interval or greater than the maximum profile interval, then set the // profile interval to the minimum or maximum as appropriate. // if (Interval < MINIMUM_PROFILE_INTERVAL) { Interval = MINIMUM_PROFILE_INTERVAL; } else if (Interval > MAXIMUM_PROFILE_INTERVAL) { Interval = MAXIMUM_PROFILE_INTERVAL; } // // First compute the profile count value and then back calculate the // actual profile interval. // TempValue.QuadPart = Int32x32To64(HalpProfileCountRate, Interval); TempValue.QuadPart += ROUND_VALUE; TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL); TempValue.QuadPart = Int32x32To64(TempValue.LowPart, ONE_SECOND); TempValue = RtlExtendedLargeIntegerDivide(TempValue, HalpProfileCountRate, NULL); HalpProfileInterval = TempValue.LowPart; return HalpProfileInterval; }
static void TIME_ClockTimeToFileTime(clock_t unix_time, LPFILETIME filetime) { ULONGLONG secs = RtlEnlargedUnsignedMultiply( unix_time, 10000000 ); secs = RtlExtendedLargeIntegerDivide( secs, CLK_TCK, NULL ); filetime->dwLowDateTime = (DWORD)secs; filetime->dwHighDateTime = (DWORD)(secs >> 32); }
VOID HalStartProfileInterrupt ( KPROFILE_SOURCE ProfileSource ) /*++ Routine Description: This routine computes the profile count value, writes the compare register, clears the count register, and updates the performance counter. N.B. This routine must be called at PROFILE_LEVEL while holding the profile lock. Arguments: Source - Supplies the profile source. Return Value: None. --*/ { PKPRCB Prcb; ULONG PreviousCount; LARGE_INTEGER TempValue; // // Compute the profile count from the current profile interval. // TempValue.QuadPart = Int32x32To64(HalpProfileCountRate, HalpProfileInterval); TempValue.QuadPart += ROUND_VALUE; TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL); // // Write the compare register and clear the count register. // PreviousCount = HalpWriteCompareRegisterAndClear(TempValue.LowPart); // // Update the performance counter by adding in the previous count value. // Prcb = KeGetCurrentPrcb(); HalpPerformanceCounter[Prcb->Number].QuadPart += PreviousCount; return; }
BOOLEAN NTAPI FsRecGetDeviceSectors(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, OUT PLARGE_INTEGER SectorCount) { PARTITION_INFORMATION PartitionInfo; IO_STATUS_BLOCK IoStatusBlock; KEVENT Event; PIRP Irp; NTSTATUS Status; ULONG Remainder; PAGED_CODE(); /* Only needed for disks */ if (DeviceObject->DeviceType != FILE_DEVICE_DISK) return FALSE; /* Build the information IRP */ KeInitializeEvent(&Event, SynchronizationEvent, FALSE); Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO, DeviceObject, NULL, 0, &PartitionInfo, sizeof(PARTITION_INFORMATION), FALSE, &Event, &IoStatusBlock); if (!Irp) return FALSE; /* Override verification */ IoGetNextIrpStackLocation(Irp)->Flags |= SL_OVERRIDE_VERIFY_VOLUME; /* Do the request */ Status = IoCallDriver(DeviceObject, Irp); if (Status == STATUS_PENDING) { /* Wait for completion */ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); Status = IoStatusBlock.Status; } /* Fail if we couldn't get the data */ if (!NT_SUCCESS(Status)) return FALSE; /* Otherwise, return the number of sectors */ *SectorCount = RtlExtendedLargeIntegerDivide(PartitionInfo.PartitionLength, SectorSize, &Remainder); return TRUE; }
/* * @implemented */ BOOL WINAPI GetMailslotInfo(IN HANDLE hMailslot, IN LPDWORD lpMaxMessageSize, IN LPDWORD lpNextSize, IN LPDWORD lpMessageCount, IN LPDWORD lpReadTimeout) { FILE_MAILSLOT_QUERY_INFORMATION Buffer; IO_STATUS_BLOCK Iosb; NTSTATUS Status; LARGE_INTEGER Timeout; Status = NtQueryInformationFile(hMailslot, &Iosb, &Buffer, sizeof(FILE_MAILSLOT_QUERY_INFORMATION), FileMailslotQueryInformation); if (!NT_SUCCESS(Status)) { DPRINT1("NtQueryInformationFile failed (Status %x)!\n", Status); BaseSetLastNTError(Status); return FALSE; } if (lpMaxMessageSize) *lpMaxMessageSize = Buffer.MaximumMessageSize; if (lpNextSize) *lpNextSize = Buffer.NextMessageSize; if (lpMessageCount) *lpMessageCount = Buffer.MessagesAvailable; if (lpReadTimeout) { if (Buffer.ReadTimeout.QuadPart == 0xFFFFFFFFFFFFFFFFLL) { *lpReadTimeout = MAILSLOT_WAIT_FOREVER; } else { Timeout.QuadPart = -Buffer.ReadTimeout.QuadPart; Timeout = RtlExtendedLargeIntegerDivide(Timeout, 10000, NULL); if (Timeout.HighPart == 0) { *lpReadTimeout = Timeout.LowPart; } else { *lpReadTimeout = 0xFFFFFFFE; } } } return TRUE; }
DWORD TimeInMicroSeconds( DWORD dwTime ) { DWORD Remainder; return RtlExtendedLargeIntegerDivide( RtlEnlargedUnsignedMultiply( dwTime, 1000000L), Frequency, &Remainder ).LowPart; }
BOOLEAN FsRecGetDeviceSectors(PDEVICE_OBJECT DeviceObject,ULONG BytesPerSector,OUT PLARGE_INTEGER SectorCount) { KEVENT Event; IO_STATUS_BLOCK IoStatus; LARGE_INTEGER Length; PIRP Irp; NTSTATUS Status; LARGE_INTEGER Divide; ULONG Remainder; if( DeviceObject->DeviceType == FILE_DEVICE_DISK) { KeInitializeEvent(&Event,SynchronizationEvent,FALSE); Irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_GET_LENGTH_INFO, // 7405C DeviceObject, NULL, 0, (PVOID)&Length, sizeof(LARGE_INTEGER), FALSE, &Event, &IoStatus); if(Irp) { (IoGetNextIrpStackLocation(Irp))->Flags |= IRP_PAGING_IO; Status = IoCallDriver(DeviceObject,Irp); if(Status == STATUS_PENDING) { KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL); Status = IoStatus.Status; } if(NT_SUCCESS(Status)) { Divide = RtlExtendedLargeIntegerDivide(Length,BytesPerSector,&Remainder); SectorCount->QuadPart = Divide.QuadPart; return TRUE; } } } return FALSE; }
DBGSTATIC VOID NetpRoundUpLargeIntegerTimeToOneSecond( IN OUT PLARGE_INTEGER LargeInteger ) { LARGE_INTEGER LargeRemainder; LARGE_INTEGER LargeResult; LARGE_INTEGER OriginalLargeIntegerTime = *LargeInteger; ULONG Remainder = 0; LargeResult = RtlExtendedLargeIntegerDivide ( OriginalLargeIntegerTime, // dividend (ULONG) UNITS_PER_SECOND, &Remainder ); IF_DEBUG( TIME ) { NetpKdPrint(( PREFIX_NETLIB "NetpRoundUpLargeIntegerTimeToOneSecond: remainder is " FORMAT_DWORD ".\n", (DWORD) Remainder )); } if (Remainder != 0) { LARGE_INTEGER LargeOneSecond; // Subtract fractional part. LargeRemainder.HighPart = 0; LargeRemainder.LowPart = (DWORD) Remainder; LargeResult.QuadPart = OriginalLargeIntegerTime.QuadPart - LargeRemainder.QuadPart; // Now add a whole second. LargeOneSecond.HighPart = 0; LargeOneSecond.LowPart = UNITS_PER_SECOND; LargeResult.QuadPart += LargeOneSecond.QuadPart; *LargeInteger = LargeResult; } } // NetpRoundUpLargeIntegerToOneSecond
LARGE_INTEGER SoundGetTime( VOID ) /*++ Routine Description: Get an accurate estimate of the current time by calling KeQueryPerformanceCounter and converting the result to 100ns units NOTE: A driver should call this once during init to get the thing safely started if it can be called from more than one device at a time Arguments: None Return Value: --*/ { static struct { LARGE_INTEGER StartTime100ns, StartTimeTicks, TicksPerSecond; ULONG Multiplier; BOOLEAN Initialized; } s = { 1 }; // Move from BSS to reduce size ULONG Remainder; if (!s.Initialized) { KeQuerySystemTime(&s.StartTime100ns); s.StartTimeTicks = KeQueryPerformanceCounter(&s.TicksPerSecond); s.Multiplier = 10000000; while (s.TicksPerSecond.HighPart != 0) { s.Multiplier = s.Multiplier / 10; s.TicksPerSecond = RtlExtendedLargeIntegerDivide(s.TicksPerSecond, 10, &Remainder); } s.Initialized = TRUE; } // // Convert ticks to 100ns units (and hope we don't overflow!) // return RtlLargeIntegerAdd( RtlExtendedLargeIntegerDivide( RtlExtendedIntegerMultiply( RtlLargeIntegerSubtract( KeQueryPerformanceCounter(NULL), s.StartTimeTicks ), s.Multiplier ), s.TicksPerSecond.LowPart, &Remainder ), s.StartTime100ns ); }
VOID KiCalibrateTimeAdjustment ( PADJUST_INTERRUPT_TIME_CONTEXT Adjust ) /*++ Routine Description: This function calibrates the adjustment of time on all processors. Arguments: Adjust - Supplies the operation context. Return Value: None. --*/ { ULONG cl; ULONG divisor; BOOLEAN Enable; LARGE_INTEGER InterruptTime; ULARGE_INTEGER li; PERFINFO_PO_CALIBRATED_PERFCOUNTER LogEntry; LARGE_INTEGER NewTickCount; ULONG NewTickOffset; LARGE_INTEGER PerfCount; LARGE_INTEGER PerfFreq; LARGE_INTEGER SetTime; // // As each processor arrives, decrement the remaining processor count. If // this is the last processor to arrive, then compute the time change, and // signal all processor when to apply the performance counter change. // if (InterlockedDecrement((PLONG)&Adjust->KiNumber)) { Enable = KeDisableInterrupts(); // // It is possible to deadlock if one or more of the other processors // receives and processes a freeze request while this processor has // interrupts disabled. Poll for a freeze request until all processors // are known to be in this code. // do { KiPollFreezeExecution(); } while (Adjust->KiNumber != (ULONG)-1); // // Wait to perform the time set. // while (Adjust->Barrier); } else { // // Set timer expiration dpc to scan the timer queues once for any // expired timers. // KeRemoveQueueDpc(&KiTimerExpireDpc); KeInsertQueueDpc(&KiTimerExpireDpc, ULongToPtr(KiQueryLowTickCount() - TIMER_TABLE_SIZE), NULL); // // Disable interrupts and indicate that this processor is now // in final portion of this code. // Enable = KeDisableInterrupts(); InterlockedDecrement((PLONG) &Adjust->KiNumber); // // Adjust Interrupt Time. // InterruptTime.QuadPart = KeQueryInterruptTime() + Adjust->Adjustment; SetTime.QuadPart = Adjust->Adjustment; // // Get the current times // PerfCount = KeQueryPerformanceCounter(&PerfFreq); // // Compute performance counter for current time. // // Multiply SetTime * PerfCount and obtain 96-bit result in cl, // li.LowPart, li.HighPart. Then divide the 96-bit result by // 10,000,000 to get new performance counter value. // li.QuadPart = RtlEnlargedUnsignedMultiply((ULONG)SetTime.LowPart, (ULONG)PerfFreq.LowPart).QuadPart; cl = li.LowPart; li.QuadPart = li.HighPart + RtlEnlargedUnsignedMultiply((ULONG)SetTime.LowPart, (ULONG)PerfFreq.HighPart).QuadPart; li.QuadPart = li.QuadPart + RtlEnlargedUnsignedMultiply((ULONG)SetTime.HighPart, (ULONG)PerfFreq.LowPart).QuadPart; li.HighPart = li.HighPart + SetTime.HighPart * PerfFreq.HighPart; divisor = 10000000; Adjust->NewCount.HighPart = RtlEnlargedUnsignedDivide(li, divisor, &li.HighPart); li.LowPart = cl; Adjust->NewCount.LowPart = RtlEnlargedUnsignedDivide(li, divisor, NULL); Adjust->NewCount.QuadPart += PerfCount.QuadPart; // // Compute tick count and tick offset for current interrupt time. // NewTickCount = RtlExtendedLargeIntegerDivide(InterruptTime, KeMaximumIncrement, &NewTickOffset); // // Apply changes to interrupt time, tick count, tick offset, and the // performance counter. // KiTickOffset = KeMaximumIncrement - NewTickOffset; KeInterruptTimeBias += Adjust->Adjustment; SharedUserData->TickCount.High2Time = NewTickCount.HighPart; #if defined(_WIN64) SharedUserData->TickCountQuad = NewTickCount.QuadPart; #else SharedUserData->TickCount.LowPart = NewTickCount.LowPart; SharedUserData->TickCount.High1Time = NewTickCount.HighPart; #endif // // N.B. There is no global tick count variable on AMD64. // #if defined(_X86_) KeTickCount.High2Time = NewTickCount.HighPart; KeTickCount.LowPart = NewTickCount.LowPart; KeTickCount.High1Time = NewTickCount.HighPart; #endif #if defined(_AMD64_) SharedUserData->InterruptTime.High2Time = InterruptTime.HighPart; *((volatile ULONG64 *)&SharedUserData->InterruptTime) = InterruptTime.QuadPart; #else SharedUserData->InterruptTime.High2Time = InterruptTime.HighPart; SharedUserData->InterruptTime.LowPart = InterruptTime.LowPart; SharedUserData->InterruptTime.High1Time = InterruptTime.HighPart; #endif // // Apply the performance counter change. // Adjust->Barrier = 0; } KeGetCurrentPrcb()->TickOffset = KiTickOffset; #if defined(_AMD64_) KeGetCurrentPrcb()->MasterOffset = KiTickOffset; #endif HalCalibratePerformanceCounter((LONG volatile *)&Adjust->HalNumber, (ULONGLONG)Adjust->NewCount.QuadPart); // // Log an event that the performance counter has been calibrated // properly and indicate the new performance counter value. // if (PERFINFO_IS_GROUP_ON(PERF_POWER)) { LogEntry.PerformanceCounter = KeQueryPerformanceCounter(NULL); PerfInfoLogBytes(PERFINFO_LOG_TYPE_PO_CALIBRATED_PERFCOUNTER, &LogEntry, sizeof(LogEntry)); } KeEnableInterrupts(Enable); return; }
/********************************************************************* * TIME_ClockTimeToFileTime ([email protected], 20-Sep-1998) * * Used by GetProcessTimes to convert clock_t into FILETIME. * * Differences to UnixTimeToFileTime: * 1) Divided by CLK_TCK * 2) Time is relative. There is no 'starting date', so there is * no need in offset correction, like in UnixTimeToFileTime */ static void TIME_ClockTimeToFileTime(clock_t unix_time, LPFILETIME filetime) { LONGLONG secs = RtlEnlargedUnsignedMultiply( unix_time, 10000000 ); ((LARGE_INTEGER *)filetime)->QuadPart = RtlExtendedLargeIntegerDivide( secs, sysconf( _SC_CLK_TCK ), NULL ); }
BOOL APIENTRY GetMailslotInfo( IN HANDLE hMailslot, OUT LPDWORD lpMaxMessageSize OPTIONAL, OUT LPDWORD lpNextSize OPTIONAL, OUT LPDWORD lpMessageCount OPTIONAL, OUT LPDWORD lpReadTimeout OPTIONAL ) /*++ Routine Description: This function will return the requested information about the specified mailslot. Arguments: hMailslot - A handle to the mailslot. lpMaxMessageSize - If specified returns the size of the largest message that can be written to the mailslot. lpNextSize - If specified returns the size of the next message in the mailslot buffer. It will return MAILSLOT_NO_MESSAGE if there are no messages in the mailslot. lpMessageCount - If specified returns the number of unread message currently in the mailslot. lpReadTimeout - If specified returns the read timeout, in milliseconds. Return Value: TRUE - The operation was successful. FALSE/NULL - The operation failed. Extended error status is available using GetLastError. --*/ { NTSTATUS status; IO_STATUS_BLOCK ioStatusBlock; FILE_MAILSLOT_QUERY_INFORMATION mailslotInfo; LARGE_INTEGER millisecondTimeout, tmp; status = NtQueryInformationFile( hMailslot, &ioStatusBlock, &mailslotInfo, sizeof( mailslotInfo ), FileMailslotQueryInformation ); if ( !NT_SUCCESS( status ) ) { BaseSetLastNTError( status ); return ( FALSE ); } if ( ARGUMENT_PRESENT( lpMaxMessageSize ) ) { *lpMaxMessageSize = mailslotInfo.MaximumMessageSize; } if ( ARGUMENT_PRESENT( lpNextSize ) ) { *lpNextSize = mailslotInfo.NextMessageSize; } if ( ARGUMENT_PRESENT( lpMessageCount ) ) { *lpMessageCount = mailslotInfo.MessagesAvailable; } if ( ARGUMENT_PRESENT( lpReadTimeout ) ) { // // Convert read timeout from 100 ns intervals to milliseconds. // The readtime is currently negative, since it is a relative time. // if ( mailslotInfo.ReadTimeout.HighPart != 0x7FFFFFFF || mailslotInfo.ReadTimeout.LowPart != 0xFFFFFFFF ) { tmp.QuadPart = - mailslotInfo.ReadTimeout.QuadPart; millisecondTimeout = RtlExtendedLargeIntegerDivide( tmp, 10 * 1000, NULL ); if ( millisecondTimeout.HighPart == 0 ) { *lpReadTimeout = millisecondTimeout.LowPart; } else { // // The millisecond calculation would overflow the dword. // Approximate a large number as best we can. // *lpReadTimeout = 0xFFFFFFFE; } } else { // // The mailslot timeout is infinite. // *lpReadTimeout = MAILSLOT_WAIT_FOREVER; } } return( TRUE ); }