gpt4 book ai didi

c - 带有 sigev_notify = SIGEV_THREAD_ID 方法的 POSIX 计时器

转载 作者:太空狗 更新时间:2023-10-29 12:12:46 24 4
gpt4 key购买 nike

在多线程场景中,我正在尝试实现一个 POSIX 计时器,其中在计时器到期时应唤醒同一进程的下一个线程(一次只有一个线程在运行,所有其他线程都处于阻塞状态)。在计时器中,我正在使用 sigev_notify = SIGEV_THREAD_ID,因为我既不希望任何处理程序为信号提供服务,也不希望在计时器到期后创建新线程。

//Import
#define _GNU_SOURCE
#define _POSIX_C_SOURCE 199309
#include <sched.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <syscall.h>
#define NUM_THREADS 10

#define CLOCKID CLOCK_REALTIME

int ret;
//pthread_cond_t condA[NUM_THREADS+1] = PTHREAD_COND_INITIALIZER;
pthread_cond_t condA = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

sem_t sem[NUM_THREADS];
sem_t mute;

timer_t timer1;
pthread_t tid[NUM_THREADS];
int state = 0;
int thread_count = 1;
int arr_tid[NUM_THREADS];
struct itimerspec new_value, old_value;

struct sigaction action;
struct sigevent sevent;
sigset_t set;
int signum = SIGALRM;

void *threadA(void *data_)
{
cpu_set_t my_set;
CPU_ZERO(&my_set);
CPU_SET(2, &my_set);
sched_setaffinity(0, sizeof(cpu_set_t), &my_set);

//struct itimerspec new_value, old_value;

int i = 0, value;
int sid;
FILE *fp;
fp=fopen("ipc.out","a");

long int loopNum;
int turn = (intptr_t)data_;
struct timespec tval_result, tval_result2;

if(thread_count < NUM_THREADS)
{
thread_count++;
sid = syscall(SYS_gettid);
arr_tid[turn] = sid;
fprintf(fp,"thread_%d %d\n", turn, sid);
//printf("Blocked %d ->%d\n", turn, thread_count );
pthread_mutex_lock(&mutex);
pthread_cond_wait(&condA, &mutex);
pthread_mutex_unlock(&mutex);
}
else
{
arr_tid[turn] = syscall(SYS_gettid);
}

for (value = 0; value < NUM_THREADS; ++value)
{
printf("%d\n",arr_tid[value] );
}
//printf("rpg\n");
pthread_mutex_lock(&mutex);
pthread_cond_broadcast(&condA);
pthread_mutex_unlock(&mutex);
//printf("unblocked\n");
fclose(fp);

if (turn > 0)
{
if (sigwait (&set, &signum) == -1)
perror ("sigwait");
//sleep(1);
//printf("thread %d is sleeping\n", turn);
}
while(1)
{
ret = sem_wait(&sem[turn]);
if (ret)
{
printf("Error in Sem Post\n");
}
//printf("this isn't the end of the world!!!\n");
sevent.sigev_notify = SIGEV_THREAD_ID;
sevent._sigev_un._tid = arr_tid[(turn+1)%10];
sevent.sigev_signo = signum;

sigemptyset(&set);
sigaddset(&set, signum);
sigprocmask(SIG_BLOCK, &set, NULL);

printf("Thread # -> %d\n", turn);
clock_gettime(CLOCKID, &tval_result);
do
{
clock_gettime(CLOCKID, &tval_result2);
} while( (tval_result2.tv_sec - tval_result.tv_sec)*1000000000+(tval_result2.tv_nsec - tval_result.tv_nsec)<=12000);
//printf("Timestamp : %ld %ld\n", tval_result2.tv_sec, tval_result2.tv_nsec);
// printf("Before creating timer\n");

new_value.it_interval.tv_sec = 0;
new_value.it_interval.tv_nsec = 0;
new_value.it_value.tv_sec = 0;
new_value.it_value.tv_nsec = 15000;
printf("next thread to be signalled %d\n", arr_tid[turn+1]);
if (timer_settime (timer1, 0, &new_value, NULL) == -1)
perror ("timer_settime");
printf("yy\n");
ret = sem_post(&sem[(state+1)%NUM_THREADS]);
if (ret)
{
printf("Error in Sem Post\n");
}
state++;
//printf("yy\n");
//sleep(1);
if (sigwait (&set, &signum) == -1)
perror ("sigwait");
}
}

int main(int argc, char *argv[])
{
int data = 0;
int err, i;
int sid = syscall(SYS_gettid);
//struct itimerspec new_value, old_value;

FILE *fp;
fp=fopen("ipc.out","a");
fprintf(fp,"Mainthread %d\n",sid);
fclose(fp);
if (timer_create (CLOCK_REALTIME, &sevent, &timer1) == -1)
perror ("timer_create");

sem_init(&sem[0], 0, 1);
//sem_init(&sem[1], 0, 0);
//sem_init(&sem[2], 0, 0);
for ( i = 1; i < NUM_THREADS; ++i)
{
sem_init(&sem[i], 0, 0);
}
while(data < NUM_THREADS)
{
//create our threads
err = pthread_create(&tid[data], NULL, threadA, (void *)(intptr_t)data);
if(err != 0)
printf("\ncan't create thread :[%s]", strerror(err));
data++;
}
pthread_exit(NULL);
}

编译: $ gcc filename.c -lrt -lpthread

我使用信号量来同步线程,以便线程按特定顺序执行。

我没有得到想要的输出。应该是在 15 微秒后定时器到期,下一个线程应该被唤醒,但它没有发生。我已经使用 sigwait() 来阻止线程。有没有其他方法可以阻止线程并使用计时器唤醒它们?signum 中可以分配哪些信号?我可以使用 pthread_cond_signal() 而不是 SIGALRM 吗?

最佳答案

嗯..好的。

将信号量初始化为一个单位并让所有线程等待它。

如果一个线程获得了该单元,它会将当前的“startTime”时间存储在一些静态/全局/任何内容中(安全,因为一次只有一个线程可以拥有该 semaunit),然后离开去做它的事情/秒。完成后,它会获取当前的“endTime”时间,将花费的时间计算为“endTime-startTime”,并从所需的线程间间隔时间中减去它 - 现在下一个线程可以运行之前还剩下多长时间 - '剩余间隔'。如果 remainingInterval 小于 0,则将其设为 0。它将 remainingInterval 转换为 usleep()/Sleep() 所需的任何单位并休眠那么长时间,然后将其单位发送到信号量。然后另一个线程可以运行,刚刚完成其工作的线程可以循环并再次等待信号量,如果它愿意的话。

无论多长时间/排序/无论作业需要多长时间,都不可能同时运行一个以上的线程。

不需要显式计时器、互斥量、condvar 等,只需一个信号量。

关于c - 带有 sigev_notify = SIGEV_THREAD_ID 方法的 POSIX 计时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36542368/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com