如何挂起另一个线程(不是当前线程)?

Wer*_*thé 5 linux multithreading pthreads

我正在尝试实现微控制器的仿真.该仿真并不意味着对一个特定微控制器进行时钟周期精确表示,而是检查代码的一般正确性.

我想过有一个执行普通代码的"主线程"和一个执行ISR代码的第二个线程.每当需要运行ISR时,ISR线程就会挂起"主线程".

当然,我想要一个阻止中断的功能.我想用一个互斥体解决这个问题,ISR线程只要执行ISR代码就会保留,而主线程只要"中断被阻塞"就会保存它.

然后可以通过暂停但杀死主线程(以及启动执行POR功能的新线程)来实现POR(上电复位).

Windows API提供了必要的功能.但似乎不可能使用posix线程(在linux上)执行上述操作.

我不想改变实际的硬件独立微控制器代码.因此,插入任何内容以检查挂起的中断都不是一种选择.

在非性能良好的点接收中断是可取的,因为这也发生在微控制器上(除非阻止中断).

有没有办法在Linux上挂起另一个线程?(我认为,调试器必须以某种方式使用该选项.)

拜托,不要告诉我这是一个坏主意.我知道在大多数情况下都是如此.但主代码不使用标准库或锁/互斥量/信号量.

luc*_*cho 11

SIGSTOP不起作用 - 它总是停止整个过程.相反,您可以使用其他一些信号,例如SIGUSR1用于暂停,SIGUSR2用于恢复:

// at process start call init_pthread_suspending to install the handlers
// to suspend a thread use pthread_kill(thread_id, SUSPEND_SIG)
// to resume a thread use pthread_kill(thread_id, RESUME_SIG)

#include <signal.h>

#define RESUME_SIG SIGUSR2
#define SUSPEND_SIG SIGUSR1

static sigset_t wait_mask;
static __thread int suspended; // per-thread flag

void resume_handler(int sig)
{
    suspended = 0;
}

void suspend_handler(int sig)
{
    if (suspended) return;
    suspended = 1;
    do sigsuspend(&wait_mask); while (suspended);
}

void init_pthread_suspending()
{
    struct sigaction sa;

    sigfillset(&wait_mask);
    sigdelset(&wait_mask, SUSPEND_SIG)
    sigdelset(&wait_mask, RESUME_SIG);

    sigfillset(&sa.sa_mask);
    sa.sa_flags = 0;
    sa.sa_handler = resume_handler;
    sigaction(RESUME_SIG, &sa, NULL);

    sa.sa_handler = suspend_handler;
    sigaction(SUSPEND_SIG, &sa, NULL);
}
Run Code Online (Sandbox Code Playgroud)

我很反感像"你不应该暂停另一个线程,那是坏事".伙计们为什么你认为别人是白痴,不知道他们在做什么?想象一下,其他人也听说过死锁,而且在完全意识中,他们还想暂停其他线程.如果你对他们的问题没有真正的答案,为什么要浪费你和读者的时间.

是的,IMO pthreads是非常短视的api,对POSIX来说是一种耻辱.


Wer*_*thé 5

Hotspot JAVA VM使用SIGUSR2为Linux上的JAVA线程实现挂起/恢复.

基于SIGUSR2的信号处理程序的过程可能是:

为SIGUSR2提供信号处理程序允许线程请求锁定(已经由信号发送线程获取).

这会挂起线程.

一旦挂起线程释放锁定,信号处理程序就可以(并且将会)获得锁定.信号处理程序立即释放锁并离开信号处理程序.

这将恢复该线程.

在开始实际处理ISR之前,可能需要引入一个控制变量以确保主线程在信号处理程序中.(细节取决于是同步还是异步调用信号处理程序.)

我不知道,如果这正是它在Java VM中的完成方式,但我认为上述过程可以满足我的需要.


Jos*_*hua 3

不知怎的,我认为发送另一个线程 SIGSTOP 是有效的。

但是,最好编写一些涉及 senaogires.mutexes 和全局变量的线程通信。

你看,如果你在 malloc() 中挂起另一个线程并且调用 malloc() -> 死锁。

我是否提到过,许多 C 标准库函数(更不用说您使用的其他库)都会在您背后调用 malloc() ?

编辑:

嗯,没有标准库代码。也许使用信号处理程序中的 setjmp/longjump() 来模拟 POR,并使用信号处理程序来模拟中断。

对于那些一直对此表示反对的人:编辑后的内容的答案被接受,这是一个特定的场景,不能在任何其他场景中使用。