| 网站首页 | 业界新闻 | 群组 | 交易 | 人才 | 下载频道 | 博客 | 代码贴 | 编程论坛
共有 72 人关注过本帖, 1 人收藏
标题:makecontext实现协程遇到问题
只看楼主 加入收藏
gsw9393
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2018-12-7
  问题点数:0  回复次数:0   
makecontext实现协程遇到问题

```

#include <unistd.h>
#include <ucontext.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <sys/time.h>

#define INTERVAL 200000
#define DELAY 50000000
#define BOUND 15
#define STACKSIZE 4096
#define THREADS 16

ucontext_t context[THREADS], myCleanup, myMain;
int status[THREADS];
char myMainArr[STACKSIZE];
struct itimerval clocktimer;
int totalThreads = 0;
int currentThread = 0;
long pos[THREADS];

void cleanup(void);
void task1(int);
void task2(int);
void signalHandler(int signal);

int main( void )
{
    char *myStack[THREADS];
    char myCleanupStack[STACKSIZE];
    int j;
    /* initialize timer to send signal every 200 ms */
    clocktimer.it_value.tv_sec = 0;
    clocktimer.it_value.tv_usec = INTERVAL;
    clocktimer.it_interval.tv_sec = 0;
    clocktimer.it_interval.tv_usec = INTERVAL;
    setitimer(ITIMER_REAL, &clocktimer, 0);
    sigset(SIGALRM, signalHandler);

    getcontext(&myCleanup);
    myCleanup.uc_stack.ss_sp = myCleanupStack;
    myCleanup.uc_stack.ss_size = STACKSIZE;
    myCleanup.uc_link = &myMain;
    makecontext(&myCleanup, (void (*)(void))cleanup, 0);
    // set up your cleanup context here.


    for (j = 0; j < THREADS; j++)
    {

        getcontext(&context[j]); // makecontext must get a context from getcontext
        myStack[j] = (char *)malloc(sizeof(char) * STACKSIZE);
        context[j].uc_stack.ss_sp = &myStack[j];
        context[j].uc_stack.ss_size = STACKSIZE;
        context[j].uc_link = &myCleanup;
        // 1: ready, 2: running 0:finished
        pos[j] = j;

        if (j % 2 == 0){
            printf("Creating task1 thread[%d]\n", j);
            makecontext(&context[j], (void (*)(void))task1, 1, pos[j]);
            // map the corresponding context to task1
        }
        else
        {
            printf("Creating task2 thread[%d]\n", j);
            makecontext(&context[j], (void (*)(void))task2, 1, pos[j]);
            // map the corresponding context to task2
        }
        // you may want to keep the status of each thread using the
        // following array. 1 means ready to execute, 2 means currently
        // executing, 0 means it has finished execution.
        status[j] = 1;
        // You can keep track of the number of task1 and task2 threads
        // using totalThreads.  When totalThreads is equal to 0, all
        // tasks have finished and you can return to the main thread.
        totalThreads++;
    }
    printf("Running threads\n");

    status[currentThread] = 2;
    swapcontext(&myMain, &context[currentThread]);
    // start running your threads here.

    for(j = 0; j < THREADS; j++)
    {
        free(myStack[j]);
    }
    printf("Program terminates successfully\n");
    return 0;
}

void signalHandler(int signal)
{

    //int nextThread;
    int prev, i;
    printf("Get a signal\n");
    //int tmp = currentThread;
    if (status[currentThread] != 0) {
        //printf("status %d is %d\n", currentThread, status[currentThread]);
        status[currentThread] = 1;
    }
    i = (currentThread + 1) % THREADS;
    for (; i != currentThread; i = ((i + 1) % THREADS)) {
        if (status[i] == 1) {
            break;
        }
    }

    prev = currentThread;
    currentThread = i;
    status[currentThread] = 2;
    //printf("prev is: %d  status is: %d   currentThread is: %d status is:%d\n", prev, status[prev], currentThread, status[currentThread]);
    swapcontext(&context[prev], &context[currentThread]);

    return;
}

void cleanup() {

    int prev;
    status[currentThread] = 0;
    totalThreads--;
    if (totalThreads == 0) return;

    int i = currentThread;
    for (i = (currentThread + 1) % THREADS; i != currentThread; i = (i + 1) % THREADS) {
        if (status[i] == 1) {
            break;
        }
    }

    prev = currentThread;
    currentThread = i;
    status[currentThread] = 2;
    swapcontext(&context[prev], &context[currentThread]);

    return;
}

void task1(int tid)
{
    // self explanatory
    int i, count = 1;
    while(count <= BOUND){
        for (i = 0; i < DELAY; i++);
        printf ("task1 [tid = %d]: count = %d\n", tid, count++);
    }
}
void task2( int tid)
{
    // self explanatory
    int i, count = 1;
    while(count <= BOUND){
        for (i = 0; i < DELAY/2; i++);
        printf ("task2 [tid = %d]: count = %d\n", tid, count++);
    }
}

```

代码如上所述,执行的时候遇到segment fault错误,第一次使用makecontext,不知道哪的问题,调试不出来,望大神支招。

代码实现的意思是:
模拟16个线程执行task1和task2,中间会有alarm信号中断,中断的时候会使用makecontext保存当前上下文,执行下一个上下文。

其中status保存当前线程的状态,0为结束,1为可以执行,2为执行中

最后,执行完成的线程会调用cleanup函数设置status为0,然后,alarm信号中断的时候不会选取该线程执行。

请指教。
2018-12-07 16:44







关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.026443 second(s), 8 queries.
Copyright©2004-2018, BCCN.NET, All Rights Reserved