c++ - 根据线程优先级/特权授予对资源的访问权限

标签 c++ pthreads

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

因为我必须发送紧急请求,所以我会创建一个锁,允许优先级最高的线程首先处理资源。

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

我一直在四处寻找,如果我需要更多优先级/线程(或者至少需要大量编码),使用嵌套互斥会阻止我改进代码。

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

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

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

注意:

线程当前各自读取一个 fifo,并在 fifo 为空时休眠,并在有内容放入各自的 fifo 时启动。

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

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

另外,抱歉,如果我的英语让您起鸡皮疙瘩。

最佳答案

如评论中所述,这是一项复杂的任务。

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

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 std::互斥量 信号量 类

关于c++ - 根据线程优先级/特权授予对资源的访问权限,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44129926/

相关文章:

c++ - Clang 和 GCC 中不明确的基类转换之间的行为差​​异

c - 线程例程内的 malloc

c++ - 如何找到 pthread 的创建顺序?

linux - pthreads 条件变量在 Linux 中是如何实现的?

posix - 针对 pthread 函数 pthread_condattr_setclock 链接 NPTL

c++ - Qt C++ WebKit windowCloseRequested 信号

c++ - CGAL 二维 alpha 形状轮廓

c++ - 有什么方法可以结合 std::istream_iterator 和 std::for_each_n() 吗?

c - 多线程等待的 `pthread_mutex_lock()` 唤醒顺序是什么?

c++ - 关于将 FFmpeg 编译成静态构建(仅限 .lib 文件)以便在 Visual Studio 中使用的说明?