Daniel Peter
/
RtosTest
Embed:
(wiki syntax)
Show/hide line numbers
OS_Services.h
00001 //****************************************************************************** 00002 //* 00003 //* FULLNAME: Single-Chip Microcontroller Real-Time Operating System 00004 //* 00005 //* NICKNAME: scmRTOS 00006 //* 00007 //* PURPOSE: OS Services Header. Declarations And Definitions 00008 //* 00009 //* Version: 3.10 00010 //* 00011 //* $Revision: 256 $ 00012 //* $Date:: 2010-01-22 #$ 00013 //* 00014 //* Copyright (c) 2003-2010, Harry E. Zhurov 00015 //* 00016 //* Permission is hereby granted, free of charge, to any person 00017 //* obtaining a copy of this software and associated documentation 00018 //* files (the "Software"), to deal in the Software without restriction, 00019 //* including without limitation the rights to use, copy, modify, merge, 00020 //* publish, distribute, sublicense, and/or sell copies of the Software, 00021 //* and to permit persons to whom the Software is furnished to do so, 00022 //* subject to the following conditions: 00023 //* 00024 //* The above copyright notice and this permission notice shall be included 00025 //* in all copies or substantial portions of the Software. 00026 //* 00027 //* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00028 //* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00029 //* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 00030 //* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 00031 //* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 00032 //* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 00033 //* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00034 //* 00035 //* ================================================================= 00036 //* See http://scmrtos.sourceforge.net for documentation, latest 00037 //* information, license and contact details. 00038 //* ================================================================= 00039 //* 00040 //****************************************************************************** 00041 00042 #ifndef OS_SERVICES_H 00043 #define OS_SERVICES_H 00044 00045 namespace OS 00046 { 00047 //-------------------------------------------------------------------------- 00048 // 00049 // NAME : Mutex 00050 // 00051 /// Binary semaphore for support of mutual exclusion 00052 // 00053 // DESCRIPTION: 00054 // 00055 // 00056 class TMutex 00057 { 00058 public: 00059 INLINE TMutex() : ProcessMap(0), ValueTag(0) { } 00060 void Lock(); 00061 void Unlock(); 00062 void UnlockISR(); 00063 00064 INLINE bool LockSoftly() { TCritSect cs; if(ValueTag) return false; else Lock(); return true; } 00065 INLINE bool IsLocked() const { TCritSect cs; if(ValueTag) return true; else return false; } 00066 00067 private: 00068 TProcessMap ProcessMap; 00069 TProcessMap ValueTag; 00070 00071 }; 00072 //-------------------------------------------------------------------------- 00073 00074 //-------------------------------------------------------------------------- 00075 // 00076 /// Event Flag 00077 /// 00078 /// Intended for processes synchronization and 00079 /// event notification one (or more) process by another 00080 // 00081 // DESCRIPTION: 00082 // 00083 // 00084 class TEventFlag 00085 { 00086 public: 00087 enum TValue { efOn = 1, efOff= 0 }; // prefix 'ef' means: "Event Flag" 00088 00089 public: 00090 INLINE TEventFlag(TValue init_val = efOff) : ProcessMap(0), Value(init_val) { } 00091 00092 bool Wait(TTimeout timeout = 0); 00093 void Signal(); 00094 INLINE void Clear() { TCritSect cs; Value = efOff; } 00095 INLINE inline void SignalISR(); 00096 INLINE bool IsSignaled() { TCritSect cs; if(Value == efOn) return true; else return false; } 00097 00098 private: 00099 TProcessMap ProcessMap; 00100 TValue Value; 00101 }; 00102 //-------------------------------------------------------------------------- 00103 00104 //-------------------------------------------------------------------------- 00105 // 00106 /// TChannel 00107 /// 00108 /// Byte-wide data channel for transferring "raw" data 00109 // 00110 // DESCRIPTION: 00111 // 00112 // 00113 class TChannel 00114 { 00115 public: 00116 INLINE TChannel(byte* buf, byte size) : Cbuf(buf, size) { } 00117 void Push(byte x); 00118 byte Pop(); 00119 void Write(const byte* data, const byte count); 00120 void Read(byte* const data, const byte count); 00121 00122 INLINE byte GetCount() const { TCritSect cs; return Cbuf.get_count(); } 00123 00124 private: 00125 TProcessMap ProducersProcessMap; 00126 TProcessMap ConsumersProcessMap; 00127 usr::TCbuf Cbuf; 00128 00129 private: 00130 void CheckWaiters(TProcessMap& pm); 00131 }; 00132 //-------------------------------------------------------------------------- 00133 00134 00135 //-------------------------------------------------------------------------- 00136 // 00137 // NAME : channel 00138 // 00139 // PURPOSE : Data channel for transferring data 00140 // objects of arbitrary type 00141 // 00142 // DESCRIPTION: 00143 // 00144 // 00145 template<typename T, word Size, typename S = byte> 00146 /// channel 00147 /// 00148 /// Data channel for transferring data objects of arbitrary type 00149 class channel 00150 { 00151 public: 00152 INLINE channel() : ProducersProcessMap(0) 00153 , ConsumersProcessMap(0) 00154 , pool() 00155 { 00156 } 00157 00158 //---------------------------------------------------------------- 00159 // 00160 // Data transfer functions 00161 // 00162 void write(const T* data, const S cnt); 00163 bool read (T* const data, const S cnt, TTimeout timeout = 0); 00164 00165 void push (const T& item); 00166 void push_front(const T& item); 00167 00168 bool pop (T& item, TTimeout timeout = 0); 00169 bool pop_back(T& item, TTimeout timeout = 0); 00170 00171 00172 //---------------------------------------------------------------- 00173 // 00174 // Service functions 00175 // 00176 INLINE S get_count() const { TCritSect cs; return pool.get_count(); } 00177 INLINE S get_free_size() const { TCritSect cs; return pool.get_free_size(); } 00178 void flush(); 00179 //const T& operator[](const S index) { TCritSect cs; return pool[index]; } 00180 00181 00182 private: 00183 TProcessMap ProducersProcessMap; 00184 TProcessMap ConsumersProcessMap; 00185 usr::ring_buffer<T, Size, S> pool; 00186 00187 private: 00188 void CheckWaiters(TProcessMap& pm); 00189 }; 00190 00191 //-------------------------------------------------------------------------- 00192 00193 //-------------------------------------------------------------------------- 00194 // 00195 /// message 00196 /// 00197 /// Template for messages 00198 // 00199 // DESCRIPTION: 00200 // 00201 // 00202 class TBaseMessage 00203 { 00204 public: 00205 INLINE TBaseMessage() : ProcessMap(0), NonEmpty(false) { } 00206 00207 bool wait (TTimeout timeout = 0); 00208 void send(); 00209 INLINE inline void sendISR(); 00210 INLINE bool is_non_empty() const { TCritSect cs; return NonEmpty; } 00211 INLINE void reset () { TCritSect cs; NonEmpty = false; } 00212 00213 private: 00214 TProcessMap ProcessMap; 00215 bool NonEmpty; 00216 }; 00217 //-------------------------------------------------------------------------- 00218 template<typename T> 00219 class message : public TBaseMessage 00220 { 00221 public: 00222 INLINE message() : TBaseMessage() { } 00223 INLINE const T& operator=(const T& msg) { TCritSect cs; Msg = msg; return Msg; } 00224 INLINE operator T() const { TCritSect cs; return Msg; } 00225 00226 private: 00227 T Msg; 00228 }; 00229 //-------------------------------------------------------------------------- 00230 } 00231 //------------------------------------------------------------------------------ 00232 // 00233 // Function-members implementation 00234 // 00235 //------------------------------------------------------------------------------ 00236 void OS::TEventFlag::SignalISR() 00237 { 00238 TCritSect cs; 00239 if(ProcessMap) // if any process waits for event 00240 { 00241 TProcessMap Timeouted = Kernel.ReadyProcessMap; // Process has its tag set in ReadyProcessMap if timeout 00242 // expired, or it was waked up by OS::ForceWakeUpProcess() 00243 if( ProcessMap & ~Timeouted ) // if any process has to be waked up 00244 { 00245 SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map 00246 ClrPrioTag(ProcessMap, ~Timeouted); // remove all non-timeouted processes from the waiting map. 00247 return; 00248 } 00249 } 00250 Value = efOn; 00251 } 00252 //------------------------------------------------------------------------------ 00253 template<typename T, word Size, typename S> 00254 void OS::channel<T, Size, S>::CheckWaiters(TProcessMap& pm) 00255 { 00256 if(pm) 00257 { 00258 TProcessMap Timeouted = Kernel.ReadyProcessMap; 00259 00260 SetPrioTag(Kernel.ReadyProcessMap, pm); // place all waiting processes to the ready map 00261 ClrPrioTag(pm, ~Timeouted); // remove waiting processes from the wait map 00262 Kernel.Scheduler(); 00263 } 00264 } 00265 //------------------------------------------------------------------------------ 00266 template<typename T, word Size, typename S> 00267 void OS::channel<T, Size, S>::push(const T& item) 00268 { 00269 TCritSect cs; 00270 00271 while(!pool.get_free_size()) 00272 { 00273 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); 00274 SetPrioTag(ProducersProcessMap, PrioTag); // channel is full, put current process to the wait map 00275 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map 00276 Kernel.Scheduler(); 00277 } 00278 00279 pool.push_back(item); 00280 CheckWaiters(ConsumersProcessMap); 00281 } 00282 //------------------------------------------------------------------------------ 00283 template<typename T, word Size, typename S> 00284 void OS::channel<T, Size, S>::push_front(const T& item) 00285 { 00286 TCritSect cs; 00287 00288 while(!pool.get_free_size()) 00289 { 00290 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); 00291 SetPrioTag(ProducersProcessMap, PrioTag); // channel is full, put current process to the wait map 00292 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map 00293 Kernel.Scheduler(); 00294 } 00295 00296 pool.push_front(item); 00297 CheckWaiters(ConsumersProcessMap); 00298 } 00299 //------------------------------------------------------------------------------ 00300 template<typename T, word Size, typename S> 00301 bool OS::channel<T, Size, S>::pop(T& item, TTimeout timeout) 00302 { 00303 TCritSect cs; 00304 00305 if(pool.get_count()) 00306 { 00307 item = pool.pop(); 00308 CheckWaiters(ProducersProcessMap); 00309 return true; 00310 } 00311 else 00312 { 00313 TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority]; 00314 p->Timeout = timeout; 00315 00316 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); 00317 for(;;) 00318 { 00319 SetPrioTag(ConsumersProcessMap, PrioTag); // channel is empty, put current process to the wait map 00320 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map 00321 Kernel.Scheduler(); 00322 00323 if(pool.get_count()) 00324 { 00325 p->Timeout = 0; 00326 item = pool.pop(); 00327 CheckWaiters(ProducersProcessMap); 00328 return true; 00329 } 00330 00331 if(ConsumersProcessMap & PrioTag) // waked up by timer when timeout expired 00332 { // or by OS::ForceWakeUpProcess() 00333 00334 p->Timeout = 0; // non-zero if waked up by ForceWakeUpProcess() 00335 ClrPrioTag(ConsumersProcessMap, PrioTag); // remove current process from the wait map 00336 return false; 00337 } 00338 } 00339 } 00340 } 00341 //------------------------------------------------------------------------------ 00342 template<typename T, word Size, typename S> 00343 bool OS::channel<T, Size, S>::pop_back(T& item, TTimeout timeout) 00344 { 00345 TCritSect cs; 00346 00347 if(pool.get_count()) 00348 { 00349 item = pool.pop_back(); 00350 CheckWaiters(ProducersProcessMap); 00351 return true; 00352 } 00353 else 00354 { 00355 TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority]; 00356 p->Timeout = timeout; 00357 00358 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); 00359 for(;;) 00360 { 00361 SetPrioTag(ConsumersProcessMap, PrioTag); // channel is empty, put current process to the wait map 00362 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map 00363 Kernel.Scheduler(); 00364 00365 if(pool.get_count()) 00366 { 00367 p->Timeout = 0; 00368 item = pool.pop_back(); 00369 CheckWaiters(ProducersProcessMap); 00370 return true; 00371 } 00372 00373 if(ConsumersProcessMap & PrioTag) // waked up by timer when timeout expired 00374 { // or by OS::ForceWakeUpProcess() 00375 00376 p->Timeout = 0; // non-zero if waked up by ForceWakeUpProcess() 00377 ClrPrioTag(ConsumersProcessMap, PrioTag); // remove current process from the wait map 00378 return false; 00379 } 00380 } 00381 } 00382 } 00383 //------------------------------------------------------------------------------ 00384 template<typename T, word Size, typename S> 00385 void OS::channel<T, Size, S>::flush() 00386 { 00387 TCritSect cs; 00388 pool.flush(); 00389 CheckWaiters(ProducersProcessMap); 00390 } 00391 //------------------------------------------------------------------------------ 00392 template<typename T, word Size, typename S> 00393 void OS::channel<T, Size, S>::write(const T* data, const S count) 00394 { 00395 TCritSect cs; 00396 00397 while(pool.get_free_size() < count) 00398 { 00399 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); 00400 SetPrioTag(ProducersProcessMap, PrioTag); // channel does not have enough space, put current process to the wait map 00401 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map 00402 Kernel.Scheduler(); 00403 } 00404 00405 pool.write(data, count); 00406 CheckWaiters(ConsumersProcessMap); 00407 } 00408 //------------------------------------------------------------------------------ 00409 template<typename T, word Size, typename S> 00410 bool OS::channel<T, Size, S>::read(T* const data, const S count, TTimeout timeout) 00411 { 00412 TCritSect cs; 00413 00414 TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority]; 00415 p->Timeout = timeout; 00416 00417 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); 00418 while(pool.get_count() < count) 00419 { 00420 SetPrioTag(ConsumersProcessMap, PrioTag); // channel doesn't contain enough data, put current process to the wait map 00421 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map 00422 Kernel.Scheduler(); 00423 00424 if(ConsumersProcessMap & PrioTag) // waked up by timer when timeout expired 00425 { // or by OS::ForceWakeUpProcess() 00426 00427 p->Timeout = 0; // non-zero if waked up by ForceWakeUpProcess() 00428 ClrPrioTag(ConsumersProcessMap, PrioTag); // remove current process from the wait map 00429 return false; 00430 } 00431 } 00432 00433 p->Timeout = 0; 00434 pool.read(data, count); 00435 CheckWaiters(ProducersProcessMap); 00436 00437 return true; 00438 } 00439 //------------------------------------------------------------------------------ 00440 00441 //------------------------------------------------------------------------------ 00442 // 00443 // OS::message template 00444 // 00445 // Function-members implementation 00446 // 00447 // 00448 //------------------------------------------------------------------------------ 00449 void OS::TBaseMessage::sendISR() 00450 { 00451 TCritSect cs; 00452 00453 if(ProcessMap) 00454 { 00455 TProcessMap Timeouted = OS::Kernel.ReadyProcessMap; // Process has it's tag set in ReadyProcessMap if timeout 00456 // expired, or it was waked up by OS::ForceWakeUpProcess() 00457 if( ProcessMap & ~Timeouted ) // if any process has to be waked up 00458 { 00459 SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map 00460 ClrPrioTag(ProcessMap, ~Timeouted); // remove all non-timeouted processes from the waiting map. 00461 return; 00462 } 00463 } 00464 NonEmpty = true; 00465 } 00466 //------------------------------------------------------------------------------ 00467 #endif // OS_SERVICES_H
Generated on Tue Jul 12 2022 21:14:46 by 1.7.2