The Pedigree Project  0.1
hosted/SchedulerTimer.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "SchedulerTimer.h"
21 #include "pedigree/kernel/Log.h"
22 #include "pedigree/kernel/compiler.h"
23 #include "pedigree/kernel/machine/Machine.h"
24 
25 using namespace __pedigree_hosted;
26 
28 #define ONE_SECOND 1000000000
29 #define HZ 10
30 
32 
33 bool HostedSchedulerTimer::registerHandler(TimerHandler *handler)
34 {
35  if (UNLIKELY(handler == 0 && m_Handler != 0))
36  return false;
37 
38  m_Handler = handler;
39  return true;
40 }
41 
43 {
44  struct sigevent sv;
45  ByteSet(&sv, 0, sizeof(sv));
46  sv.sigev_notify = SIGEV_SIGNAL;
47  sv.sigev_signo = SIGUSR2;
48  sv.sigev_value.sival_ptr = this;
49  int r = timer_create(CLOCK_REALTIME, &sv, &m_Timer);
50  if (r != 0)
51  {
53  return false;
54  }
55 
56  struct itimerspec interval;
57  ByteSet(&interval, 0, sizeof(interval));
58  interval.it_interval.tv_nsec = ONE_SECOND / HZ;
59  interval.it_value.tv_nsec = ONE_SECOND / HZ;
60  r = timer_settime(m_Timer, 0, &interval, 0);
61  if (r != 0)
62  {
63  timer_delete(m_Timer);
64  return false;
65  }
66 
67  IrqManager &irqManager = *Machine::instance().getIrqManager();
68  m_IrqId = irqManager.registerIsaIrqHandler(1, this);
69  if (m_IrqId == 0)
70  {
71  timer_delete(m_Timer);
72  return false;
73  }
74 
75  return true;
76 }
78 {
79  timer_delete(m_Timer);
80 
81  // Free the IRQ
82  if (m_IrqId != 0)
83  {
84  IrqManager &irqManager = *Machine::instance().getIrqManager();
85  irqManager.unregisterHandler(m_IrqId, this);
86  }
87 }
88 
89 HostedSchedulerTimer::HostedSchedulerTimer() : m_IrqId(0), m_Handler(0)
90 {
91 }
92 
93 bool HostedSchedulerTimer::irq(irq_id_t number, InterruptState &state)
94 {
95  // Should we handle this?
96  uint64_t opaque = state.getRegister(0);
97  if (opaque != reinterpret_cast<uint64_t>(this))
98  {
99  return false;
100  }
101 
102  // TODO: Delta is wrong
103  if (LIKELY(m_Handler != 0))
104  m_Handler->timer(ONE_SECOND / HZ, state);
105 
106  return true;
107 }
HostedSchedulerTimer() INITIALISATION_ONLY
static HostedSchedulerTimer m_Instance
virtual void unregisterHandler(irq_id_t Id, IrqHandler *handler)=0
virtual void timer(uint64_t delta, InterruptState &state)=0
virtual irq_id_t registerIsaIrqHandler(uint8_t irq, IrqHandler *handler, bool bEdge=false)=0
bool initialise() INITIALISATION_ONLY
virtual bool irq(irq_id_t number, InterruptState &state)