summaryrefslogtreecommitdiffstats
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/syscall.C14
-rw-r--r--src/kernel/timemgr.C51
2 files changed, 62 insertions, 3 deletions
diff --git a/src/kernel/syscall.C b/src/kernel/syscall.C
index 3a6f128ed..d9ac13b17 100644
--- a/src/kernel/syscall.C
+++ b/src/kernel/syscall.C
@@ -8,11 +8,13 @@
#include <kernel/pagemgr.H>
#include <kernel/usermutex.H>
#include <kernel/msg.H>
+#include <kernel/timemgr.H>
extern "C"
void kernel_execute_decrementer()
{
Scheduler* s = CpuManager::getCurrentCPU()->scheduler;
+ TimeManager::checkReleaseTasks(s);
s->returnRunnable();
s->setNextRunnable();
}
@@ -38,6 +40,7 @@ namespace Systemcalls
void MsgWait(task_t*);
void MmioMap(task_t*);
void MmioUnmap(task_t*);
+ void TimeNanosleep(task_t*);
syscall syscalls[] =
{
@@ -63,6 +66,8 @@ namespace Systemcalls
&MmioMap,
&MmioUnmap,
+
+ &TimeNanosleep,
};
};
@@ -339,5 +344,14 @@ namespace Systemcalls
TASK_SETRTN(t, VmmManager::mmioUnmap(ea,pages));
}
+ void TimeNanosleep(task_t* t)
+ {
+ TimeManager::delayTask(t, TASK_GETARG0(t), TASK_GETARG1(t));
+ TASK_SETRTN(t, 0);
+
+ Scheduler* s = t->cpu->scheduler;
+ s->setNextRunnable();
+ }
+
};
diff --git a/src/kernel/timemgr.C b/src/kernel/timemgr.C
index 73a920524..3871e1ceb 100644
--- a/src/kernel/timemgr.C
+++ b/src/kernel/timemgr.C
@@ -1,7 +1,8 @@
#include <kernel/timemgr.H>
+#include <kernel/scheduler.H>
#include <util/singleton.H>
-uint64_t TimeManager::iv_timeSlice = 0xFFFFFFFF;
+uint64_t TimeManager::iv_timebaseFreq = 0xFFFFFFFF;
void TimeManager::init()
{
@@ -10,6 +11,50 @@ void TimeManager::init()
void TimeManager::_init()
{
- /* TB freq / Timeslice per Sec */
- iv_timeSlice = 512000000 / 1000;
+ iv_timebaseFreq = 512000000ULL;
+}
+
+uint64_t TimeManager::convertSecToTicks(uint64_t i_sec, uint64_t i_nsec)
+{
+ // This code will handle times almost up to a year without overflowing a
+ // uint64. This should be more than sufficient for our purposes.
+
+ // Result = ((sec * 10^9 + nsec) * tb) / 10^9.
+ uint64_t result = ((i_sec * 1000000000ULL) + i_nsec);
+ result *= (iv_timebaseFreq / 1000000);
+ result /= 1000;
+ return result;
+}
+
+void TimeManager::delayTask(task_t* t, uint64_t i_sec, uint64_t i_nsec)
+{
+ Singleton<TimeManager>::instance()._delayTask(t,i_sec,i_nsec);
+}
+
+void TimeManager::_delayTask(task_t* t, uint64_t i_sec, uint64_t i_nsec)
+{
+ _TimeManager_Delay_t* node = new _TimeManager_Delay_t();
+
+ node->key = this->getCurrentTimeBase() +
+ this->convertSecToTicks(i_sec, i_nsec);
+ node->task = t;
+
+ iv_taskList.insert(node);
+}
+
+void TimeManager::checkReleaseTasks(Scheduler* s)
+{
+ Singleton<TimeManager>::instance()._checkReleaseTasks(s);
+}
+
+void TimeManager::_checkReleaseTasks(Scheduler* s)
+{
+ uint64_t l_currentTime = getCurrentTimeBase();
+ _TimeManager_Delay_t* node = NULL;
+
+ while(NULL != (node = iv_taskList.remove_if(l_currentTime)))
+ {
+ s->addTask(node->task);
+ delete node;
+ }
}
OpenPOWER on IntegriCloud