diff --git a/arch/sim/src/up_critmon.c b/arch/sim/src/up_critmon.c new file mode 100644 index 0000000000..b9ddbfca64 --- /dev/null +++ b/arch/sim/src/up_critmon.c @@ -0,0 +1,90 @@ +/************************************************************************************ + * arch/sim/src/up_critmon.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* From nuttx/clock.h */ + +#define NSEC_PER_SEC 1000000000 + +/* From fixedmath.h */ + +#define b32ONE 0x0000000100000000 /* 1 */ +#define b32toi(a) ((a) >> 32) /* Conversion to integer */ +#define itob32(i) (((b32_t)(i)) << 32) /* Conversion from integer */ +#define b32frac(a) ((a) & 0x00000000ffffffff) /* Take fractional part */ + +/************************************************************************************ + * Private Types + ************************************************************************************/ + +/* From fixedmath.h */ + +typedef int64_t b32_t; + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: up_critmon_gettime + ************************************************************************************/ + +uint32_t up_critmon_gettime(void) +{ + return (uint32_t)clock() + 1; /* Avoid returning zero which means clock-not-ready */ +} + +/************************************************************************************ + * Name: up_critmon_gettime + ************************************************************************************/ + +void up_critmon_convert(uint32_t elapsed, struct timespec *ts) +{ + b32_t b32elapsed; + + b32elapsed = itob32(elapsed) / CLOCKS_PER_SEC; + ts->tv_sec = b32toi(b32elapsed); + ts->tv_nsec = NSEC_PER_SEC * b32frac(b32elapsed) / b32ONE; +} diff --git a/fs/procfs/fs_procfscritmon.c b/fs/procfs/fs_procfscritmon.c index 8518dc1ac8..37b01635dd 100644 --- a/fs/procfs/fs_procfscritmon.c +++ b/fs/procfs/fs_procfscritmon.c @@ -242,7 +242,7 @@ static ssize_t critmon_read_cpu(FAR struct critmon_file_s *attr, /* Generate output for maximum time pre-emption disabled */ - linesize = snprintf(attr->line, CRITMON_LINELEN, "%2d,%lu.%09lu,", + linesize = snprintf(attr->line, CRITMON_LINELEN, "%d,%lu.%09lu,", cpu, (unsigned long)maxtime.tv_sec, (unsigned long)maxtime.tv_nsec); copysize = procfs_memcpy(attr->line, linesize, buffer, buflen, offset); diff --git a/sched/sched/sched_critmonitor.c b/sched/sched/sched_critmonitor.c index 674c055ac0..1193427681 100644 --- a/sched/sched/sched_critmonitor.c +++ b/sched/sched/sched_critmonitor.c @@ -136,21 +136,27 @@ void sched_critmon_preemption(FAR struct tcb_s *tcb, bool state) /* Disabling.. Save the thread start time */ tcb->premp_start = up_critmon_gettime(); - DISABLE_PREEMPT(tcb); - /* Save the global start time */ + /* Zero means that the timer is not ready */ - g_premp_start[cpu] = tcb->premp_start; + if (tcb->premp_start != 0) + { + DISABLE_PREEMPT(tcb); + + /* Save the global start time */ + + g_premp_start[cpu] = tcb->premp_start; + } } else if (tcb->premp_start != 0) { - DEBUGASSERT(PREEMPT_ISDISABLED(tcb)); - /* Re-enabling.. Check for the max elapsed time */ uint32_t now = up_critmon_gettime(); uint32_t elapsed = now - tcb->premp_start; + DEBUGASSERT(now != 0 && PREEMPT_ISDISABLED(tcb)); + tcb->premp_start = 0; if (elapsed > tcb->premp_max) { @@ -195,9 +201,16 @@ void sched_critmon_csection(FAR struct tcb_s *tcb, bool state) DEBUGASSERT(tcb->crit_start == 0); tcb->crit_start = up_critmon_gettime(); - /* Set the global start time */ + /* Zero means that the timer is not ready */ - g_crit_start[cpu] = tcb->crit_start; + if (tcb->crit_start != 0) + { + ENTER_CSECTION(tcb); + + /* Set the global start time */ + + g_crit_start[cpu] = tcb->crit_start; + } } else if (tcb->crit_start != 0) { @@ -206,13 +219,15 @@ void sched_critmon_csection(FAR struct tcb_s *tcb, bool state) uint32_t now = up_critmon_gettime(); uint32_t elapsed = now - tcb->crit_start; + DEBUGASSERT(now != 0 && IN_CSECTION(tcb)); + tcb->crit_start = 0; if (elapsed > tcb->crit_max) { tcb->crit_max = elapsed; } - ENTER_CSECTION(tcb); + LEAVE_CSECTION(tcb); /* Check for the global max elapsed time */ @@ -252,6 +267,8 @@ void sched_critmon_resume(FAR struct tcb_s *tcb) /* Yes.. Save the start time */ tcb->premp_start = up_critmon_gettime(); + DEBUGASSERT(tcb->premp_start != 0); + if (g_premp_start[cpu] == 0) { g_premp_start[cpu] = tcb->premp_start; @@ -277,6 +294,8 @@ void sched_critmon_resume(FAR struct tcb_s *tcb) /* Yes.. Save the start time */ tcb->crit_start = up_critmon_gettime(); + DEBUGASSERT(tcb->crit_start != 0); + if (g_crit_start[cpu] == 0) { g_crit_start[cpu] = tcb->crit_start;