这两个中断服务例程中的竞争条件是什么?

aga*_*rie 5 c queue multithreading arm interrupt

我在大学的实时系统课程中使用 ARM 微控制器。在我目前正在进行的项目中,我正在实现矢量场直方图(VFH)算法。

问题是:我需要在线程之间进行通信;更具体地说,我想要一个线程从测距仪获取传感器数据,对其进行必要的转换并将它们存储在队列中。他们,另一个线程必须获取这些数据并处理它,等等。

目前,我正在使用它的一个更简单的版本 - 一个线程从 ADC (SensorAcquisitionHandler) 获取数据,另一个线程将前 5 项(最多)的平均值输出到显示器 (ControlSignalHandler)。

/* Queue used to store data from the rangefinder sensors. */
static unsigned int Sensors[100];
static int SensorsHead = 0;
static int SensorsTail = 0;

void SensorAcquisitionHandler(void) {
    /* Clear the interrupt. */
    ADCIntClear(ADC0_BASE, 1);

    int i; /* Index for the measurements buffer. */

    /* There are only 3 rangefinders used. */
    if (ADCSequenceDataGet(ADC0_BASE, 1, rangeBuffer) == 3) {
        /* Put rangeBuffer's data into SensorDataQueue. */
        /* Also, when using SensorDataQueue, must put what's the direction of 
        the corresponding range measurement. */

        /* Critical section ahead!!! Turn off interrupts!!! */
        IntMasterDisable();

        /* Temporarily using the simple FIFO... */
        for (i = 0; i < 3; ++i) {
            if (SensorsHead < 100) {
                Sensors[SensorsHead] = rangeBuffer[i];
                SensorsHead++;
            }
        }

        /* All is fine, turn on interrupts. */
        IntMasterEnable();
    }
}

void ControlSignalHandler(void) {
    /* Clear the timer interrupt. */
    TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

    unsigned char i; /* Index for the measurements buffer. */
    unsigned long average = 0;
    char buffer[20];

    /* Average first n (n <= 5) elements from Sensors queue. */
    for (i = 0; i < 5 && SensorsTail < SensorsHead; ++i) {
        average += Sensors[SensorsTail];
        SensorsTail++;
    }

    IntMasterDisable();
    average /= i;

    sprintf(buffer, "%d  ", average);

    average = 0;

    if (SensorsTail >= SensorsHead) {
        SensorsTail = 0;
        SensorsHead = 0;
    }

    Display96x16x1StringDraw(buffer, 0, 0);
    IntMasterEnable();
}
Run Code Online (Sandbox Code Playgroud)

结果在一段时间内相对稳定,但在随机间隔内会变得非常高(结果几乎始终约为 330)。另外,当我在“非常高的值”时刻使用符号调试器时,索引 SensorTail 和 SensorHead 可以达到 300+(队列是一个 100 个元素的数组)。

这听起来像是某种溢出,但我无法想象它是如何发生的。有人可以帮我找到它吗?

我知道问题的答案是“使用线程安全队列”,但我想了解这里如何发生竞争条件,索引如何变得混乱等等。谢谢!

Nem*_*emo 3

通过清除中断,您就允许它再次发生。想象一下,如果(例如)ControlSignalHandler由于计时器设法超出了您的代码而在第一个循环的中间重新进入,会发生什么......

整个函数(两者)包裹在IntMasterDisable+中IntMasterEnable,并在禁用之后和启用之前清除中断。(我会在启用之前立即执行此操作。)