Skip to content

Commit

Permalink
Std.Time patch
Browse files Browse the repository at this point in the history
  • Loading branch information
IridescentRose committed Oct 11, 2020
1 parent 38fc162 commit d0bdc45
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 1 deletion.
155 changes: 155 additions & 0 deletions src/psp/os/time.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2015-2020 Zig Contributors
// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
const std = @import("std");
const builtin = std.builtin;
const assert = std.debug.assert;
const testing = std.testing;
const math = std.math;

usingnamespace @import("../include/psprtc.zig");
usingnamespace @import("../include/pspthreadman.zig");

/// Spurious wakeups are possible and no precision of timing is guaranteed.
/// TODO integrate with evented I/O
pub fn sleep(nanoseconds: u64) void {
_ = sceKernelDelayThread(@truncate(u32, nanoseconds / 1000));
}

/// Get a calendar timestamp, in seconds, relative to UTC 1970-01-01.
/// Precision of timing depends on the hardware and operating system.
/// The return value is signed because it is possible to have a date that is
/// before the epoch.
/// See `std.os.clock_gettime` for a POSIX timestamp.
pub fn timestamp() i64 {
var r : u64 = 0;
_ = sceRtcGetCurrentTick(&r);
return @intCast(i64, r / sceRtcGetTickResolution());
}

/// Get a calendar timestamp, in milliseconds, relative to UTC 1970-01-01.
/// Precision of timing depends on the hardware and operating system.
/// The return value is signed because it is possible to have a date that is
/// before the epoch.
/// See `std.os.clock_gettime` for a POSIX timestamp.
pub fn milliTimestamp() i64 {
var r : u64 = 0;
_ = sceRtcGetCurrentTick(&r);
return @intCast(i64, r / 1000);
}

/// Get a calendar timestamp, in nanoseconds, relative to UTC 1970-01-01.
/// Precision of timing depends on the hardware and operating system.
/// On Windows this has a maximum granularity of 100 nanoseconds.
/// The return value is signed because it is possible to have a date that is
/// before the epoch.
/// See `std.os.clock_gettime` for a POSIX timestamp.
pub fn nanoTimestamp() i128 {
var r : u64 = 0;
_ = sceRtcGetCurrentTick(&r);
return @intCast(i64, r * 1000);
}

// Divisions of a nanosecond.
pub const ns_per_us = 1000;
pub const ns_per_ms = 1000 * ns_per_us;
pub const ns_per_s = 1000 * ns_per_ms;
pub const ns_per_min = 60 * ns_per_s;
pub const ns_per_hour = 60 * ns_per_min;
pub const ns_per_day = 24 * ns_per_hour;
pub const ns_per_week = 7 * ns_per_day;

// Divisions of a microsecond.
pub const us_per_ms = 1000;
pub const us_per_s = 1000 * us_per_ms;
pub const us_per_min = 60 * us_per_s;
pub const us_per_hour = 60 * us_per_min;
pub const us_per_day = 24 * us_per_hour;
pub const us_per_week = 7 * us_per_day;

// Divisions of a millisecond.
pub const ms_per_s = 1000;
pub const ms_per_min = 60 * ms_per_s;
pub const ms_per_hour = 60 * ms_per_min;
pub const ms_per_day = 24 * ms_per_hour;
pub const ms_per_week = 7 * ms_per_day;

// Divisions of a second.
pub const s_per_min = 60;
pub const s_per_hour = s_per_min * 60;
pub const s_per_day = s_per_hour * 24;
pub const s_per_week = s_per_day * 7;


/// A monotonic high-performance timer.
/// Timer.start() must be called to initialize the struct, which captures
/// the counter frequency on windows and darwin, records the resolution,
/// and gives the user an opportunity to check for the existnece of
/// monotonic clocks without forcing them to check for error on each read.
/// .resolution is in nanoseconds on all platforms but .start_time's meaning
/// depends on the OS. On Windows and Darwin it is a hardware counter
/// value that requires calculation to convert to a meaninful unit.
pub const Timer = struct {
///if we used resolution's value when performing the
/// performance counter calc on windows/darwin, it would
/// be less precise
frequency: void,
resolution: u64,
start_time: u64,

pub const Error = error{TimerUnsupported};

/// At some point we may change our minds on RAW, but for now we're
/// sticking with posix standard MONOTONIC. For more information, see:
/// https://github.com/ziglang/zig/pull/933
const monotonic_clock_id = os.CLOCK_MONOTONIC;

/// Initialize the timer structure.
/// Can only fail when running in a hostile environment that intentionally injects
/// error values into syscalls, such as using seccomp on Linux to intercept
/// `clock_gettime`.
pub fn start() Timer {
var r : u64 = 0;
_ = sceRtcGetCurrentTick(&r);

return Timer{
.resolution = sceRtcGetTickResolution(),
.start_time = r,
.frequency = {},
};
}

/// Reads the timer value since start or the last reset in nanoseconds
pub fn read(self: Timer) u64 {
var clock = clockNative() - self.start_time;
return self.nativeDurationToNanos(clock);
}

/// Resets the timer value to 0/now.
pub fn reset(self: *Timer) void {
self.start_time = clockNative();
}

/// Returns the current value of the timer in nanoseconds, then resets it
pub fn lap(self: *Timer) u64 {
var now = clockNative();
var lap_time = self.nativeDurationToNanos(now - self.start_time);
self.start_time = now;
return lap_time;
}

//Gets our current ticker
fn clockNative() u64 {
var r : u64 = 0;
_ = sceRtcGetCurrentTick(&r);
return r;
}

//On PSP... duration = us
//Therefore duration * ns_per_us
fn nativeDurationToNanos(self: Timer, duration: u64) u64 {
return duration * ns_per_us;
}
};
2 changes: 1 addition & 1 deletion src/psp/sdk/pspthreadman.zig
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ pub extern fn sceKernelSuspendThread(thid: SceUID) c_int;
pub extern fn sceKernelResumeThread(thid: SceUID) c_int;
pub extern fn sceKernelWaitThreadEnd(thid: SceUID, timeout: [*c]SceUInt) c_int;
pub extern fn sceKernelWaitThreadEndCB(thid: SceUID, timeout: [*c]SceUInt) c_int;
pub extern fn sceKernelDelayThread(delay: SceUInt) c_int;
pub extern fn sceKernelDelayThread(delay: u32) c_int;
pub extern fn sceKernelDelayThreadCB(delay: SceUInt) c_int;
pub extern fn sceKernelDelaySysClockThread(delay: [*c]SceKernelSysClock) c_int;
pub extern fn sceKernelDelaySysClockThreadCB(delay: [*c]SceKernelSysClock) c_int;
Expand Down

0 comments on commit d0bdc45

Please sign in to comment.