1 using System;
2 using System.Threading;
3
4 namespace cmsx.machine
5 {
6 public class ClockDriver
7 {
8 public ClockDriver(Clock& clock_) : clock(clock_)
9 {
10 clock.Start();
11 }
12 public ~ClockDriver()
13 {
14 clock.Stop();
15 }
16 private Clock& clock;
17 }
18
19 public class Clock
20 {
21 public const long tick = 50;
22
23 static Clock() : instance(new Clock())
24 {
25 }
26 public static Clock& Instance()
27 {
28 return *instance;
29 }
30 private Clock() : machine(GetMachine()), started(false), stopping(false)
31 {
32 }
33 public void Start()
34 {
35 ThreadStartMethod tickMethod = Tick;
36 thread = Thread.StartMethod(tickMethod);
37 started = true;
38 }
39 public void Stop()
40 {
41 if (!started) return;
42 stopping = true;
43 stop.NotifyOne();
44 thread.Join();
45 }
46 private void Tick()
47 {
48 try
49 {
50 while (!stopping)
51 {
52 ConditionVariableStatus status = stop.WaitFor(mtx, Duration.FromMilliseconds(tick));
53 if (status == ConditionVariableStatus.timeout)
54 {
55 machine.GetRegisters().SetInterrupt(CLOCK_BIT);
56 }
57 }
58 }
59 catch (const Exception& ex)
60 {
61 Console.Error() << "clock: " << ex.ToString() << endl();
62 }
63 }
64 private static UniquePtr<Clock> instance;
65 private Machine& machine;
66 private RecursiveMutex mtx;
67 private ConditionVariable stop;
68 private Thread thread;
69 private bool started;
70 private bool stopping;
71 }
72 }