/* * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ #include #include #include #include #include #include #include #include #include #include #include #include int clock_getres(clockid_t clockID, struct timespec* resolution) { // check the clock ID switch (clockID) { case CLOCK_MONOTONIC: case CLOCK_REALTIME: case CLOCK_PROCESS_CPUTIME_ID: case CLOCK_THREAD_CPUTIME_ID: break; default: if (clockID < 0) RETURN_AND_SET_ERRNO(EINVAL); // For clock IDs we can't otherwise verify, try to get the time. if (clockID != getpid()) { timespec dummy; if (clock_gettime(clockID, &dummy) != 0) return -1; } } // currently resolution is always 1us if (resolution != NULL) { resolution->tv_sec = 0; resolution->tv_nsec = 1000; } return 0; } int clock_gettime(clockid_t clockID, struct timespec* time) { bigtime_t microSeconds; switch (clockID) { case CLOCK_MONOTONIC: microSeconds = system_time(); break; case CLOCK_REALTIME: microSeconds = real_time_clock_usecs(); break; case CLOCK_PROCESS_CPUTIME_ID: case CLOCK_THREAD_CPUTIME_ID: default: { status_t error = _kern_get_clock(clockID, µSeconds); if (error != B_OK) RETURN_AND_SET_ERRNO(error); } } bigtime_to_timespec(microSeconds, *time); return 0; } int clock_settime(clockid_t clockID, const struct timespec* time) { // can't set the monotonic clock if (clockID == CLOCK_MONOTONIC) RETURN_AND_SET_ERRNO(EINVAL); bigtime_t microSeconds; if (!timespec_to_bigtime(*time, microSeconds)) RETURN_AND_SET_ERRNO(EINVAL); RETURN_AND_SET_ERRNO(_kern_set_clock(clockID, microSeconds)); } int clock_nanosleep(clockid_t clockID, int flags, const struct timespec* time, struct timespec* remainingTime) { // convert time to microseconds (round up) bigtime_t microSeconds; if (!timespec_to_bigtime(*time, microSeconds)) RETURN_AND_TEST_CANCEL(EINVAL); // get timeout flags uint32 timeoutFlags; if ((flags & TIMER_ABSTIME) != 0) { timeoutFlags = B_ABSOLUTE_TIMEOUT; // ignore remainingTime for absolute waits remainingTime = NULL; } else timeoutFlags = B_RELATIVE_TIMEOUT; // wait bigtime_t remainingMicroSeconds; status_t error = _kern_snooze_etc(microSeconds, clockID, timeoutFlags, remainingTime != NULL ? &remainingMicroSeconds : NULL); // If interrupted and this is a relative wait, compute and return the // remaining wait time. if (error == B_INTERRUPTED && remainingTime != NULL) { if (remainingMicroSeconds > 0) { bigtime_to_timespec(remainingMicroSeconds, *remainingTime); } else { // We were slow enough that the wait time passed anyway. error = B_OK; } } RETURN_AND_TEST_CANCEL(error); } int clock_getcpuclockid(pid_t pid, clockid_t* _clockID) { if (pid < 0) return ESRCH; // The CPU clock ID for a process is simply the team ID. For pid == 0 we're // supposed to return the current process' clock. if (pid == 0) { *_clockID = getpid(); return 0; } status_t error = _kern_get_cpuclockid(pid, TEAM_ID, _clockID); if (error != B_OK) { // Since pid is > 0, B_BAD_VALUE always means a team with that ID // doesn't exist. Translate the error code accordingly. if (error == B_BAD_VALUE) return ESRCH; return error; } return 0; } int pthread_getcpuclockid(pthread_t thread, clockid_t* _clockID) { if (thread->id < 0) return ESRCH; status_t error = _kern_get_cpuclockid(thread->id, THREAD_ID, _clockID); if (error != B_OK) { // Since thread->id is > 0, B_BAD_VALUE always means a thread with that ID // doesn't exist. Translate the error code accordingly. if (error == B_BAD_VALUE) return ESRCH; return error; } return 0; }