feat(systime): gettimeofday/itimer/utimes
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
#ifndef VLIBC_SYS_TIME_H
|
||||
#define VLIBC_SYS_TIME_H
|
||||
|
||||
/*
|
||||
* vlibc — <sys/time.h>.
|
||||
*
|
||||
* Wall-clock access and per-process interval timers expressed in
|
||||
* microseconds. Everything here is XSI or BSD legacy — POSIX.1-2008 base
|
||||
* leaves only timerisset in this header — so the whole surface is gated at
|
||||
* level 2:
|
||||
*
|
||||
* Level 2 (muslmimic): gettimeofday, settimeofday, getitimer,
|
||||
* setitimer, utimes, futimes, lutimes,
|
||||
* struct timeval, struct itimerval,
|
||||
* struct timezone, the timer* macros.
|
||||
*
|
||||
* struct timeval is the same type <sys/select.h> uses for select()'s
|
||||
* timeout; that header defines it under the shared guard below so the two
|
||||
* headers agree and either may be included first. The layout is the kernel
|
||||
* ABI on x86_64 (two longs), which is why gettimeofday/setitimer pass it
|
||||
* through unmodified.
|
||||
*
|
||||
* ITIMER_REAL/ITIMER_VIRTUAL/ITIMER_PROF are kernel ABI values (the
|
||||
* getitimer/setitimer `which` argument). None of these declarations carries
|
||||
* an intent attribute: every function performs I/O with side effects and
|
||||
* reports failures through errno, so const/pure would be unsound.
|
||||
*/
|
||||
|
||||
#include <vlibc/features.h>
|
||||
|
||||
#include <sys/types.h> /* time_t, suseconds_t */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if VLIBC_LEVEL_GE(2)
|
||||
/* Level 2 (muslmimic): XSI/BSD date-and-time interfaces. */
|
||||
|
||||
/* Interval-timer kinds (kernel ABI; the `which` argument). */
|
||||
#define ITIMER_REAL 0 /* count down in real time */
|
||||
#define ITIMER_VIRTUAL 1 /* count down in process virtual time */
|
||||
#define ITIMER_PROF 2 /* count down in process virtual + system time */
|
||||
|
||||
/*
|
||||
* Elapsed time in seconds and microseconds. Shared guard with
|
||||
* <sys/select.h>, which needs struct timeval for select()'s timeout at
|
||||
* level 1 and defines it under the same macro; either header may therefore
|
||||
* be included first. tv_usec holds 0..999999.
|
||||
*/
|
||||
#ifndef VLIBC_TIMEVAL_DEFINED
|
||||
#define VLIBC_TIMEVAL_DEFINED
|
||||
struct timeval
|
||||
{
|
||||
time_t tv_sec; /* seconds */
|
||||
suseconds_t tv_usec; /* microseconds */
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* An interval timer setting: it_value is the time to the next expiry,
|
||||
* it_interval the period between expiries after the first (both zero for a
|
||||
* one-shot or a disarmed timer). Kernel ABI layout (x86_64): two timevals.
|
||||
*/
|
||||
struct itimerval
|
||||
{
|
||||
struct timeval it_interval; /* interval between periodic expiries */
|
||||
struct timeval it_value; /* time to the next expiry */
|
||||
};
|
||||
|
||||
/*
|
||||
* Historic timezone record for settimeofday(). POSIX.1-2008 removed struct
|
||||
* timezone; it is kept for the legacy gettimeofday/settimeofday signatures,
|
||||
* whose tz argument is ignored (see src/time/gettimeofday.c).
|
||||
*/
|
||||
struct timezone
|
||||
{
|
||||
int tz_minuteswest; /* minutes west of Greenwich */
|
||||
int tz_dsttime; /* type of daylight-saving correction */
|
||||
};
|
||||
|
||||
/* True when the timer described by tp is armed. */
|
||||
#define timerisset(tp) ((tp)->tv_sec != 0 || (tp)->tv_usec != 0)
|
||||
|
||||
/* Disarm the timer described by tp (zero both fields). */
|
||||
#define timerclear(tp) ((tp)->tv_sec = (tp)->tv_usec = 0)
|
||||
|
||||
/*
|
||||
* Set *result to *a plus *b, normalizing the carry into tv_sec. The
|
||||
* arguments may be evaluated more than once (classic BSD form).
|
||||
*/
|
||||
#define timeradd(a, b, result) \
|
||||
do \
|
||||
{ \
|
||||
(result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
|
||||
(result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
|
||||
if ((result)->tv_usec >= 1000000) \
|
||||
{ \
|
||||
(result)->tv_sec++; \
|
||||
(result)->tv_usec -= 1000000; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Set *result to *a minus *b, normalizing the borrow out of tv_sec. The
|
||||
* arguments may be evaluated more than once (classic BSD form).
|
||||
*/
|
||||
#define timersub(a, b, result) \
|
||||
do \
|
||||
{ \
|
||||
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
|
||||
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
|
||||
if ((result)->tv_usec < 0) \
|
||||
{ \
|
||||
(result)->tv_sec--; \
|
||||
(result)->tv_usec += 1000000; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* True when *a op *b, compared first by tv_sec and, on equality, by
|
||||
* tv_usec. op is a comparison operator (timercmp(x, y, <=)). The
|
||||
* arguments may be evaluated more than once (classic BSD form).
|
||||
*/
|
||||
/* clang-format off */
|
||||
#define timercmp(a, b, op) \
|
||||
(((a)->tv_sec == (b)->tv_sec) ? ((a)->tv_usec op (b)->tv_usec) : ((a)->tv_sec op (b)->tv_sec))
|
||||
/* clang-format on */
|
||||
|
||||
/*
|
||||
* Read the current wall-clock time into tv (seconds since the Epoch and
|
||||
* microseconds 0..999999). tz is ignored for compatibility with the
|
||||
* historic two-argument form and may be anything, including NULL; tv may
|
||||
* also be NULL, in which case nothing is written. Return 0, or -1 with
|
||||
* errno set when tv points outside the address space.
|
||||
*/
|
||||
int
|
||||
gettimeofday(struct timeval *restrict tv, void *restrict tz);
|
||||
|
||||
/*
|
||||
* Set the kernel's idea of the current time from tv. tz, when not NULL, is
|
||||
* honored only together with tv; passing tz alone is unsupported (ENOTSUP).
|
||||
* Requires privilege. Return 0, or -1 with errno set.
|
||||
*/
|
||||
int
|
||||
settimeofday(const struct timeval *tv, const struct timezone *tz);
|
||||
|
||||
/*
|
||||
* Store the current setting of interval timer which (ITIMER_REAL,
|
||||
* ITIMER_VIRTUAL or ITIMER_PROF) through value. Return 0, or -1 with errno
|
||||
* set for an unknown which or when value points outside the address space.
|
||||
*/
|
||||
int
|
||||
getitimer(int which, struct itimerval *value);
|
||||
|
||||
/*
|
||||
* Arm interval timer which from value (when value is not NULL) and store
|
||||
* the previous setting through ovalue (when not NULL). A value whose
|
||||
* it_value is zero disarms the timer. Return 0, or -1 with errno set.
|
||||
*/
|
||||
int
|
||||
setitimer(int which, const struct itimerval *restrict value, struct itimerval *restrict ovalue);
|
||||
|
||||
/*
|
||||
* Set the access (times[0]) and modification (times[1]) timestamps of path.
|
||||
* A NULL times array sets both to the current time. Return 0, or -1 with
|
||||
* errno set.
|
||||
*/
|
||||
int
|
||||
utimes(const char *path, const struct timeval times[2]);
|
||||
|
||||
/* utimes() on the open file fd. */
|
||||
int
|
||||
futimes(int fd, const struct timeval times[2]);
|
||||
|
||||
/* utimes() on the symbolic link path itself, never following it. */
|
||||
int
|
||||
lutimes(const char *path, const struct timeval times[2]);
|
||||
|
||||
#endif /* VLIBC_LEVEL_GE(2) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VLIBC_SYS_TIME_H */
|
||||
Reference in New Issue
Block a user