The Pedigree Project  0.1
TimeoutGuard.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 
21 #include "pedigree/kernel/compiler.h"
22 #ifdef THREADS
23 #include "pedigree/kernel/process/Thread.h"
24 #endif
25 #include "pedigree/kernel/LockGuard.h"
26 #include "pedigree/kernel/Log.h"
27 #include "pedigree/kernel/machine/Machine.h"
28 #include "pedigree/kernel/machine/Timer.h"
29 #include "pedigree/kernel/processor/Processor.h"
30 #include "pedigree/kernel/processor/ProcessorInformation.h"
31 #include "pedigree/kernel/utilities/new"
32 
33 static void guardEventFired(uint8_t *pBuffer) NORETURN;
34 
35 TimeoutGuard::TimeoutGuard(size_t timeoutSecs)
36  : m_pEvent(0), m_bTimedOut(false),
37 #ifdef THREADS
38  m_State(),
39 #endif
40  m_nLevel(0), m_Lock()
41 {
42 #ifdef THREADS
43  if (timeoutSecs)
44  {
45  Thread *pThread = Processor::information().getCurrentThread();
46 
47  m_nLevel = pThread->getStateLevel();
48  m_pEvent = new TimeoutGuardEvent(this, m_nLevel);
49 
50  Machine::instance().getTimer()->addAlarm(m_pEvent, timeoutSecs);
51 
52  // Generate the SchedulerState to restore to.
54  }
55 #else
56  WARNING("TimeoutGuard: TimeoutGuard needs thread support");
57 #endif
58 }
59 
61 {
62 #ifdef THREADS
63  // Stop any interrupts - now we know that we can't be preempted by
64  // our own event handler.
66 
67  // If the event hasn't fired yet, remove and delete it.
68  if (m_pEvent)
69  {
70  Machine::instance().getTimer()->removeAlarm(m_pEvent);
71  // Ensure that the event isn't queued.
72  Processor::information().getCurrentThread()->cullEvent(m_pEvent);
73  delete m_pEvent;
74  m_pEvent = 0;
75  }
76 #endif
77 }
78 
80 {
81 #ifdef THREADS
82  // Called by TimeoutGuardEvent.
83  m_bTimedOut = true;
84 
85  m_pEvent = 0;
86 
88 #endif
89 }
90 
91 static void guardEventFired(uint8_t *pBuffer)
92 {
93 #ifdef THREADS
94  NOTICE("GuardEventFired");
96  if (!TimeoutGuard::TimeoutGuardEvent::unserialize(pBuffer, e))
97  {
98  FATAL("guardEventFired: Event is not a TimeoutGuardEvent!");
99  }
100  e.m_pTarget->cancel();
101  NOTICE("Cancel finished");
102 #endif
103 }
104 
105 TimeoutGuard::TimeoutGuardEvent::TimeoutGuardEvent(
106  TimeoutGuard *pTarget, size_t specificNestingLevel)
107  : Event(
108  reinterpret_cast<uintptr_t>(&guardEventFired), true /* Deletable */,
109  specificNestingLevel),
110  m_pTarget(pTarget)
111 {
112 }
113 
114 TimeoutGuard::TimeoutGuardEvent::~TimeoutGuardEvent()
115 {
116 }
117 
119 {
120  void *alignedBuffer = ASSUME_ALIGNMENT(pBuffer, sizeof(size_t));
121  size_t *pBufferSize_t = reinterpret_cast<size_t *>(alignedBuffer);
122  pBufferSize_t[0] = EventNumbers::TimeoutGuard;
123  pBufferSize_t[1] = reinterpret_cast<size_t>(m_pTarget);
124  return 2 * sizeof(size_t);
125 }
126 
127 bool TimeoutGuard::TimeoutGuardEvent::unserialize(
128  uint8_t *pBuffer, TimeoutGuardEvent &event)
129 {
130  void *alignedBuffer = ASSUME_ALIGNMENT(pBuffer, sizeof(size_t));
131  size_t *pBufferSize_t = reinterpret_cast<size_t *>(alignedBuffer);
132  if (pBufferSize_t[0] != EventNumbers::TimeoutGuard)
133  return false;
134  event.m_pTarget = reinterpret_cast<TimeoutGuard *>(pBufferSize_t[1]);
135  return true;
136 }
Spinlock m_Lock
Definition: TimeoutGuard.h:112
size_t m_nLevel
Definition: TimeoutGuard.h:109
virtual void removeAlarm(class Event *pEvent)=0
static void restoreState(SchedulerState &state, volatile uintptr_t *pLock=0) NORETURN
TimeoutGuardEvent * m_pEvent
Definition: TimeoutGuard.h:96
virtual Timer * getTimer()=0
void cancel() NORETURN
Definition: TimeoutGuard.cc:79
size_t getStateLevel() const
Definition: Thread.cc:474
SchedulerState m_State
Definition: TimeoutGuard.h:103
static ProcessorInformation & information()
Definition: Processor.cc:45
bool m_bTimedOut
Definition: TimeoutGuard.h:99
#define WARNING(text)
Definition: Log.h:78
#define NOTICE(text)
Definition: Log.h:74
static bool saveState(SchedulerState &state)
virtual size_t serialize(uint8_t *pBuffer)
Definition: Thread.h:54
Definition: Event.h:48
TimeoutGuard(size_t timeoutSecs)
Definition: TimeoutGuard.cc:35
#define FATAL(text)
Definition: Log.h:89
virtual void addAlarm(class Event *pEvent, size_t alarmSecs, size_t alarmUsecs=0)=0
Implements the class TimeoutGuard, which cancels any operation after a given amount of time...