将 pthread 作为输入并将其挂起的函数

发布于 2024-11-02 17:44:49 字数 1166 浏览 4 评论 0原文

我正在尝试从 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 调用这些例程。我对这类事情很陌生,而且我已经无法理解了。任何帮助表示赞赏。

I'm trying to port the real time Thread_Metric from ExpressLogic in POSIX, in order to benchmark PREEMPT_RT patches for Linux, Xenomai and RTAI for my thesis. They provide a C source file with the following functions, which you have to implement in order for the benchmark to work:

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);

Right now I'm trying to implement the tm_thread_suspend and tm_thread_resume functions, which take a pthread as input. I know that you can suspend a pthread with pthread_mutex_lock and pthread_cond_wait routines, but you have to call these from the thread start_function. I'm new at this kind of stuff and I'm way in over my head. Any help is appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

玻璃人 2024-11-09 17:44:49

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

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

警告:

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

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

编辑

按照@R..的建议,有async-signal-safe函数可以阻止您使用(而不是不安全的sem_wait) 。这是您可以安全使用的函数列表

pthread_suspend really seems the way to go if it's available. This solution might be more dirty than it's worth. For each thread keep a semaphore. Make each thread listen for signals. In the signal handler simply do a down on the associated semaphore.

So when you want to stop a thread, simply send it a signal (perhaps using a real-time signal would be best) and it will stop in the handler. The handler masks itself by default (that is, it won't be called again if the same signal is received before it is done). When you want to restart the thread, simply do an up on the semaphore.

Caveat:

  • Use what @bmargulies suggested, it's better (safer, cleaner, more efficient) if you can
  • You can also use a mutex instead of a semaphore
  • Dealing with signals is a nasty job. Before embarking make sure you (re)read about
    • async-signal-safety
    • threads and signals
    • interrupting and restarting system calls (SA_RESTART)
  • I am pretty sure sem_wait(3) isn't async-signal safe, but it's safe as long as you don't use SA_NODEFER (not that you'd have any reason)

Unfortunately I can't find any really stellar free documentation about this. Still, stellar or not, there is a lot of free documentation.

Edit

As suggested by @R.. there are async-signal-safe functions that block that you could use (instead of the unsafe sem_wait). Here's a list of functions you may safely use.

埋葬我深情 2024-11-09 17:44:49

您可以使用两个信号完全可移植地完成此操作(避免异步信号不安全函数的所有问题):

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

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

You can do this completely portably (avoiding all issues with async-signal-unsafe functions) using two signals:

The "thread suspend" signal handler would use pselect to atomically unblock the second signal and sleep indefinitely. The second signal would terminate the pselect and cause the signal handler to return.

Also there are plenty of other solutions using async-signal-safe interfaces - basically anything that deals with file descriptors and blocking on them rather than on user-space synchronization primitives. For example, having the signal handler read from a pipe and writing a single byte to the pipe to resume the thread would work.

月朦胧 2024-11-09 17:44:49

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

Some implementations of pthreads have these functions. http://www.unix.com/man-page/all/3t/pthread_suspend/ But your linux kernel may not support them.

要走干脆点 2024-11-09 17:44:49

执行此操作的方法是使用 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 倍。

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

The way you do this is to use sigwait() and pthread_kill.

// global variable

int _fSigSet; 

Before calling pthread_create we set a signal mask. Every thread will inherit the mask. You could set the mask in the thread function I suppose. Here is the code we use:

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

To SUSPEND:

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

To RESUME:

pthread_kill(&Thread, SIGUSR1);

If you cant use SIGUSR1 for some reason be aware that not all signals work for us. We may be doing something wrong, but SIGCONT doesn't work.

We have benchmarked pausing threads this way and this method was 5x faster than using mutexes and condition variables.

Here is some code that uses this technique.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文