Files
vlibc/include/sys/time.h
T

187 lines
7.5 KiB
C

#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 */