简体   繁体   English

C:使用pthreads和程序不会退出for循环

[英]C: Using pthreads and program is not exiting a for loop

I am simulating a device that will receive bytes of data and write to a register when the clock has a falling edge. 我正在模拟一种设备,该设备将在时钟具有下降沿时接收字节数据并写入寄存器。 I've created a seperate pthread that will account for shifting the clock between high and low. 我创建了一个单独的pthread,它将负责在高低之间切换时钟。

Now my issue is that in the main thread I have the console ask the user to type a hex value to write to the "device" and it then it calls a SendCommand(uint32_t addr, uint16_t data) function to do that. 现在我的问题是,在主线程中,控制台让用户键入一个十六进制值以写入“设备”,然后它调用SendCommand(uint32_t addr,uint16_t data)函数来执行此操作。 Since it is supposed to send one bit at a time per clock cycle, I have it in a for loop. 由于应该在每个时钟周期一次发送一位,因此我将它放在for循环中。 Here is the send command function: 这是发送命令功能:

void SendCmd(uint32_t loadAddr, uint16_t data)
{
    dest = &loadAddr;
    int i;
    printf("%d\n\n",status);
    for(i=15; i>=0; --i) {
        pthread_cond_wait(&rising_edge, &data_lock);
        *dest = (*dest << 1)|(data & 0x8000) >> 15;
               //     ^^^^^^^^ get MSB
               //               ^^^^^ move the MSB down to the LSB, assuming the
               //                     peripheral wants the bit in the LSB.
        pthread_cond_wait(&falling_edge, &data_lock);
        data <<= 1;
        printf("%d\ti=%d\n",*dest,i);
    }
    pthread_mutex_unlock(&data_lock);
    status = ENABLED_IDLE;
}

When i=0, the loop should exit and return back to the main function where it will ask the user to enter another hex value. 当i = 0时,循环应退出并返回主功能,在此功能将要求用户输入另一个十六进制值。 But it doesnt, and I can't seem to find why it would be stuck before exiting the loop. 但这没有,而且我似乎无法找到为什么退出循环之前会被卡住的原因。

EDIT: The freeze is actually occurring before the function ever executes: 编辑:冻结实际上发生在函数执行之前:

int main()
{
    State status = DISABLED;
    Clock clk = LOW;
    int exit_flag = 0;
    char Command[20];
    pthread_t clk_t;
    pthread_cond_init(&en_sig, NULL);
    pthread_cond_init(&rising_edge, NULL);
    pthread_cond_init(&falling_edge, NULL);
    pthread_mutex_init(&clk_lock, NULL);
    pthread_mutex_init(&data_lock, NULL);
    pthread_create(&clk_t, NULL, simClk, NULL);
    while(!exit_flag)
    {
        if(status != ENABLED_ACTIVE)
        {
            fputs("(enable/disable/write [addr] [word_0] [word_1*]/quit): ", stdout);
            fflush(stdout);
            if ( fgets(Command, sizeof Command, stdin) != NULL )
            {
                char *newline = strchr(Command, '\n');
                if ( newline != NULL )
                {
                    *newline = '\0';
                }
            }

            if(strcasecmp(Command,"quit")==0)
            {
                printf("\nShutting Down!\n\n");
                pthread_cancel(&clk_t);
                pthread_mutex_destroy(&clk_lock);
                exit_flag = ~exit_flag;
                continue;
            }

            if(strcasecmp(Command,"enable")==0)
            {
                if(status != DISABLED)
                {
                    printf("\nSynthesizer is already enabled!\n\n");
                    continue;
                }
                status = ENABLED_IDLE;
                nanosleep(&ecsWait, NULL);
                printf("\nEnabled!\n\n");
                pthread_cond_signal(&en_sig);
                continue;
            }

            if(strcasecmp(Command,"disable")==0)
            {
                status = DISABLED;
               // pthread_mutex_lock(&clk_lock);
                printf("\nDisabled!\n\n");
                continue;
            }

            if(strcasecmp(Command,"w")==0)
            {
                if(status != ENABLED_IDLE)
                {
                    printf("\nSynthesizer is not enabled!\n\n");
                    continue;
                }
                printf("\nWriting!\n\n");
                status = ENABLED_ACTIVE;      //FREEZE OCCURS HERE!
                SendCmd(NREGISTER_ADDR,0xF13F);
                continue;
            }

            printf("Invalid command!\n");
        }
   }
    return 0;

}

The issue: the main thread needs to call pthread_cond_wait before the other thread calls pthread_cond_signal . 问题:主线程需要先调用pthread_cond_wait 然后再另一个线程调用pthread_cond_signal If the other thread signals the condition before the main thread is waiting for the condition, then pthread_cond_wait will never return. 如果另一个线程在主线程等待条件之前发出了该条件的信号,则pthread_cond_wait将永远不会返回。

So you need to make sure that things happen in the proper order, and that's where the mutex comes in. You should lock the mutex before creating the other thread, and only unlock the mutex when you are finished using the condition variable. 因此,您需要确保事情按正确的顺序进行,这就是互斥锁的所在。您应该创建另一个线程之前锁定互斥锁,并且仅在完成使用条件变量后才解锁互斥锁。 The other thread needs to lock the mutex, signal the condition, and unlock the mutex. 另一个线程需要锁定互斥锁,向状态发出信号并解锁互斥锁。

Pseudo code for the main thread 主线程的伪代码

init mutex
lock the mutex
init condition variable
create the other thread
while ( !done )
{
   wait for condition
   do something useful after the condition is signaled 
}
unlock the mutex

Pseudo code for the other thread when it wants to signal the condition 当另一个线程想要发出信号时发出伪代码

lock the mutex
signal the condition 
unlock the mutex

Obvious question: "But if the main thread always has the mutex locked, how will the other thread ever get the mutex?". 显而易见的问题:“但是,如果主线程始终锁定互斥锁,那么另一个线程将如何获取互斥锁?”。 Answer: " pthread_cond_wait internally unlocks the mutex, that's why you pass the mutex to pthread_cond_wait ." 答:“ pthread_cond_wait内部解锁互斥锁,这就是为什么将互斥锁传递给pthread_cond_wait 。”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM