mirror of
https://github.com/switchbrew/libnx.git
synced 2025-08-05 16:09:24 +02:00
time: Add timeGetStandardSteadyClockTimePoint (uses sharedmem on 6.x+, ISteadyClock prior to 6.x)
This commit is contained in:
parent
2edfb7cc56
commit
b18ae1c884
@ -53,7 +53,7 @@ typedef struct {
|
|||||||
} TimeLocationName;
|
} TimeLocationName;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
s64 time_point; ///< A point in time.
|
s64 time_point; ///< Monotonic count in seconds.
|
||||||
Uuid source_id; ///< An ID representing the clock source.
|
Uuid source_id; ///< An ID representing the clock source.
|
||||||
} TimeSteadyClockTimePoint;
|
} TimeSteadyClockTimePoint;
|
||||||
|
|
||||||
@ -74,12 +74,23 @@ Service* timeGetServiceSession(void);
|
|||||||
/// Gets the Service object for ISystemClock with the specified \ref TimeType. This will return NULL when the type is invalid.
|
/// Gets the Service object for ISystemClock with the specified \ref TimeType. This will return NULL when the type is invalid.
|
||||||
Service* timeGetServiceSession_SystemClock(TimeType type);
|
Service* timeGetServiceSession_SystemClock(TimeType type);
|
||||||
|
|
||||||
|
/// Gets the Service object for ISteadyClock.
|
||||||
|
Service* timeGetServiceSession_SteadyClock(void);
|
||||||
|
|
||||||
/// Gets the Service object for ITimeZoneService.
|
/// Gets the Service object for ITimeZoneService.
|
||||||
Service* timeGetServiceSession_TimeZoneService(void);
|
Service* timeGetServiceSession_TimeZoneService(void);
|
||||||
|
|
||||||
/// [6.0.0+] Gets the address of the SharedMemory.
|
/// [6.0.0+] Gets the address of the SharedMemory.
|
||||||
void* timeGetSharedmemAddr(void);
|
void* timeGetSharedmemAddr(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the timepoint for the standard steady clock.
|
||||||
|
* @param[out] out Output timepoint (see \ref TimeSteadyClockTimePoint)
|
||||||
|
* @remark The standard steady clock counts time since the RTC was configured (usually this happens during manufacturing).
|
||||||
|
* @return Result code.
|
||||||
|
*/
|
||||||
|
Result timeGetStandardSteadyClockTimePoint(TimeSteadyClockTimePoint *out);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the time for the specified clock.
|
* @brief Gets the time for the specified clock.
|
||||||
* @param[in] type Clock to use.
|
* @param[in] type Clock to use.
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
#define NX_SERVICE_ASSUME_NON_DOMAIN
|
#define NX_SERVICE_ASSUME_NON_DOMAIN
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
#include "service_guard.h"
|
#include "service_guard.h"
|
||||||
|
#include "arm/counter.h"
|
||||||
#include "kernel/shmem.h"
|
#include "kernel/shmem.h"
|
||||||
#include "services/time.h"
|
#include "services/time.h"
|
||||||
#include "runtime/hosversion.h"
|
#include "runtime/hosversion.h"
|
||||||
@ -9,6 +12,7 @@ __attribute__((weak)) TimeServiceType __nx_time_service_type = TimeServiceType_U
|
|||||||
static Service g_timeSrv;
|
static Service g_timeSrv;
|
||||||
static Service g_timeUserSystemClock;
|
static Service g_timeUserSystemClock;
|
||||||
static Service g_timeNetworkSystemClock;
|
static Service g_timeNetworkSystemClock;
|
||||||
|
static Service g_timeSteadyClock;
|
||||||
static Service g_timeTimeZoneService;
|
static Service g_timeTimeZoneService;
|
||||||
static Service g_timeLocalSystemClock;
|
static Service g_timeLocalSystemClock;
|
||||||
|
|
||||||
@ -16,6 +20,7 @@ static SharedMemory g_timeSharedmem;
|
|||||||
|
|
||||||
static Result _timeCmdGetSession(Service* srv, Service* srv_out, u32 cmd_id);
|
static Result _timeCmdGetSession(Service* srv, Service* srv_out, u32 cmd_id);
|
||||||
static Result _timeGetSharedMemoryNativeHandle(Service* srv, Handle* out);
|
static Result _timeGetSharedMemoryNativeHandle(Service* srv, Handle* out);
|
||||||
|
static void _timeReadSharedmemObj(void* out, size_t offset, size_t size);
|
||||||
|
|
||||||
NX_GENERATE_SERVICE_GUARD(time);
|
NX_GENERATE_SERVICE_GUARD(time);
|
||||||
|
|
||||||
@ -51,6 +56,9 @@ Result _timeInitialize(void) {
|
|||||||
if (R_SUCCEEDED(rc))
|
if (R_SUCCEEDED(rc))
|
||||||
rc = _timeCmdGetSession(&g_timeSrv, &g_timeNetworkSystemClock, 1);
|
rc = _timeCmdGetSession(&g_timeSrv, &g_timeNetworkSystemClock, 1);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc))
|
||||||
|
rc = _timeCmdGetSession(&g_timeSrv, &g_timeSteadyClock, 2);
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc))
|
if (R_SUCCEEDED(rc))
|
||||||
rc = _timeCmdGetSession(&g_timeSrv, &g_timeTimeZoneService, 3);
|
rc = _timeCmdGetSession(&g_timeSrv, &g_timeTimeZoneService, 3);
|
||||||
|
|
||||||
@ -73,6 +81,7 @@ void _timeCleanup(void) {
|
|||||||
shmemClose(&g_timeSharedmem);
|
shmemClose(&g_timeSharedmem);
|
||||||
serviceClose(&g_timeLocalSystemClock);
|
serviceClose(&g_timeLocalSystemClock);
|
||||||
serviceClose(&g_timeTimeZoneService);
|
serviceClose(&g_timeTimeZoneService);
|
||||||
|
serviceClose(&g_timeSteadyClock);
|
||||||
serviceClose(&g_timeNetworkSystemClock);
|
serviceClose(&g_timeNetworkSystemClock);
|
||||||
serviceClose(&g_timeUserSystemClock);
|
serviceClose(&g_timeUserSystemClock);
|
||||||
serviceClose(&g_timeSrv);
|
serviceClose(&g_timeSrv);
|
||||||
@ -97,6 +106,10 @@ Service* timeGetServiceSession_SystemClock(TimeType type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Service* timeGetServiceSession_SteadyClock(void) {
|
||||||
|
return &g_timeSteadyClock;
|
||||||
|
}
|
||||||
|
|
||||||
Service* timeGetServiceSession_TimeZoneService(void) {
|
Service* timeGetServiceSession_TimeZoneService(void) {
|
||||||
return &g_timeTimeZoneService;
|
return &g_timeTimeZoneService;
|
||||||
}
|
}
|
||||||
@ -105,6 +118,20 @@ void* timeGetSharedmemAddr(void) {
|
|||||||
return shmemGetAddr(&g_timeSharedmem);
|
return shmemGetAddr(&g_timeSharedmem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _timeReadSharedmemObj(void* out, size_t offset, size_t size) {
|
||||||
|
void* addr = (u8*)shmemGetAddr(&g_timeSharedmem) + offset;
|
||||||
|
|
||||||
|
vu32* counter = (vu32*)addr;
|
||||||
|
void* data = (u8*)addr + 8;
|
||||||
|
|
||||||
|
u32 cur_counter;
|
||||||
|
do {
|
||||||
|
cur_counter = *counter;
|
||||||
|
memcpy(out, (u8*)data + (cur_counter&1)*size, size);
|
||||||
|
atomic_thread_fence(memory_order_consume);
|
||||||
|
} while (cur_counter != *counter);
|
||||||
|
}
|
||||||
|
|
||||||
static Result _timeCmdGetSession(Service* srv, Service* srv_out, u32 cmd_id) {
|
static Result _timeCmdGetSession(Service* srv, Service* srv_out, u32 cmd_id) {
|
||||||
return serviceDispatch(srv, cmd_id,
|
return serviceDispatch(srv, cmd_id,
|
||||||
.out_num_objects = 1,
|
.out_num_objects = 1,
|
||||||
@ -131,6 +158,22 @@ static Result _appletCmdNoInOutU32(Service* srv, u32 *out, u32 cmd_id) {
|
|||||||
return serviceDispatchOut(srv, cmd_id, *out);
|
return serviceDispatchOut(srv, cmd_id, *out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result timeGetStandardSteadyClockTimePoint(TimeSteadyClockTimePoint *out) {
|
||||||
|
if (!shmemGetAddr(&g_timeSharedmem)) {
|
||||||
|
return serviceDispatchOut(&g_timeSteadyClock, 0, *out);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct { // SteadyClockContext
|
||||||
|
u64 internal_offset;
|
||||||
|
Uuid source_id;
|
||||||
|
} context;
|
||||||
|
|
||||||
|
_timeReadSharedmemObj(&context, 0x00, sizeof(context));
|
||||||
|
out->time_point = (context.internal_offset + armTicksToNs(armGetSystemTick())) / 1000000000UL;
|
||||||
|
out->source_id = context.source_id;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Result timeGetCurrentTime(TimeType type, u64 *timestamp) {
|
Result timeGetCurrentTime(TimeType type, u64 *timestamp) {
|
||||||
Service *srv = timeGetServiceSession_SystemClock(type);
|
Service *srv = timeGetServiceSession_SystemClock(type);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user