将pthread作为输入并暂停的函数

时间:2011-04-20 21:59:44

标签: c pthreads real-time xenomai preempt-rt

我正在尝试从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 个答案:

答案 0 :(得分:3)

如果它可用,

pthread_suspend似乎真的要走了。这个解决方案可能比它的价值更脏。对于每个帖子,请保留semaphore。让每个线程监听信号。在信号处理程序中,只需在相关的信号量上执行down

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

警告:

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

不幸的是,我找不到任何关于此的真正免费文档。不管是不是,还是有很多免费文档。

修改

正如@R所建议的那样,有async-signal-safe个函数阻止你可以使用(而不是不安全的sem_wait)。这是a list of functions you may safely use

答案 1 :(得分:1)

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

答案 2 :(得分:1)

您可以使用两个信号完全移植(避免使用异步信号不安全功能的所有问题):

“线程挂起”信号处理程序将使用pselect以原子方式解锁第二个信号并无限期地休眠。第二个信号将终止pselect并导致信号处理程序返回。

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

答案 3 :(得分: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倍。

以下是一些使用此技术的code