使用计时器将信号发送到被阻塞的线程

时间:2016-01-29 13:41:14

标签: multithreading pthreads signals

我在同一个核心上运行两个进程(进程A和B)。进程B是多线程的,其中一个线程正在向下一个线程发送信号以唤醒它并开始工作。一次,只有一个进程B的线程可以在公共核心上运行。

**//Process A** 
#define _GNU_SOURCE
#include <sched.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>

int main(int argc, char const *argv[])
{
    struct timeval tval_result;
    cpu_set_t my_set;        
    CPU_ZERO(&my_set);       
    CPU_SET(2, &my_set);     
    sched_setaffinity(0, sizeof(cpu_set_t), &my_set);
    long int loopNum;
    while(1)
    {
        gettimeofday(&tval_result, NULL);
            printf("Dummy Time elapsed: %ld.%06ld\n", (long int)tval_result.tv_sec, (long int)tval_result.tv_usec);
        //for(loopNum = 1; loopNum <= 100000; loopNum++);
            //printf("Dummy!!! # \n");
    }

    return 0;
}        

以下是流程B的代码。

//Import 
#define _GNU_SOURCE
#include <sched.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#define NUM_THREADS 100

//global variables

pthread_cond_t      condA[NUM_THREADS+1]  = PTHREAD_COND_INITIALIZER;
pthread_cond_t      condB  = PTHREAD_COND_INITIALIZER;
pthread_mutex_t     mutex  = PTHREAD_MUTEX_INITIALIZER;

pthread_t tid[NUM_THREADS];
int state = 0;

void *threadA(void *data_)
{
    int i = 0, rValue;
    long int loopNum;

    int turn = (intptr_t)data_;

    struct timeval tval_result;
    while(1)
    {
        cpu_set_t my_set;        
        CPU_ZERO(&my_set);       
        CPU_SET(2, &my_set);     
        sched_setaffinity(0, sizeof(cpu_set_t), &my_set);
        /* Wait for state A */
        pthread_mutex_lock(&mutex);
        // while (state != STATE_A)
        if(state != turn)
        {
            pthread_cond_wait(&condA[turn], &mutex);
        }
        pthread_mutex_unlock(&mutex);

        //do stuff
        gettimeofday(&tval_result, NULL);
        printf("Time elapsed: %ld.%06ld\n", (long int)tval_result.tv_sec, (long int)tval_result.tv_usec);
        //for(loopNum = 1; loopNum <= 10000000000; loopNum++);
        //printf("Hello Thread # %d\n", turn);

        /* Set state TRUE for next thread */
        pthread_mutex_lock(&mutex);
        state = (state +1)%NUM_THREADS;
        pthread_cond_signal(&condA[state]);
        pthread_mutex_unlock(&mutex);

    }

}

int main(int argc, char *argv[])
{
    int data = 0;
    int err;

    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));
        else
            printf("\n Thread created successfully\n");

        data++;
    }

    pthread_exit(NULL);

}

我想在进程A的线程之间插入进程B的执行很短的持续时间(小于1微秒)。因此,当进程B的线程i完成其工作时,它将信号发送到下一个线程i + 1并且在其间,我希望进程A到来。这应该在执行的其余部分重复进行。

当我在程序上运行时,进程A无法进入进程B的线程之间。是否有任何机制可以通过某个计时器发送信号,以便信号不会立即到达下一个线程(和因此,进程A在两个连续的线程之间出现一段时间。)

1 个答案:

答案 0 :(得分:1)

您无法在该级别强制执行Linux调度程序。 你必须“发出信号”进程A,然后让它“发出信号”另一个B线程。

但是“信号”可能是一个用户空间机制,就像在共享内存中的变量上旋转一样。

我建议你首先用正常信号(通过内核)尝试它,看看延迟是否足够好。只有当它太长时,才能在用户空间中进行旋转。

不要指望所有这些总是在1us以下。无论是旋转还是使用内核信令,你都可能会得到大量的抖动,不得不将进程从核心移开以减少它。

对于内核信令,您也可以使用套接字,管道,futexes ......

现在我的问题是,如果你在一个核心上运行所有这些,就像你说的那样,为什么不将它作为单个线程运行 - 只需要一个线程调用B1,然后是A,然后是B2?