time: Add timeGetStandardSteadyClockTimePoint (uses sharedmem on 6.x+, ISteadyClock prior to 6.x)

This commit is contained in:
fincs 2020-04-10 19:42:31 +02:00
parent 2edfb7cc56
commit b18ae1c884
No known key found for this signature in database
GPG Key ID: 62C7609ADA219C60
2 changed files with 55 additions and 1 deletions

View File

@ -53,7 +53,7 @@ typedef struct {
} TimeLocationName;
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.
} 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.
Service* timeGetServiceSession_SystemClock(TimeType type);
/// Gets the Service object for ISteadyClock.
Service* timeGetServiceSession_SteadyClock(void);
/// Gets the Service object for ITimeZoneService.
Service* timeGetServiceSession_TimeZoneService(void);
/// [6.0.0+] Gets the address of the SharedMemory.
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.
* @param[in] type Clock to use.

View File

@ -1,5 +1,8 @@
#define NX_SERVICE_ASSUME_NON_DOMAIN
#include <string.h>
#include <stdatomic.h>
#include "service_guard.h"
#include "arm/counter.h"
#include "kernel/shmem.h"
#include "services/time.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_timeUserSystemClock;
static Service g_timeNetworkSystemClock;
static Service g_timeSteadyClock;
static Service g_timeTimeZoneService;
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 _timeGetSharedMemoryNativeHandle(Service* srv, Handle* out);
static void _timeReadSharedmemObj(void* out, size_t offset, size_t size);
NX_GENERATE_SERVICE_GUARD(time);
@ -51,6 +56,9 @@ Result _timeInitialize(void) {
if (R_SUCCEEDED(rc))
rc = _timeCmdGetSession(&g_timeSrv, &g_timeNetworkSystemClock, 1);
if (R_SUCCEEDED(rc))
rc = _timeCmdGetSession(&g_timeSrv, &g_timeSteadyClock, 2);
if (R_SUCCEEDED(rc))
rc = _timeCmdGetSession(&g_timeSrv, &g_timeTimeZoneService, 3);
@ -73,6 +81,7 @@ void _timeCleanup(void) {
shmemClose(&g_timeSharedmem);
serviceClose(&g_timeLocalSystemClock);
serviceClose(&g_timeTimeZoneService);
serviceClose(&g_timeSteadyClock);
serviceClose(&g_timeNetworkSystemClock);
serviceClose(&g_timeUserSystemClock);
serviceClose(&g_timeSrv);
@ -97,6 +106,10 @@ Service* timeGetServiceSession_SystemClock(TimeType type) {
}
}
Service* timeGetServiceSession_SteadyClock(void) {
return &g_timeSteadyClock;
}
Service* timeGetServiceSession_TimeZoneService(void) {
return &g_timeTimeZoneService;
}
@ -105,6 +118,20 @@ void* timeGetSharedmemAddr(void) {
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) {
return serviceDispatch(srv, cmd_id,
.out_num_objects = 1,
@ -131,6 +158,22 @@ static Result _appletCmdNoInOutU32(Service* srv, u32 *out, u32 cmd_id) {
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) {
Service *srv = timeGetServiceSession_SystemClock(type);