【问题标题】:Give access to a resource based on thread priority/privilege根据线程优先级/特权授予对资源的访问权限
【发布时间】:2017-05-23 08:43:27
【问题描述】:

我不是开发人员,我只是在玩编程,试图让我的工作场所更加自主。 我目前正在尝试让一系列具有所有不同优先级(0:最高 8:最低)的 9 个线程使用相同的 UART 端口。

由于我必须发送紧急请求,我想创建一个锁,允许最高优先级的线程首先进入资源。

我还必须让 receive_data IRQ 线程在 UART 端口发生时立即处理它(或者尽快,硬件 UART 缓冲区是 500 字节长)。

我一直在环顾四周,如果我需要更多优先级/线程(或至少需要大量编码),使用嵌套互斥锁会阻止我使代码进化。

我读过这个问题:How to give priority to privileged thread in mutex locking?,第二个答案看起来像我想要的……但我不明白如何实现这个过程。

由于问题有点老了,还有其他方法可以做我想做的事吗? 如果没有,我可以获得更易读的版本吗(木工)?

问题:如何保护对 UART 读写器的访问,并根据线程的优先级给予线程的优先访问权?

注意:

线程当前正在读取每个 fifo,并且在 fifo 为空时处于休眠状态,并在将某些内容放入各自的 fifo 时启动。

然后线程以硬件可以解释并通过 UART 发送的格式处理命令/数据。

我尝试这样做,因为我意识到,当我使用单个线程并且 fifo 被大量填充时,有时紧急命令会等待大约 1 秒或更长时间才能被处理。

另外,对不起,如果我的英语让你起鸡皮疙瘩。

【问题讨论】:

  • 请重新整理您的问题,以便更清楚地说明您的问题。
  • 这是一项非常重要的工作。链接的问题似乎确实有多个代码示例,这将是一个很好的起点(或完整的解决方案),如果您不能利用它,您可能需要重新考虑您的设计以简化事情,直到您可以做出一些工作,并在以后转移到更复杂的系统。

标签: c++ pthreads


【解决方案1】:

正如 cmets 中所述,这是一项复杂的任务。

一种方法是创建一个像这样的类:

class UART_access_manager

{

typedef std::multimap<int, dispatch_semaphore_t> priority_map_t;
public:

 UART_access_manager();
~UART_access_manager();
void access_manager(unsigned int prio, dispatch_semaphore_t pSem);


private:

void amInext(unsigned int prio);
void process_priority(unsigned int prio);
void priority_locker(unsigned int prio);
void priority_unlocker(unsigned int prio);


int count;
std::mutex data_mtx, priority_0_mtx, mtx;
priority_map_t priority_map;
};

请注意,我在 OSX 上构建了测试并且无法使用未命名的信号量,我没有检查调度是否在其他操作系统上可用(可能不是作为它的苹果库)。

UART_access_manager::UART_access_manager()

{

}
UART_access_manager::~UART_access_manager()
{

}



 /*********************************************************************
  *
  * Function:        void UART_access_manager::access_manager(unsigned

int prio, dispatch_semaphore_t pSem)
 *
 * Description:     add an UART access request to the queue based on priority & start process based on type
 *
 * Notes:           0 is highest
 *
 * Returns:         none
 *
 *********************************************************************/

void UART_access_manager::access_manager(unsigned int prio, dispatch_semaphore_t pSem)//, add parameters at will
 {
 int counter = 1; //debug only
 while (counter) //should check for termination criteria
 {
    //check if something was pushed on the file descriptor

    if( counter == 10) //add run condition
    {
        counter = 0; //debug

        priority_locker(prio);

        priority_map_t::iterator it = priority_map.insert(std::pair<int, dispatch_semaphore_t>(prio, pSem) );
        printf("\n thread with priority %d added to queue(size %lu)", prio, priority_map.size());
        amInext(prio);

        priority_unlocker(prio);

        while(dispatch_semaphore_wait(pSem, DISPATCH_TIME_NOW) != 0){};



        priority_locker(prio);
        // do the actual job
        process_priority(prio);
        // done, remove yourself
        priority_map.erase(it);
        if( ! priority_map.empty() )
        {
            // let next guy run:
            dispatch_semaphore_signal((priority_map.begin()->second));
        }
        priority_unlocker(prio);
    }
    else
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(50)); //test purpose only
        counter++;
    }

 }
}


/*********************************************************************
 *
 * Function:       void UART_access_manager::amInext(unsigned int prio)
 *
 * Description:    check if current priority has to run next or not
 *
 * Notes:           0 is highest
 *
 * Returns:        none
 *
 *********************************************************************/
 void UART_access_manager::amInext(unsigned int prio)
{

 if(priority_map.begin()->first == prio) dispatch_semaphore_signal(priority_map.begin()->second);
}


/*********************************************************************
*
* Function:        void UART_access_manager::process_priority(unsigned 
int prio)
*
* Description: TODO
*********************************************************************/
void UART_access_manager::process_priority(unsigned int prio)
{
 printf("\n    Priority_%d running \n",prio);
 //TODO
}

/*********************************************************************
*
* Function:       void UART_access_manager::priority_locker(unsigned 
int prio)
*
 * Description:     lock mutex in a way to guarantee priority event 
 to 
 *                  get the fastest lock possible
 *
 * Notes:           0 is highest
 ******************************************************************/
 void UART_access_manager::priority_locker(unsigned int prio)
 {
 //Low-priority threads: lock mtx, lock priority_0_mtx, lock data_mtx, 
  unlock priority_0_mtx,
 //High-priority thread: lock priority_0_mtx, lock data_mtx, unlock 
  priority_0_mtx,
  //this will insure that max priority level get privileged access to 
 the data

if(!prio)
 {
    priority_0_mtx.lock();
    data_mtx.lock();
    priority_0_mtx.unlock();
 }
else
 {
    mtx.lock();
    priority_0_mtx.lock();
    data_mtx.lock();
    priority_0_mtx.unlock();
 }
}

/*********************************************************************
 *
 * Function:        void 
 UART_access_manager::priority_unlocker(unsigned int prio)
 *
 * Description:     unlock mtx based on the mutex locked by the 
 priority level
 *
 * Notes:           0 is highest
 *
 * Returns:         none
 *
 *********************************************************************/
void UART_access_manager::priority_unlocker(unsigned int prio)
{
if(!prio)
 {
    data_mtx.unlock();
 }
else
 {
    mtx.unlock();
    data_mtx.unlock();
 }
}

代码冗长易于理解,并且不会做任何事情,您进展顺利,将其视为一项作业,如果您有任何问题,请不要犹豫,评论,我会回复。

(HS:你想做什么?)

您将学到的东西: std::multimap 标准::互斥 信号量 类

【讨论】:

  • 试过了,按你说的稍微改了一下,效果很好。会更深入地研究它。
猜你喜欢
  • 1970-01-01
  • 2016-06-13
  • 2021-03-21
  • 2021-05-19
  • 1970-01-01
  • 2020-01-31
  • 1970-01-01
  • 1970-01-01
  • 2013-10-15
相关资源
最近更新 更多