<commit_before>// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::os::windows::io::AsRawHandle;
use std::os::windows::io::RawHandle;
use std::ptr;
use std::time::Duration;

use win_util::LargeInteger;
use win_util::SecurityAttributes;
use win_util::SelfRelativeSecurityDescriptor;
use winapi::shared::minwindef::FALSE;
use winapi::shared::winerror::WAIT_TIMEOUT;
use winapi::um::synchapi::CancelWaitableTimer;
use winapi::um::synchapi::SetWaitableTimer;
use winapi::um::synchapi::WaitForSingleObject;
use winapi::um::winbase::CreateWaitableTimerA;
use winapi::um::winbase::INFINITE;
use winapi::um::winbase::WAIT_OBJECT_0;

use super::errno_result;
use super::win::nt_query_timer_resolution;
use super::Result;
use crate::descriptor::AsRawDescriptor;
use crate::descriptor::FromRawDescriptor;
use crate::descriptor::SafeDescriptor;
use crate::timer::Timer;
use crate::timer::WaitResult;

impl AsRawHandle for Timer {
    fn as_raw_handle(&self) -> RawHandle {
        self.handle.as_raw_descriptor()
    }
}

impl Timer {
    /// Creates a new timer.  The timer is initally disarmed and must be armed by calling
    /// `reset`. Note that this timer MAY wake/trigger early due to limitations on
    /// SetWaitableTimer (see https://github.com/rust-lang/rust/issues/43376).
    pub fn new() -> Result<Timer> {
        // Safe because this doesn't modify any memory and we check the return value.
        let handle = unsafe {
            CreateWaitableTimerA(
                // Not inheritable, duplicate before passing to child prcesses
                SecurityAttributes::new_with_security_descriptor(
                    SelfRelativeSecurityDescriptor::get_singleton(),
                    /* inherit= */ false,
                )
                .as_mut(),
                // This is a synchronization timer, not a manual-reset timer.
                FALSE,
                // TODO (colindr) b/145622516 - we may have to give this a name if we later
                // want to use names to test object equality
                ptr::null_mut(),
            )
        };

        if handle.is_null() {
            return errno_result();
        }

        // Safe because we uniquely own the file descriptor.
        Ok(Timer {
            handle: unsafe { SafeDescriptor::from_raw_descriptor(handle) },
            interval: None,
        })
    }

    /// Sets the timer to expire after `dur`. If `interval` is not `None` and non-zero
    /// it represents the period for repeated expirations after the initial expiration.
    /// Otherwise the timer will expire just once.  Cancels any existing duration and
    /// repeating interval.
    pub fn reset(&mut self, dur: Duration, mut interval: Option<Duration>) -> Result<()> {
        // If interval is 0 or None it means that this timer does not repeat. We
        // set self.interval to None in this case so it can easily be checked
        // in self.wait.
        if interval == Some(Duration::from_secs(0)) {
            interval = None;
        }
        self.interval = interval;
        // Windows timers use negative values for relative times, and positive
        // values for absolute times, so we'll use negative times.

        // Windows timers also use a 64 number of 100 nanosecond intervals,
        // which we get like so: (dur.as_secs()*1e7 + dur.subsec_nanos()/100)

        let due_time = LargeInteger::new(
            -((dur.as_secs() * 10_000_000 + (dur.subsec_nanos() as u64) / 100) as i64),
        );
        let period: i32 = match interval {
            Some(int) => int.as_millis() as i32,
            None => 0,
        };

        // Safe because this doesn't modify any memory and we check the return value.
        let ret = unsafe {
            SetWaitableTimer(
                self.as_raw_descriptor(),
                &*due_time,
                period,
                None,            // no completion routine
                ptr::null_mut(), // or routine argument
                FALSE,           // no restoring system from power conservation mode
            )
        };
        if ret == 0 {
            return errno_result();
        }

        Ok(())
    }

    /// Waits until the timer expires or an optional wait timeout expires, whichever happens first.
    ///
    /// # Returns
    ///
    /// - `WaitResult::Expired` if the timer expired.
    /// - `WaitResult::Timeout` if `timeout` was not `None` and the timer did not expire within the
    ///   specified timeout period.
    pub fn wait_for(&mut self, timeout: Option<Duration>) -> Result<WaitResult> {
        let timeout = match timeout {
            None => INFINITE,<commit_msg>base: windows: timer: fix interval < 1ms<commit_after>// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::os::windows::io::AsRawHandle;
use std::os::windows::io::RawHandle;
use std::ptr;
use std::time::Duration;

use win_util::LargeInteger;
use win_util::SecurityAttributes;
use win_util::SelfRelativeSecurityDescriptor;
use winapi::shared::minwindef::FALSE;
use winapi::shared::winerror::WAIT_TIMEOUT;
use winapi::um::synchapi::CancelWaitableTimer;
use winapi::um::synchapi::SetWaitableTimer;
use winapi::um::synchapi::WaitForSingleObject;
use winapi::um::winbase::CreateWaitableTimerA;
use winapi::um::winbase::INFINITE;
use winapi::um::winbase::WAIT_OBJECT_0;

use super::errno_result;
use super::win::nt_query_timer_resolution;
use super::Result;
use crate::descriptor::AsRawDescriptor;
use crate::descriptor::FromRawDescriptor;
use crate::descriptor::SafeDescriptor;
use crate::timer::Timer;
use crate::timer::WaitResult;

impl AsRawHandle for Timer {
    fn as_raw_handle(&self) -> RawHandle {
        self.handle.as_raw_descriptor()
    }
}

impl Timer {
    /// Creates a new timer.  The timer is initally disarmed and must be armed by calling
    /// `reset`. Note that this timer MAY wake/trigger early due to limitations on
    /// SetWaitableTimer (see https://github.com/rust-lang/rust/issues/43376).
    pub fn new() -> Result<Timer> {
        // Safe because this doesn't modify any memory and we check the return value.
        let handle = unsafe {
            CreateWaitableTimerA(
                // Not inheritable, duplicate before passing to child prcesses
                SecurityAttributes::new_with_security_descriptor(
                    SelfRelativeSecurityDescriptor::get_singleton(),
                    /* inherit= */ false,
                )
                .as_mut(),
                // This is a synchronization timer, not a manual-reset timer.
                FALSE,
                // TODO (colindr) b/145622516 - we may have to give this a name if we later
                // want to use names to test object equality
                ptr::null_mut(),
            )
        };

        if handle.is_null() {
            return errno_result();
        }

        // Safe because we uniquely own the file descriptor.
        Ok(Timer {
            handle: unsafe { SafeDescriptor::from_raw_descriptor(handle) },
            interval: None,
        })
    }

    /// Sets the timer to expire after `dur`. If `interval` is not `None` and non-zero
    /// it represents the period for repeated expirations after the initial expiration.
    /// Otherwise the timer will expire just once.  Cancels any existing duration and
    /// repeating interval.
    pub fn reset(&mut self, dur: Duration, mut interval: Option<Duration>) -> Result<()> {
        // If interval is 0 or None it means that this timer does not repeat. We
        // set self.interval to None in this case so it can easily be checked
        // in self.wait.
        if interval == Some(Duration::from_secs(0)) {
            interval = None;
        }
        self.interval = interval;
        // Windows timers use negative values for relative times, and positive
        // values for absolute times, so we'll use negative times.

        // Windows timers also use a 64 number of 100 nanosecond intervals,
        // which we get like so: (dur.as_secs()*1e7 + dur.subsec_nanos()/100)

        let due_time = LargeInteger::new(
            -((dur.as_secs() * 10_000_000 + (dur.subsec_nanos() as u64) / 100) as i64),
        );
        let period: i32 = match interval {
            // Period is in ms, and 0ms means non-periodic, so we convert to ms and
            // make sure it's non-zero.
            Some(int) => std::cmp::max(1, int.as_millis() as i32),
            // Period of 0ms=non-periodic.
            None => 0,
        };

        // Safe because this doesn't modify any memory and we check the return value.
        let ret = unsafe {
            SetWaitableTimer(
                self.as_raw_descriptor(),
                &*due_time,
                period,
                None,            // no completion routine
                ptr::null_mut(), // or routine argument
                FALSE,           // no restoring system from power conservation mode
            )
        };
        if ret == 0 {
            return errno_result();
        }

        Ok(())
    }

    /// Waits until the timer expires or an optional wait timeout expires, whichever happens first.
    ///
    /// # Returns
    ///
    /// - `WaitResult::Expired` if the timer expired.
    /// - `WaitResult::Timeout` if `timeout` was not `None` and the timer did not expire within the
    ///   specified timeout period.
    pub fn wait_for(&mut self, timeout: Option<Duration>) -> Result<WaitResult> {
        let timeout = match timeout {
            None => INFINITE,
{'fraction_non_alphanumeric': 0.10351924264251904, 'fraction_numerical': 0.011113397818481169, 'mean_word_length': 2.245075125208681, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 27, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7222185', 'n_tokens_mistral': 2748, 'n_tokens_neox': 2571, 'n_words': 892}