summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/include/kernel/timemgr.H41
-rw-r--r--src/include/time.h61
-rw-r--r--src/kernel/timemgr.C9
-rw-r--r--src/lib/syscall_time.C28
-rw-r--r--src/usr/testcore/lib/time.H70
5 files changed, 207 insertions, 2 deletions
diff --git a/src/include/kernel/timemgr.H b/src/include/kernel/timemgr.H
index 4f4bc4413..0590dedff 100644
--- a/src/include/kernel/timemgr.H
+++ b/src/include/kernel/timemgr.H
@@ -32,36 +32,72 @@
class Scheduler;
+/** Struct to hold sleeping tasks in a pqueue */
struct _TimeManager_Delay_t
{
_TimeManager_Delay_t * next;
- _TimeManager_Delay_t * prev;
+ _TimeManager_Delay_t * prev;
uint64_t key;
task_t* task;
};
+/** @class TimeManager
+ * @brief Keeps track of sleeping of tasks and conversions between TB and time.
+ */
class TimeManager
{
public:
enum
{
+ /** Number of time-slices to allow per second.
+ *
+ * Context length becomes (1/TIMESLICE_PER_SECOND) sec.
+ */
TIMESLICE_PER_SEC = 1000,
};
+ /** Initialize the time subsystem. */
static void init();
+ /** Return the number of ticks per time-slice. */
static uint64_t getTimeSliceCount()
{
return iv_timebaseFreq / TIMESLICE_PER_SEC;
};
+ /** Returns the value of the processor timebase register. */
static uint64_t getCurrentTimeBase()
{
return getTB();
};
+ /** Converts seconds/nsecs to timebase ticks.
+ *
+ * Typically this is used for calculating the number of ticks in an
+ * interval.
+ *
+ * @param[in] i_sec - Number of seconds.
+ * @param[in] i_nsec - Number of nsecs.
+ *
+ * @return Number of timebase ticks.
+ */
static uint64_t convertSecToTicks(uint64_t i_sec, uint64_t i_nsec);
+ /** Converts timebase ticks to seconds/nsecs.
+ *
+ * @param[in] i_ticks - Number of ticks.
+ * @param[out] o_sec - Number of seconds.
+ * @param[out] o_nsec - Number of nsecs.
+ */
+ static void convertTicksToSec(uint64_t i_ticks,
+ uint64_t& o_sec, uint64_t& o_nsec);
+ /** Delay (sleep) a task for a length of time.
+ *
+ * @param[in] t - Task to delay.
+ * @param[in] i_sec - Seconds.
+ * @param[in] i_nsec - Nsecs.
+ */
static void delayTask(task_t* t, uint64_t i_sec, uint64_t i_nsec);
+ /** Checks the sleep queue to determine if any tasks should be woken. */
static void checkReleaseTasks(Scheduler* s);
protected:
@@ -72,9 +108,10 @@ class TimeManager
void _init();
void _delayTask(task_t* t, uint64_t i_sec, uint64_t i_nsec);
void _checkReleaseTasks(Scheduler* s);
-
+
Util::Locked::PQueue<_TimeManager_Delay_t, uint64_t>
iv_taskList[KERNEL_MAX_SUPPORTED_CPUS];
+ /** Frequency of the timebase register in Hz. (ticks per second) */
static uint64_t iv_timebaseFreq;
};
diff --git a/src/include/time.h b/src/include/time.h
new file mode 100644
index 000000000..cc3a9e4bf
--- /dev/null
+++ b/src/include/time.h
@@ -0,0 +1,61 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/include/time.h $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __TIME_H
+#define __TIME_H
+
+#include <stdint.h>
+
+// POSIX structure for time (sec / nsec pairs).
+struct timespec
+{
+ uint64_t tv_sec;
+ uint64_t tv_nsec;
+};
+typedef struct timespec timespec_t;
+
+// POSIX clock IDs.
+typedef enum
+{
+ CLOCK_REALTIME = 0,
+ CLOCK_MONOTONIC = 1
+} clockid_t;
+
+/** @fn clock_gettime
+ * @brief Reads the clock value from a POSIX clock.
+ *
+ * @note Currently, we only support CLOCK_MONOTONIC.
+ * CLOCK_REALTIME requires synchronization of the timebase with the FSP
+ * RTC.
+ *
+ * @param[in] clk_id - The clock ID to read.
+ * @param[out] tp - The timespec struct to store the clock value in.
+ *
+ * @return 0 or -(errno).
+ * @retval 0 - SUCCESS.
+ * @retval -EINVAL - Invalid clock requested.
+ * @retval -EFAULT - NULL ptr given for timespec struct.
+ *
+ */
+int clock_gettime(clockid_t clk_id, timespec_t* tp);
+
+#endif
diff --git a/src/kernel/timemgr.C b/src/kernel/timemgr.C
index 896871a4d..b6be8cb90 100644
--- a/src/kernel/timemgr.C
+++ b/src/kernel/timemgr.C
@@ -49,6 +49,15 @@ uint64_t TimeManager::convertSecToTicks(uint64_t i_sec, uint64_t i_nsec)
return result;
}
+void TimeManager::convertTicksToSec(uint64_t i_ticks,
+ uint64_t& o_sec, uint64_t& o_nsec)
+{
+ o_sec = i_ticks / iv_timebaseFreq;
+
+ o_nsec = (i_ticks - (o_sec * iv_timebaseFreq)) * 1000;
+ o_nsec /= (iv_timebaseFreq / 1000000);
+}
+
void TimeManager::delayTask(task_t* t, uint64_t i_sec, uint64_t i_nsec)
{
Singleton<TimeManager>::instance()._delayTask(t,i_sec,i_nsec);
diff --git a/src/lib/syscall_time.C b/src/lib/syscall_time.C
index d4ea6d0a7..819b605b0 100644
--- a/src/lib/syscall_time.C
+++ b/src/lib/syscall_time.C
@@ -20,8 +20,11 @@
// Origin: 30
//
// IBM_PROLOG_END
+#include <time.h>
#include <sys/time.h>
#include <sys/syscall.h>
+#include <errno.h>
+#include <kernel/timemgr.H>
using namespace Systemcalls;
@@ -29,3 +32,28 @@ void nanosleep(uint64_t sec, uint64_t nsec)
{
_syscall2(TIME_NANOSLEEP, (void*)sec, (void*)nsec);
}
+
+int clock_gettime(clockid_t clk_id, timespec_t* tp)
+{
+ if (unlikely(NULL == tp)) { return -EFAULT; }
+
+ int rc = 0;
+
+ switch(clk_id)
+ {
+ case CLOCK_REALTIME: // TODO: Need a message to the FSP to get the
+ // real-time.
+ rc = -EINVAL;
+ break;
+
+ case CLOCK_MONOTONIC:
+ TimeManager::convertTicksToSec(getTB(), tp->tv_sec, tp->tv_nsec);
+ break;
+
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
diff --git a/src/usr/testcore/lib/time.H b/src/usr/testcore/lib/time.H
new file mode 100644
index 000000000..895d2884e
--- /dev/null
+++ b/src/usr/testcore/lib/time.H
@@ -0,0 +1,70 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/testcore/lib/time.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+
+#ifndef __TESTCORE_LIB_TIME_H
+#define __TESTCORE_LIB_TIME_H
+
+#include <time.h>
+#include <sys/time.h>
+#include <errno.h>
+
+/** @file time.H
+ * @brief Test cases for the time / sleep sub-system.
+ */
+
+class TimeTest : public CxxTest::TestSuite
+{
+ public:
+ /**
+ * Tests for the clock_gettime POSIX function.
+ */
+ void testClockGetTime()
+ {
+ timespec_t first, second;
+
+ if (-EINVAL != clock_gettime(CLOCK_REALTIME, &first))
+ {
+ TS_FAIL("CLOCK_REALTIME not implemented, but no EINVAL");
+ }
+
+ if (0 != clock_gettime(CLOCK_MONOTONIC, &first))
+ {
+ TS_FAIL("Unable to read monotonic clock");
+ }
+
+ nanosleep(0,1);
+
+ if (0 != clock_gettime(CLOCK_MONOTONIC, &second))
+ {
+ TS_FAIL("Unable to read monotonic clock");
+ }
+
+ if ((second.tv_sec <= first.tv_sec) &&
+ (second.tv_nsec <= first.tv_nsec))
+ {
+ TS_FAIL("Monotonic clock is not increasing.");
+ }
+ }
+};
+
+#endif
OpenPOWER on IntegriCloud