diff --git a/include/nuttx/clock.h b/include/nuttx/clock.h index 294f528d81..ace7a20a48 100644 --- a/include/nuttx/clock.h +++ b/include/nuttx/clock.h @@ -81,6 +81,21 @@ # undef CONFIG_SYSTEM_TIME64 #endif +/* The following are the bit fields of the clockid_t + * bit 0~2: the clock type + * CLOCK_REALTIME - 0 + * CLOCK_MONOTONIC - 1 + * CLOCK_PROCESS_CPUTIME_ID - 2 + * CLOCK_THREAD_CPUTIME_ID - 3 + * CLOCK_BOOTTIME - 4 + * bit 3~32: the pid or tid value + * + * The CLOCK_MASK are using to extract the clock_type from the clockid_t + */ + +#define CLOCK_MASK 7 +#define CLOCK_SHIFT 3 + /* Timing constants *********************************************************/ #define NSEC_PER_SEC 1000000000L /* Seconds */ diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h index 949c629450..5218e5f292 100644 --- a/include/sys/syscall_lookup.h +++ b/include/sys/syscall_lookup.h @@ -168,6 +168,7 @@ SYSCALL_LOOKUP(clock_nanosleep, 4) */ SYSCALL_LOOKUP(clock, 0) +SYSCALL_LOOKUP(clock_getcpuclockid, 2) SYSCALL_LOOKUP(clock_getres, 2) SYSCALL_LOOKUP(clock_gettime, 2) SYSCALL_LOOKUP(clock_settime, 2) diff --git a/include/time.h b/include/time.h index 6f08b4a02b..72e35584c9 100644 --- a/include/time.h +++ b/include/time.h @@ -201,6 +201,7 @@ clock_t clock(void); int clock_settime(clockid_t clockid, FAR const struct timespec *tp); int clock_gettime(clockid_t clockid, FAR struct timespec *tp); int clock_getres(clockid_t clockid, FAR struct timespec *res); +int clock_getcpuclockid(pid_t pid, FAR clockid_t *clockid); int timespec_get(FAR struct timespec *t, int b); time_t timegm(FAR struct tm *tp); diff --git a/sched/clock/Make.defs b/sched/clock/Make.defs index 5c51e902be..fc7ff0a952 100644 --- a/sched/clock/Make.defs +++ b/sched/clock/Make.defs @@ -21,7 +21,7 @@ CSRCS += clock_initialize.c clock_settime.c clock_gettime.c clock_getres.c CSRCS += clock_abstime2ticks.c CSRCS += clock_systime_ticks.c clock_systime_timespec.c -CSRCS += clock.c +CSRCS += clock.c clock_getcpuclockid.c ifeq ($(CONFIG_CLOCK_TIMEKEEPING),y) CSRCS += clock_timekeeping.c diff --git a/sched/clock/clock_getcpuclockid.c b/sched/clock/clock_getcpuclockid.c new file mode 100644 index 0000000000..d26731bee1 --- /dev/null +++ b/sched/clock/clock_getcpuclockid.c @@ -0,0 +1,74 @@ +/**************************************************************************** + * sched/clock/clock_getcpuclockid.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "clock/clock.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: clock_getcpuclockid + * + * Description: + * The function shall return clock id of the CPU-time clock of the process + * specified by pid + * + * Input Parameters: + * pid - the specified process id + * clockid - the clock type that need to setup + * + * Returned Value: + * Return 0 on success, return error number on error + * + ****************************************************************************/ + +int clock_getcpuclockid(pid_t pid, FAR clockid_t *clockid) +{ + if (pid < 0) + { + set_errno(EINVAL); + return ERROR; + } + + /* If the pid is 0, we need to use the pid of current process */ + + if (pid == 0) + { + pid = getpid(); + } + + /* For clock_getcpuclockid, the clock type are + * CLOCK_PROCESS_CPUTIME_ID + */ + + *clockid = (pid << CLOCK_SHIFT) | CLOCK_PROCESS_CPUTIME_ID; + return OK; +} diff --git a/sched/clock/clock_getres.c b/sched/clock/clock_getres.c index c5b27104f7..99ed173a5f 100644 --- a/sched/clock/clock_getres.c +++ b/sched/clock/clock_getres.c @@ -45,11 +45,12 @@ int clock_getres(clockid_t clock_id, struct timespec *res) { - int ret = OK; + clockid_t clock_type = clock_id & CLOCK_MASK; + int ret = OK; - sinfo("clock_id=%d\n", clock_id); + sinfo("clock_id=%d, clock_type=%d\n", clock_id, clock_type); - switch (clock_id) + switch (clock_type) { default: serr("Returning ERROR\n"); diff --git a/sched/clock/clock_gettime.c b/sched/clock/clock_gettime.c index 4f1d5e0f4b..2842e08292 100644 --- a/sched/clock/clock_gettime.c +++ b/sched/clock/clock_gettime.c @@ -31,6 +31,7 @@ #include #include +#include #include #include "clock/clock.h" @@ -58,6 +59,11 @@ int clock_gettime(clockid_t clock_id, struct timespec *tp) #endif int ret = OK; + clockid_t clock_type = clock_id & CLOCK_MASK; +#ifdef CONFIG_SCHED_CRITMONITOR + pid_t pid = clock_id >> CLOCK_SHIFT; +#endif + DEBUGASSERT(tp != NULL); /* CLOCK_MONOTONIC is an optional under POSIX: "If the Monotonic Clock @@ -72,7 +78,7 @@ int clock_gettime(clockid_t clock_id, struct timespec *tp) * is invoked with a clock_id argument of CLOCK_MONOTONIC." */ - if (clock_id == CLOCK_MONOTONIC || clock_id == CLOCK_BOOTTIME) + if (clock_type == CLOCK_MONOTONIC || clock_type == CLOCK_BOOTTIME) { /* The the time elapsed since the timer was initialized at power on * reset. @@ -87,7 +93,7 @@ int clock_gettime(clockid_t clock_id, struct timespec *tp) * backward as the system time-of-day clock is changed. */ - else if (clock_id == CLOCK_REALTIME) + else if (clock_type == CLOCK_REALTIME) { /* Get the elapsed time since the time-of-day was last set. * clock_systime_timespec() provides the time since power was applied; @@ -131,6 +137,57 @@ int clock_gettime(clockid_t clock_id, struct timespec *tp) } #endif /* CONFIG_CLOCK_TIMEKEEPING */ } +#ifdef CONFIG_SCHED_CRITMONITOR + else if (clock_type == CLOCK_THREAD_CPUTIME_ID) + { + FAR struct tcb_s *tcb; + + if (pid == 0) + { + /* Fetch the THREAD_CPUTIME for current thread */ + + tcb = nxsched_self(); + } + else + { + tcb = nxsched_get_tcb(pid); + } + + up_perf_convert(tcb->run_time, tp); + } + else if (clock_type == CLOCK_PROCESS_CPUTIME_ID) + { + FAR struct task_group_s *group; + unsigned long runtime; + irqstate_t flags; + int i; + FAR struct tcb_s *tcb; + + if (pid == 0) + { + /* Fetch the PROCESS_CPUTIME for current process */ + + tcb = nxsched_self(); + } + else + { + tcb = nxsched_get_tcb(pid); + } + + group = tcb->group; + runtime = 0; + + flags = enter_critical_section(); + for (i = group->tg_nmembers - 1; i >= 0; i--) + { + tcb = nxsched_get_tcb(group->tg_members[i]); + runtime += tcb->run_time; + } + + leave_critical_section(flags); + up_perf_convert(runtime, tp); + } +#endif else { ret = -EINVAL; diff --git a/syscall/syscall.csv b/syscall/syscall.csv index c0f048f11b..f40c2de7d5 100644 --- a/syscall/syscall.csv +++ b/syscall/syscall.csv @@ -13,6 +13,7 @@ "chown","unistd.h","","int","FAR const char *","uid_t","gid_t" "clearenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","int" "clock","time.h","","clock_t" +"clock_getcpuclockid","time.h","","int","pid_t","FAR clockid_t *" "clock_getres","time.h","","int","clockid_t","FAR struct timespec *" "clock_gettime","time.h","","int","clockid_t","FAR struct timespec *" "clock_nanosleep","time.h","","int","clockid_t","int","FAR const struct timespec *", "FAR struct timespec *"