libroot_debug: Merge guarded heap into libroot_debug.
[haiku.git] / src / system / libroot / posix / time / clock_support.cpp
blob6f214f8660bfd5f128736b99d0910629d0883a60
1 /*
2 * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include <time.h>
9 #include <errno.h>
10 #include <pthread.h>
11 #include <sys/resource.h>
12 #include <unistd.h>
14 #include <OS.h>
16 #include <errno_private.h>
17 #include <syscall_utils.h>
19 #include <syscalls.h>
22 int
23 clock_getres(clockid_t clockID, struct timespec* resolution)
25 // check the clock ID
26 switch (clockID) {
27 case CLOCK_MONOTONIC:
28 case CLOCK_REALTIME:
29 case CLOCK_PROCESS_CPUTIME_ID:
30 case CLOCK_THREAD_CPUTIME_ID:
31 break;
32 default:
33 if (clockID < 0)
34 RETURN_AND_SET_ERRNO(EINVAL);
36 // For clock IDs we can't otherwise verify, try to get the time.
37 if (clockID != getpid()) {
38 timespec dummy;
39 if (clock_gettime(clockID, &dummy) != 0)
40 return -1;
44 // currently resolution is always 1us
45 if (resolution != NULL) {
46 resolution->tv_sec = 0;
47 resolution->tv_nsec = 1000;
50 return 0;
54 int
55 clock_gettime(clockid_t clockID, struct timespec* time)
57 // get the time in microseconds
58 bigtime_t microSeconds;
60 switch (clockID) {
61 case CLOCK_MONOTONIC:
62 microSeconds = system_time();
63 break;
64 case CLOCK_REALTIME:
65 microSeconds = real_time_clock_usecs();
66 break;
67 case CLOCK_PROCESS_CPUTIME_ID:
68 case CLOCK_THREAD_CPUTIME_ID:
69 default:
71 status_t error = _kern_get_clock(clockID, &microSeconds);
72 if (error != B_OK)
73 RETURN_AND_SET_ERRNO(error);
77 // set the result
78 time->tv_sec = microSeconds / 1000000;
79 time->tv_nsec = (microSeconds % 1000000) * 1000;
81 return 0;
85 int
86 clock_settime(clockid_t clockID, const struct timespec* time)
88 // can't set the monotonic clock
89 if (clockID == CLOCK_MONOTONIC)
90 RETURN_AND_SET_ERRNO(EINVAL);
92 // check timespec validity
93 if (time->tv_sec < 0 || time->tv_nsec < 0 || time->tv_nsec >= 1000000000)
94 RETURN_AND_SET_ERRNO(EINVAL);
96 // convert to microseconds and set the clock
97 bigtime_t microSeconds = (bigtime_t)time->tv_sec * 1000000
98 + time->tv_nsec / 1000;
100 RETURN_AND_SET_ERRNO(_kern_set_clock(clockID, microSeconds));
105 clock_nanosleep(clockid_t clockID, int flags, const struct timespec* time,
106 struct timespec* remainingTime)
108 // convert time to microseconds (round up)
109 if (time->tv_sec < 0 || time->tv_nsec < 0 || time->tv_nsec >= 1000000000)
110 RETURN_AND_TEST_CANCEL(EINVAL);
112 bigtime_t microSeconds = (bigtime_t)time->tv_sec * 1000000
113 + (time->tv_nsec + 999) / 1000;
115 // get timeout flags
116 uint32 timeoutFlags;
117 if ((flags & TIMER_ABSTIME) != 0) {
118 timeoutFlags = B_ABSOLUTE_TIMEOUT;
120 // ignore remainingTime for absolute waits
121 remainingTime = NULL;
122 } else
123 timeoutFlags = B_RELATIVE_TIMEOUT;
125 // wait
126 bigtime_t remainingMicroSeconds;
127 status_t error = _kern_snooze_etc(microSeconds, clockID, timeoutFlags,
128 remainingTime != NULL ? &remainingMicroSeconds : NULL);
130 // If interrupted and this is a relative wait, compute and return the
131 // remaining wait time.
132 if (error == B_INTERRUPTED && remainingTime != NULL) {
133 if (remainingMicroSeconds > 0) {
134 remainingTime->tv_sec = remainingMicroSeconds / 1000000;
135 remainingTime->tv_nsec = (remainingMicroSeconds % 1000000) * 1000;
136 } else {
137 // We were slow enough that the wait time passed anyway.
138 error = B_OK;
142 RETURN_AND_TEST_CANCEL(error);
147 clock_getcpuclockid(pid_t pid, clockid_t* _clockID)
149 if (pid < 0)
150 return ESRCH;
152 // The CPU clock ID for a process is simply the team ID. For pid == 0 we're
153 // supposed to return the current process' clock.
154 if (pid == 0) {
155 *_clockID = getpid();
156 return 0;
159 // test-get the time to verify the team exists and we have permission
160 bigtime_t microSeconds;
161 status_t error = _kern_get_clock(pid, &microSeconds);
162 if (error != B_OK) {
163 // Since pid is > 0, B_BAD_VALUE always means a team with that ID
164 // doesn't exist. Translate the error code accordingly.
165 if (error == B_BAD_VALUE)
166 return ESRCH;
167 return error;
170 *_clockID = pid;
171 return 0;