3

我正在尝试从 POSIX 中的 ExpressLogic 移植实时 Thread_Metric,以便为我的论文对 Linux、Xenomai 和 RTAI 的 PREEMPT_RT 补丁进行基准测试。它们提供了具有以下功能的 C 源文件,您必须实现这些功能才能使基准测试工作:

void   tm_initialize(void (*test_initialization_function)(void));
int    tm_thread_create(int thread_id, int priority, void (*entry_function)(void));
int    tm_thread_resume(int thread_id);
int    tm_thread_suspend(int thread_id);
void   tm_thread_relinquish(void);
void   tm_thread_sleep(int seconds);
int    tm_queue_create(int queue_id);
int    tm_queue_send(int queue_id, unsigned long *message_ptr);
int    tm_queue_receive(int queue_id, unsigned long *message_ptr);
int    tm_semaphore_create(int semaphore_id);
int    tm_semaphore_get(int semaphore_id);
int    tm_semaphore_put(int semaphore_id);
int    tm_memory_pool_create(int pool_id);
int    tm_memory_pool_allocate(int pool_id, unsigned char **memory_ptr);
int    tm_memory_pool_deallocate(int pool_id, unsigned char *memory_ptr);

现在我正在尝试实现 tm_thread_suspend 和 tm_thread_resume 函数,它们将 pthread 作为输入。我知道您可以使用 pthread_mutex_lock 和 pthread_cond_wait 例程挂起 pthread,但是您必须从线程 start_function 调用它们。我是这种东西的新手,而且我已经过头了。任何帮助表示赞赏。

4

4 回答 4

3

pthread_suspend如果它可用的话,真的似乎是要走的路。这个解决方案可能比它的价值更脏。为每个线程保留一个semaphore. 让每个线程监听信号。在信号处理程序中,只需down对相关的信号量执行一个操作。

因此,当您想要stop一个线程时,只需向它发送一个信号(也许最好使用实时信号),它就会在处理程序中停止。默认情况下,处理程序会屏蔽自身(也就是说,如果在完成之前接收到相同的信号,则不会再次调用它)。当你想重新启动线程时,只需up在信号量上做一个。

警告:

  • 使用@bmargulies 的建议,如果可以的话,它会更好(更安全、更清洁、更高效)
  • 您还可以使用互斥锁代替信号量
  • 处理信号是一项令人讨厌的工作。在开始之前,请确保您(重新)阅读
    • 异步信号安全
    • 线程和信号
    • 中断和重新启动系统调用 ( SA_RESTART)
  • 我很确定sem_wait(3)异步信号不是安全的,但只要你不使用SA_NODEFER它就是安全的(不是你有任何理由)

不幸的是,我找不到任何关于此的真正出色的免费文档。尽管如此,无论是否出色,都有很多免费文档。

编辑

正如@R.. 所建议的async-signal-safe那样,您可以使用一些阻塞功能(而不是 unsafe sem_wait)。这是您可以安全使用的功能列表

于 2011-04-20T22:27:56.447 回答
1

pthread 的一些实现具有这些功能。http://www.unix.com/man-page/all/3t/pthread_suspend/但是你的linux内核可能不支持它们。

于 2011-04-20T22:03:17.180 回答
1

您可以使用两个信号完全可移植地执行此操作(避免 async-signal-unsafe 函数的所有问题):

“线程挂起”信号处理程序将用于pselect原子地解除对第二个信号的阻塞并无限期地休眠。第二个信号将终止pselect并导致信号处理程序返回。

还有很多其他使用异步信号安全接口的解决方案——基本上任何处理文件描述符并阻止它们而不是用户空间同步原语的东西。例如,read从管道中获取信号处理程序并将单个字节写入管道以恢复线程将起作用。

于 2011-04-20T22:54:17.470 回答
0

这样做的方法是使用 sigwait() 和 pthread_kill。

// 全局变量

int _fSigSet; 

在调用 pthread_create 之前,我们设置了一个信号掩码。每个线程都将继承掩码。你可以在我想的线程函数中设置掩码。这是我们使用的代码:

sigemptyset(&_fSigSet);
sigaddset(&_fSigSet, SIGUSR1);
sigaddset(&_fSigSet, SIGSEGV);
pthread_sigmask(SIG_BLOCK, &_fSigSet, NULL);
... 
pthread_create(&Thread, NULL, ThreadProc, NULL);
...

暂停:

int nSig;  // signal you get if you care.
sigwait(&_fSigSet, &nSig);  // thread is suspended here waiting for signal.

恢复:

pthread_kill(&Thread, SIGUSR1);

如果由于某种原因您不能使用 SIGUSR1,请注意并非所有信号都对我们有效。我们可能做错了什么,但 SIGCONT 不起作用。

我们以这种方式对暂停线程进行了基准测试,这种方法比使用互斥锁和条件变量快 5 倍。

下面是一些使用这种技术的代码。

于 2011-04-25T23:41:29.177 回答