Daniel Peter
/
RtosTest
Embed:
(wiki syntax)
Show/hide line numbers
OS_Services.cpp
00001 //****************************************************************************** 00002 //* 00003 //* FULLNAME: Single-Chip Microcontroller Real-Time Operating System 00004 //* 00005 //* NICKNAME: scmRTOS 00006 //* 00007 //* PURPOSE: OS Services Source 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 #include "scmRTOS.h" 00043 00044 using namespace OS; 00045 00046 //------------------------------------------------------------------------------ 00047 // 00048 // 00049 // TEventFlag 00050 // 00051 // 00052 bool OS::TEventFlag::Wait(TTimeout timeout) 00053 { 00054 TCritSect cs; 00055 00056 if(Value) // if flag already signaled 00057 { 00058 Value = efOff; // clear flag 00059 return true; 00060 } 00061 else 00062 { 00063 TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority]; 00064 p->Timeout = timeout; 00065 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); 00066 00067 SetPrioTag(ProcessMap, PrioTag); // put current process to the wait map 00068 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map 00069 00070 Kernel.Scheduler(); 00071 00072 p->Timeout = 0; 00073 00074 if( !(ProcessMap & PrioTag) ) // if waked up by signal() or signal_ISR() 00075 return true; 00076 00077 ClrPrioTag(ProcessMap, PrioTag); // otherwise waked up by timeout or by 00078 return false; // OS::ForceWakeUpProcess(), remove process from the wait map 00079 } 00080 } 00081 //------------------------------------------------------------------------------ 00082 void OS::TEventFlag::Signal() 00083 { 00084 TCritSect cs; 00085 if(ProcessMap) // if any process waits for event 00086 { 00087 TProcessMap Timeouted = Kernel.ReadyProcessMap; // Process has its tag set in ReadyProcessMap if timeout expired 00088 // or it was waked up by OS::ForceWakeUpProcess() 00089 00090 if( ProcessMap & ~Timeouted ) // if any process has to be waked up 00091 { 00092 SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map 00093 ClrPrioTag(ProcessMap, ~Timeouted); // remove all non-timeouted processes from the waiting map. 00094 // Used to check that process waked up by signal() or signalISR() 00095 // and not by timeout or OS::ForceWakeUpProcess() 00096 Kernel.Scheduler(); 00097 return; 00098 } 00099 } 00100 Value = efOn; 00101 } 00102 //------------------------------------------------------------------------------ 00103 00104 //------------------------------------------------------------------------------ 00105 // 00106 // 00107 // TMutex 00108 // 00109 // 00110 void OS::TMutex::Lock() 00111 { 00112 TCritSect cs; 00113 00114 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); 00115 while(ValueTag) 00116 { 00117 SetPrioTag(ProcessMap, PrioTag); // mutex already locked by another process, put current process to the wait map 00118 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map 00119 00120 Kernel.Scheduler(); 00121 } 00122 ValueTag = PrioTag; // mutex has been successfully locked 00123 } 00124 //------------------------------------------------------------------------------ 00125 void OS::TMutex::Unlock() 00126 { 00127 TCritSect cs; 00128 00129 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); 00130 if(ValueTag != PrioTag) return; // the only process that had locked mutex can unlock the mutex 00131 ValueTag = 0; 00132 if(ProcessMap) 00133 { 00134 byte pr = GetHighPriority(ProcessMap); 00135 PrioTag = GetPrioTag(pr); 00136 ClrPrioTag(ProcessMap, PrioTag); // remove next ready process from the wait map 00137 SetPrioTag(Kernel.ReadyProcessMap, PrioTag); // place next process to the ready map 00138 Kernel.Scheduler(); 00139 } 00140 } 00141 //------------------------------------------------------------------------------ 00142 void OS::TMutex::UnlockISR() 00143 { 00144 TCritSect cs; 00145 00146 ValueTag = 0; 00147 if(ProcessMap) 00148 { 00149 byte pr = GetHighPriority(ProcessMap); 00150 TProcessMap PrioTag = GetPrioTag(pr); 00151 ClrPrioTag(ProcessMap, PrioTag); // remove next ready process from the wait map 00152 SetPrioTag(Kernel.ReadyProcessMap, PrioTag); // place next process to the ready map 00153 } 00154 } 00155 //------------------------------------------------------------------------------ 00156 00157 00158 //------------------------------------------------------------------------------ 00159 // 00160 // 00161 // TChannel 00162 // 00163 // 00164 void OS::TChannel::CheckWaiters(TProcessMap& pm) 00165 { 00166 if(pm) 00167 { 00168 byte pr = GetHighPriority(pm); 00169 TProcessMap PrioTag = GetPrioTag(pr); 00170 ClrPrioTag(pm, PrioTag); // remove next ready process from the wait map 00171 SetPrioTag(Kernel.ReadyProcessMap, PrioTag); // place next process to the ready map 00172 Kernel.Scheduler(); 00173 } 00174 } 00175 //------------------------------------------------------------------------------ 00176 void OS::TChannel::Push(byte x) 00177 { 00178 TCritSect cs; 00179 00180 while (!Cbuf.get_free_size()) 00181 { 00182 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); 00183 SetPrioTag (ProducersProcessMap, PrioTag); // channel is full, put current process to the wait map 00184 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map 00185 Kernel.Scheduler(); // wait until waked-up by Pop() or Read() 00186 } 00187 00188 Cbuf.put(x); 00189 CheckWaiters(ConsumersProcessMap); 00190 } 00191 //------------------------------------------------------------------------------ 00192 byte OS::TChannel::Pop() 00193 { 00194 TCritSect cs; 00195 byte x; 00196 00197 while(!Cbuf.get_count()) 00198 { 00199 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); 00200 SetPrioTag(ConsumersProcessMap, PrioTag); // channel is empty, put current process to the wait map 00201 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map 00202 Kernel.Scheduler(); // wait until waked up by Push() or Write() 00203 } 00204 x = Cbuf.get(); 00205 CheckWaiters(ProducersProcessMap); 00206 return x; 00207 } 00208 //------------------------------------------------------------------------------ 00209 void OS::TChannel::Write(const byte* data, const byte count) 00210 { 00211 TCritSect cs; 00212 00213 while(Cbuf.get_free_size() < count) 00214 { 00215 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); 00216 SetPrioTag(ProducersProcessMap, PrioTag); // channel has not enough space, put current process to the wait map 00217 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map 00218 Kernel.Scheduler(); // wait until waked up by Read() or Pop() 00219 } 00220 00221 Cbuf.write(data, count); 00222 CheckWaiters(ConsumersProcessMap); 00223 } 00224 //------------------------------------------------------------------------------ 00225 void OS::TChannel::Read(byte* const data, const byte count) 00226 { 00227 TCritSect cs; 00228 00229 while(Cbuf.get_count() < count) 00230 { 00231 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); 00232 SetPrioTag(ConsumersProcessMap, PrioTag); // channel doesn't contain enough data, put current process to the wait map 00233 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map 00234 Kernel.Scheduler(); // wait until waked up by Write() or Push() 00235 } 00236 00237 Cbuf.read(data, count); 00238 CheckWaiters(ProducersProcessMap); 00239 } 00240 //------------------------------------------------------------------------------ 00241 00242 //------------------------------------------------------------------------------ 00243 // 00244 // OS::message template 00245 // 00246 // Function-members implementation 00247 // 00248 // 00249 //------------------------------------------------------------------------------ 00250 bool OS::TBaseMessage::wait(TTimeout timeout) 00251 { 00252 TCritSect cs; 00253 00254 if(NonEmpty) // message alredy send 00255 { 00256 NonEmpty = false; 00257 return true; 00258 } 00259 else 00260 { 00261 TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority]; 00262 p->Timeout = timeout; 00263 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); 00264 00265 SetPrioTag(ProcessMap, PrioTag); // put current process to the wait map 00266 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map 00267 Kernel.Scheduler(); // wait until wake up 00268 00269 p->Timeout = 0; 00270 if( !(ProcessMap & PrioTag) ) // if waked up by send() or sendISR() 00271 return true; 00272 00273 ClrPrioTag(ProcessMap, PrioTag); // otherwise waked up by timeout or by 00274 return false; // OS::ForceWakeUpProcess(), remove process from wait map 00275 } 00276 } 00277 //------------------------------------------------------------------------------ 00278 void OS::TBaseMessage::send() 00279 { 00280 TCritSect cs; 00281 00282 if(ProcessMap) 00283 { 00284 TProcessMap Timeouted = Kernel.ReadyProcessMap; // Process has its tag set in ReadyProcessMap if timeout expired, 00285 // or it was waked up by OS::ForceWakeUpProcess() 00286 if( ProcessMap & ~Timeouted ) // if any process has to be waked up 00287 { 00288 SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map 00289 ClrPrioTag(ProcessMap, ~Timeouted); // remove all non-timeouted processes from the waiting map. 00290 Kernel.Scheduler(); 00291 return; 00292 } 00293 } 00294 00295 NonEmpty = true; 00296 } 00297 //------------------------------------------------------------------------------ 00298
Generated on Tue Jul 12 2022 21:14:46 by 1.7.2