Committer:
segundo
Date:
Thu Nov 11 10:30:39 2010 +0000
Revision:
7:6fab7e5aa489
Parent:
0:d7810ff946c1

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
segundo 0:d7810ff946c1 1 //******************************************************************************
segundo 0:d7810ff946c1 2 //*
segundo 0:d7810ff946c1 3 //* FULLNAME: Single-Chip Microcontroller Real-Time Operating System
segundo 0:d7810ff946c1 4 //*
segundo 0:d7810ff946c1 5 //* NICKNAME: scmRTOS
segundo 0:d7810ff946c1 6 //*
segundo 0:d7810ff946c1 7 //* PURPOSE: OS Services Source
segundo 0:d7810ff946c1 8 //*
segundo 0:d7810ff946c1 9 //* Version: 3.10
segundo 0:d7810ff946c1 10 //*
segundo 0:d7810ff946c1 11 //* $Revision: 256 $
segundo 0:d7810ff946c1 12 //* $Date:: 2010-01-22 #$
segundo 0:d7810ff946c1 13 //*
segundo 0:d7810ff946c1 14 //* Copyright (c) 2003-2010, Harry E. Zhurov
segundo 0:d7810ff946c1 15 //*
segundo 0:d7810ff946c1 16 //* Permission is hereby granted, free of charge, to any person
segundo 0:d7810ff946c1 17 //* obtaining a copy of this software and associated documentation
segundo 0:d7810ff946c1 18 //* files (the "Software"), to deal in the Software without restriction,
segundo 0:d7810ff946c1 19 //* including without limitation the rights to use, copy, modify, merge,
segundo 0:d7810ff946c1 20 //* publish, distribute, sublicense, and/or sell copies of the Software,
segundo 0:d7810ff946c1 21 //* and to permit persons to whom the Software is furnished to do so,
segundo 0:d7810ff946c1 22 //* subject to the following conditions:
segundo 0:d7810ff946c1 23 //*
segundo 0:d7810ff946c1 24 //* The above copyright notice and this permission notice shall be included
segundo 0:d7810ff946c1 25 //* in all copies or substantial portions of the Software.
segundo 0:d7810ff946c1 26 //*
segundo 0:d7810ff946c1 27 //* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
segundo 0:d7810ff946c1 28 //* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
segundo 0:d7810ff946c1 29 //* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
segundo 0:d7810ff946c1 30 //* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
segundo 0:d7810ff946c1 31 //* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
segundo 0:d7810ff946c1 32 //* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
segundo 0:d7810ff946c1 33 //* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
segundo 0:d7810ff946c1 34 //*
segundo 0:d7810ff946c1 35 //* =================================================================
segundo 0:d7810ff946c1 36 //* See http://scmrtos.sourceforge.net for documentation, latest
segundo 0:d7810ff946c1 37 //* information, license and contact details.
segundo 0:d7810ff946c1 38 //* =================================================================
segundo 0:d7810ff946c1 39 //*
segundo 0:d7810ff946c1 40 //******************************************************************************
segundo 0:d7810ff946c1 41
segundo 0:d7810ff946c1 42 #include "scmRTOS.h"
segundo 0:d7810ff946c1 43
segundo 0:d7810ff946c1 44 using namespace OS;
segundo 0:d7810ff946c1 45
segundo 0:d7810ff946c1 46 //------------------------------------------------------------------------------
segundo 0:d7810ff946c1 47 //
segundo 0:d7810ff946c1 48 //
segundo 0:d7810ff946c1 49 // TEventFlag
segundo 0:d7810ff946c1 50 //
segundo 0:d7810ff946c1 51 //
segundo 0:d7810ff946c1 52 bool OS::TEventFlag::Wait(TTimeout timeout)
segundo 0:d7810ff946c1 53 {
segundo 0:d7810ff946c1 54 TCritSect cs;
segundo 0:d7810ff946c1 55
segundo 0:d7810ff946c1 56 if(Value) // if flag already signaled
segundo 0:d7810ff946c1 57 {
segundo 0:d7810ff946c1 58 Value = efOff; // clear flag
segundo 0:d7810ff946c1 59 return true;
segundo 0:d7810ff946c1 60 }
segundo 0:d7810ff946c1 61 else
segundo 0:d7810ff946c1 62 {
segundo 0:d7810ff946c1 63 TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority];
segundo 0:d7810ff946c1 64 p->Timeout = timeout;
segundo 0:d7810ff946c1 65 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
segundo 0:d7810ff946c1 66
segundo 0:d7810ff946c1 67 SetPrioTag(ProcessMap, PrioTag); // put current process to the wait map
segundo 0:d7810ff946c1 68 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
segundo 0:d7810ff946c1 69
segundo 0:d7810ff946c1 70 Kernel.Scheduler();
segundo 0:d7810ff946c1 71
segundo 0:d7810ff946c1 72 p->Timeout = 0;
segundo 0:d7810ff946c1 73
segundo 0:d7810ff946c1 74 if( !(ProcessMap & PrioTag) ) // if waked up by signal() or signal_ISR()
segundo 0:d7810ff946c1 75 return true;
segundo 0:d7810ff946c1 76
segundo 0:d7810ff946c1 77 ClrPrioTag(ProcessMap, PrioTag); // otherwise waked up by timeout or by
segundo 0:d7810ff946c1 78 return false; // OS::ForceWakeUpProcess(), remove process from the wait map
segundo 0:d7810ff946c1 79 }
segundo 0:d7810ff946c1 80 }
segundo 0:d7810ff946c1 81 //------------------------------------------------------------------------------
segundo 0:d7810ff946c1 82 void OS::TEventFlag::Signal()
segundo 0:d7810ff946c1 83 {
segundo 0:d7810ff946c1 84 TCritSect cs;
segundo 0:d7810ff946c1 85 if(ProcessMap) // if any process waits for event
segundo 0:d7810ff946c1 86 {
segundo 0:d7810ff946c1 87 TProcessMap Timeouted = Kernel.ReadyProcessMap; // Process has its tag set in ReadyProcessMap if timeout expired
segundo 0:d7810ff946c1 88 // or it was waked up by OS::ForceWakeUpProcess()
segundo 0:d7810ff946c1 89
segundo 0:d7810ff946c1 90 if( ProcessMap & ~Timeouted ) // if any process has to be waked up
segundo 0:d7810ff946c1 91 {
segundo 0:d7810ff946c1 92 SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map
segundo 0:d7810ff946c1 93 ClrPrioTag(ProcessMap, ~Timeouted); // remove all non-timeouted processes from the waiting map.
segundo 0:d7810ff946c1 94 // Used to check that process waked up by signal() or signalISR()
segundo 0:d7810ff946c1 95 // and not by timeout or OS::ForceWakeUpProcess()
segundo 0:d7810ff946c1 96 Kernel.Scheduler();
segundo 0:d7810ff946c1 97 return;
segundo 0:d7810ff946c1 98 }
segundo 0:d7810ff946c1 99 }
segundo 0:d7810ff946c1 100 Value = efOn;
segundo 0:d7810ff946c1 101 }
segundo 0:d7810ff946c1 102 //------------------------------------------------------------------------------
segundo 0:d7810ff946c1 103
segundo 0:d7810ff946c1 104 //------------------------------------------------------------------------------
segundo 0:d7810ff946c1 105 //
segundo 0:d7810ff946c1 106 //
segundo 0:d7810ff946c1 107 // TMutex
segundo 0:d7810ff946c1 108 //
segundo 0:d7810ff946c1 109 //
segundo 0:d7810ff946c1 110 void OS::TMutex::Lock()
segundo 0:d7810ff946c1 111 {
segundo 0:d7810ff946c1 112 TCritSect cs;
segundo 0:d7810ff946c1 113
segundo 0:d7810ff946c1 114 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
segundo 0:d7810ff946c1 115 while(ValueTag)
segundo 0:d7810ff946c1 116 {
segundo 0:d7810ff946c1 117 SetPrioTag(ProcessMap, PrioTag); // mutex already locked by another process, put current process to the wait map
segundo 0:d7810ff946c1 118 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
segundo 0:d7810ff946c1 119
segundo 0:d7810ff946c1 120 Kernel.Scheduler();
segundo 0:d7810ff946c1 121 }
segundo 0:d7810ff946c1 122 ValueTag = PrioTag; // mutex has been successfully locked
segundo 0:d7810ff946c1 123 }
segundo 0:d7810ff946c1 124 //------------------------------------------------------------------------------
segundo 0:d7810ff946c1 125 void OS::TMutex::Unlock()
segundo 0:d7810ff946c1 126 {
segundo 0:d7810ff946c1 127 TCritSect cs;
segundo 0:d7810ff946c1 128
segundo 0:d7810ff946c1 129 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
segundo 0:d7810ff946c1 130 if(ValueTag != PrioTag) return; // the only process that had locked mutex can unlock the mutex
segundo 0:d7810ff946c1 131 ValueTag = 0;
segundo 0:d7810ff946c1 132 if(ProcessMap)
segundo 0:d7810ff946c1 133 {
segundo 0:d7810ff946c1 134 byte pr = GetHighPriority(ProcessMap);
segundo 0:d7810ff946c1 135 PrioTag = GetPrioTag(pr);
segundo 0:d7810ff946c1 136 ClrPrioTag(ProcessMap, PrioTag); // remove next ready process from the wait map
segundo 0:d7810ff946c1 137 SetPrioTag(Kernel.ReadyProcessMap, PrioTag); // place next process to the ready map
segundo 0:d7810ff946c1 138 Kernel.Scheduler();
segundo 0:d7810ff946c1 139 }
segundo 0:d7810ff946c1 140 }
segundo 0:d7810ff946c1 141 //------------------------------------------------------------------------------
segundo 0:d7810ff946c1 142 void OS::TMutex::UnlockISR()
segundo 0:d7810ff946c1 143 {
segundo 0:d7810ff946c1 144 TCritSect cs;
segundo 0:d7810ff946c1 145
segundo 0:d7810ff946c1 146 ValueTag = 0;
segundo 0:d7810ff946c1 147 if(ProcessMap)
segundo 0:d7810ff946c1 148 {
segundo 0:d7810ff946c1 149 byte pr = GetHighPriority(ProcessMap);
segundo 0:d7810ff946c1 150 TProcessMap PrioTag = GetPrioTag(pr);
segundo 0:d7810ff946c1 151 ClrPrioTag(ProcessMap, PrioTag); // remove next ready process from the wait map
segundo 0:d7810ff946c1 152 SetPrioTag(Kernel.ReadyProcessMap, PrioTag); // place next process to the ready map
segundo 0:d7810ff946c1 153 }
segundo 0:d7810ff946c1 154 }
segundo 0:d7810ff946c1 155 //------------------------------------------------------------------------------
segundo 0:d7810ff946c1 156
segundo 0:d7810ff946c1 157
segundo 0:d7810ff946c1 158 //------------------------------------------------------------------------------
segundo 0:d7810ff946c1 159 //
segundo 0:d7810ff946c1 160 //
segundo 0:d7810ff946c1 161 // TChannel
segundo 0:d7810ff946c1 162 //
segundo 0:d7810ff946c1 163 //
segundo 0:d7810ff946c1 164 void OS::TChannel::CheckWaiters(TProcessMap& pm)
segundo 0:d7810ff946c1 165 {
segundo 0:d7810ff946c1 166 if(pm)
segundo 0:d7810ff946c1 167 {
segundo 0:d7810ff946c1 168 byte pr = GetHighPriority(pm);
segundo 0:d7810ff946c1 169 TProcessMap PrioTag = GetPrioTag(pr);
segundo 0:d7810ff946c1 170 ClrPrioTag(pm, PrioTag); // remove next ready process from the wait map
segundo 0:d7810ff946c1 171 SetPrioTag(Kernel.ReadyProcessMap, PrioTag); // place next process to the ready map
segundo 0:d7810ff946c1 172 Kernel.Scheduler();
segundo 0:d7810ff946c1 173 }
segundo 0:d7810ff946c1 174 }
segundo 0:d7810ff946c1 175 //------------------------------------------------------------------------------
segundo 0:d7810ff946c1 176 void OS::TChannel::Push(byte x)
segundo 0:d7810ff946c1 177 {
segundo 0:d7810ff946c1 178 TCritSect cs;
segundo 0:d7810ff946c1 179
segundo 0:d7810ff946c1 180 while (!Cbuf.get_free_size())
segundo 0:d7810ff946c1 181 {
segundo 0:d7810ff946c1 182 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
segundo 0:d7810ff946c1 183 SetPrioTag (ProducersProcessMap, PrioTag); // channel is full, put current process to the wait map
segundo 0:d7810ff946c1 184 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
segundo 0:d7810ff946c1 185 Kernel.Scheduler(); // wait until waked-up by Pop() or Read()
segundo 0:d7810ff946c1 186 }
segundo 0:d7810ff946c1 187
segundo 0:d7810ff946c1 188 Cbuf.put(x);
segundo 0:d7810ff946c1 189 CheckWaiters(ConsumersProcessMap);
segundo 0:d7810ff946c1 190 }
segundo 0:d7810ff946c1 191 //------------------------------------------------------------------------------
segundo 0:d7810ff946c1 192 byte OS::TChannel::Pop()
segundo 0:d7810ff946c1 193 {
segundo 0:d7810ff946c1 194 TCritSect cs;
segundo 0:d7810ff946c1 195 byte x;
segundo 0:d7810ff946c1 196
segundo 0:d7810ff946c1 197 while(!Cbuf.get_count())
segundo 0:d7810ff946c1 198 {
segundo 0:d7810ff946c1 199 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
segundo 0:d7810ff946c1 200 SetPrioTag(ConsumersProcessMap, PrioTag); // channel is empty, put current process to the wait map
segundo 0:d7810ff946c1 201 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
segundo 0:d7810ff946c1 202 Kernel.Scheduler(); // wait until waked up by Push() or Write()
segundo 0:d7810ff946c1 203 }
segundo 0:d7810ff946c1 204 x = Cbuf.get();
segundo 0:d7810ff946c1 205 CheckWaiters(ProducersProcessMap);
segundo 0:d7810ff946c1 206 return x;
segundo 0:d7810ff946c1 207 }
segundo 0:d7810ff946c1 208 //------------------------------------------------------------------------------
segundo 0:d7810ff946c1 209 void OS::TChannel::Write(const byte* data, const byte count)
segundo 0:d7810ff946c1 210 {
segundo 0:d7810ff946c1 211 TCritSect cs;
segundo 0:d7810ff946c1 212
segundo 0:d7810ff946c1 213 while(Cbuf.get_free_size() < count)
segundo 0:d7810ff946c1 214 {
segundo 0:d7810ff946c1 215 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
segundo 0:d7810ff946c1 216 SetPrioTag(ProducersProcessMap, PrioTag); // channel has not enough space, put current process to the wait map
segundo 0:d7810ff946c1 217 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
segundo 0:d7810ff946c1 218 Kernel.Scheduler(); // wait until waked up by Read() or Pop()
segundo 0:d7810ff946c1 219 }
segundo 0:d7810ff946c1 220
segundo 0:d7810ff946c1 221 Cbuf.write(data, count);
segundo 0:d7810ff946c1 222 CheckWaiters(ConsumersProcessMap);
segundo 0:d7810ff946c1 223 }
segundo 0:d7810ff946c1 224 //------------------------------------------------------------------------------
segundo 0:d7810ff946c1 225 void OS::TChannel::Read(byte* const data, const byte count)
segundo 0:d7810ff946c1 226 {
segundo 0:d7810ff946c1 227 TCritSect cs;
segundo 0:d7810ff946c1 228
segundo 0:d7810ff946c1 229 while(Cbuf.get_count() < count)
segundo 0:d7810ff946c1 230 {
segundo 0:d7810ff946c1 231 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
segundo 0:d7810ff946c1 232 SetPrioTag(ConsumersProcessMap, PrioTag); // channel doesn't contain enough data, put current process to the wait map
segundo 0:d7810ff946c1 233 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
segundo 0:d7810ff946c1 234 Kernel.Scheduler(); // wait until waked up by Write() or Push()
segundo 0:d7810ff946c1 235 }
segundo 0:d7810ff946c1 236
segundo 0:d7810ff946c1 237 Cbuf.read(data, count);
segundo 0:d7810ff946c1 238 CheckWaiters(ProducersProcessMap);
segundo 0:d7810ff946c1 239 }
segundo 0:d7810ff946c1 240 //------------------------------------------------------------------------------
segundo 0:d7810ff946c1 241
segundo 0:d7810ff946c1 242 //------------------------------------------------------------------------------
segundo 0:d7810ff946c1 243 //
segundo 0:d7810ff946c1 244 // OS::message template
segundo 0:d7810ff946c1 245 //
segundo 0:d7810ff946c1 246 // Function-members implementation
segundo 0:d7810ff946c1 247 //
segundo 0:d7810ff946c1 248 //
segundo 0:d7810ff946c1 249 //------------------------------------------------------------------------------
segundo 0:d7810ff946c1 250 bool OS::TBaseMessage::wait(TTimeout timeout)
segundo 0:d7810ff946c1 251 {
segundo 0:d7810ff946c1 252 TCritSect cs;
segundo 0:d7810ff946c1 253
segundo 0:d7810ff946c1 254 if(NonEmpty) // message alredy send
segundo 0:d7810ff946c1 255 {
segundo 0:d7810ff946c1 256 NonEmpty = false;
segundo 0:d7810ff946c1 257 return true;
segundo 0:d7810ff946c1 258 }
segundo 0:d7810ff946c1 259 else
segundo 0:d7810ff946c1 260 {
segundo 0:d7810ff946c1 261 TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority];
segundo 0:d7810ff946c1 262 p->Timeout = timeout;
segundo 0:d7810ff946c1 263 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
segundo 0:d7810ff946c1 264
segundo 0:d7810ff946c1 265 SetPrioTag(ProcessMap, PrioTag); // put current process to the wait map
segundo 0:d7810ff946c1 266 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
segundo 0:d7810ff946c1 267 Kernel.Scheduler(); // wait until wake up
segundo 0:d7810ff946c1 268
segundo 0:d7810ff946c1 269 p->Timeout = 0;
segundo 0:d7810ff946c1 270 if( !(ProcessMap & PrioTag) ) // if waked up by send() or sendISR()
segundo 0:d7810ff946c1 271 return true;
segundo 0:d7810ff946c1 272
segundo 0:d7810ff946c1 273 ClrPrioTag(ProcessMap, PrioTag); // otherwise waked up by timeout or by
segundo 0:d7810ff946c1 274 return false; // OS::ForceWakeUpProcess(), remove process from wait map
segundo 0:d7810ff946c1 275 }
segundo 0:d7810ff946c1 276 }
segundo 0:d7810ff946c1 277 //------------------------------------------------------------------------------
segundo 0:d7810ff946c1 278 void OS::TBaseMessage::send()
segundo 0:d7810ff946c1 279 {
segundo 0:d7810ff946c1 280 TCritSect cs;
segundo 0:d7810ff946c1 281
segundo 0:d7810ff946c1 282 if(ProcessMap)
segundo 0:d7810ff946c1 283 {
segundo 0:d7810ff946c1 284 TProcessMap Timeouted = Kernel.ReadyProcessMap; // Process has its tag set in ReadyProcessMap if timeout expired,
segundo 0:d7810ff946c1 285 // or it was waked up by OS::ForceWakeUpProcess()
segundo 0:d7810ff946c1 286 if( ProcessMap & ~Timeouted ) // if any process has to be waked up
segundo 0:d7810ff946c1 287 {
segundo 0:d7810ff946c1 288 SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map
segundo 0:d7810ff946c1 289 ClrPrioTag(ProcessMap, ~Timeouted); // remove all non-timeouted processes from the waiting map.
segundo 0:d7810ff946c1 290 Kernel.Scheduler();
segundo 0:d7810ff946c1 291 return;
segundo 0:d7810ff946c1 292 }
segundo 0:d7810ff946c1 293 }
segundo 0:d7810ff946c1 294
segundo 0:d7810ff946c1 295 NonEmpty = true;
segundo 0:d7810ff946c1 296 }
segundo 0:d7810ff946c1 297 //------------------------------------------------------------------------------
segundo 0:d7810ff946c1 298