⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_services.h

📁 scmRTOS is real-time preemptive operating system and supports up to 31 user processes (and one syste
💻 H
📖 第 1 页 / 共 2 页
字号:
//------------------------------------------------------------------------------
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 + -