📄 os_services.h
字号:
//------------------------------------------------------------------------------
void OS::TEventFlag::SignalISR()
{
TCritSect cs;
if(ProcessMap) // if any process waits for event
{
TProcessMap Timeouted = Kernel.ReadyProcessMap; // Process has its tag set in ReadyProcessMap if timeout
// expired, or it was waked up by OS::ForceWakeUpProcess()
SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map
ClrPrioTag(ProcessMap, ~Timeouted); // remove all non-timeouted processes from the waiting map.
}
else
{
Value = efOn;
}
}
//------------------------------------------------------------------------------
template<typename T, word Size, typename S>
void OS::channel<T, Size, S>::CheckWaiters(TProcessMap& pm)
{
if(pm)
{
TProcessMap Timeouted = Kernel.ReadyProcessMap;
SetPrioTag(Kernel.ReadyProcessMap, pm); // place all waiting processes to the ready map
ClrPrioTag(pm, ~Timeouted); // remove waiting processes from the wait map
Kernel.Scheduler();
}
}
//------------------------------------------------------------------------------
template<typename T, word Size, typename S>
void OS::channel<T, Size, S>::push(const T& item)
{
TCritSect cs;
while(!pool.get_free_size())
{
TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
SetPrioTag(ProducersProcessMap, PrioTag); // channel is full, put current process to the wait map
ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
Kernel.Scheduler();
}
pool.push_back(item);
CheckWaiters(ConsumersProcessMap);
}
//------------------------------------------------------------------------------
template<typename T, word Size, typename S>
void OS::channel<T, Size, S>::push_front(const T& item)
{
TCritSect cs;
while(!pool.get_free_size())
{
TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
SetPrioTag(ProducersProcessMap, PrioTag); // channel is full, put current process to the wait map
ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
Kernel.Scheduler();
}
pool.push_front(item);
CheckWaiters(ConsumersProcessMap);
}
//------------------------------------------------------------------------------
template<typename T, word Size, typename S>
bool OS::channel<T, Size, S>::pop(T& item, TTimeout timeout)
{
TCritSect cs;
if(pool.get_count())
{
item = pool.pop();
CheckWaiters(ProducersProcessMap);
return true;
}
else
{
TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority];
p->Timeout = timeout;
TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
for(;;)
{
SetPrioTag(ConsumersProcessMap, PrioTag); // channel is empty, put current process to the wait map
ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
Kernel.Scheduler();
if(pool.get_count())
{
p->Timeout = 0;
item = pool.pop();
CheckWaiters(ProducersProcessMap);
return true;
}
if(ConsumersProcessMap & PrioTag) // waked up by timer when timeout expired
{ // or by OS::ForceWakeUpProcess()
p->Timeout = 0; // non-zero if waked up by ForceWakeUpProcess()
ClrPrioTag(ConsumersProcessMap, PrioTag); // remove current process from the wait map
return false;
}
}
}
}
//------------------------------------------------------------------------------
template<typename T, word Size, typename S>
bool OS::channel<T, Size, S>::pop_back(T& item, TTimeout timeout)
{
TCritSect cs;
if(pool.get_count())
{
item = pool.pop_back();
CheckWaiters(ProducersProcessMap);
return true;
}
else
{
TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority];
p->Timeout = timeout;
TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
for(;;)
{
SetPrioTag(ConsumersProcessMap, PrioTag); // channel is empty, put current process to the wait map
ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
Kernel.Scheduler();
if(pool.get_count())
{
p->Timeout = 0;
item = pool.pop_back();
CheckWaiters(ProducersProcessMap);
return true;
}
if(ConsumersProcessMap & PrioTag) // waked up by timer when timeout expired
{ // or by OS::ForceWakeUpProcess()
p->Timeout = 0; // non-zero if waked up by ForceWakeUpProcess()
ClrPrioTag(ConsumersProcessMap, PrioTag); // remove current process from the wait map
return false;
}
}
}
}
//------------------------------------------------------------------------------
template<typename T, word Size, typename S>
void OS::channel<T, Size, S>::flush()
{
TCritSect cs;
pool.flush();
CheckWaiters(ProducersProcessMap);
}
//------------------------------------------------------------------------------
template<typename T, word Size, typename S>
void OS::channel<T, Size, S>::write(const T* data, const S count)
{
TCritSect cs;
while(pool.get_free_size() < count)
{
TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
SetPrioTag(ProducersProcessMap, PrioTag); // channel does not have enough space, put current process to the wait map
ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
Kernel.Scheduler();
}
pool.write(data, count);
CheckWaiters(ConsumersProcessMap);
}
//------------------------------------------------------------------------------
template<typename T, word Size, typename S>
bool OS::channel<T, Size, S>::read(T* const data, const S count, TTimeout timeout)
{
TCritSect cs;
TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority];
p->Timeout = timeout;
TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
while(pool.get_count() < count)
{
SetPrioTag(ConsumersProcessMap, PrioTag); // channel doesn't contain enough data, put current process to the wait map
ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
Kernel.Scheduler();
if(ConsumersProcessMap & PrioTag) // waked up by timer when timeout expired
{ // or by OS::ForceWakeUpProcess()
p->Timeout = 0; // non-zero if waked up by ForceWakeUpProcess()
ClrPrioTag(ConsumersProcessMap, PrioTag); // remove current process from the wait map
return false;
}
}
p->Timeout = 0;
pool.read(data, count);
CheckWaiters(ProducersProcessMap);
return true;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//
// OS::message template
//
// Function-members implementation
//
//
//------------------------------------------------------------------------------
void OS::TBaseMessage::sendISR()
{
TCritSect cs;
if(ProcessMap)
{
TProcessMap Timeouted = OS::Kernel.ReadyProcessMap; // Process has it's tag set in ReadyProcessMap if timeout
// expired, or it was waked up by OS::ForceWakeUpProcess()
SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to ready map
ClrPrioTag(ProcessMap, ~Timeouted); // remove all non-timeouted processes from the waiting map.
}
else
{
NonEmpty = true;
}
}
//------------------------------------------------------------------------------
#endif // OS_SERVICES_H
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -