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

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

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中调用它们。 我是这种东西的新手,而且我已经在脑海里了。 任何帮助表示赞赏。

pthread_suspend真的好像是可行的方式。 这个解决方案可能比它的价值更脏。 为每个线程保留一个semaphore 。 让每个线程监听信号。 在信号处理程序中,只需down相关的信号量即可。

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

警告:

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

不幸的是,我找不到任何关于此的真正的免费文档。 仍然,恒星与否,有很多免费文档。

编辑

正如@R所建议的那样,有async-signal-safe函数阻止你可以使用(而不是不安全的sem_wait )。 这是您可以安全使用的function列表 。

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

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

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

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

//全局变量

 int _fSigSet; 

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

 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倍。

以下是一些使用此技术的代码 。