2013-10-06 55 views
1

基本上我正在嘗試的是在具有上下文切換的單個線程上模擬多線程。我每10微秒設置一次鬧鐘,並將上下文從一個切換到另一個線程。問題在於,大約有五分之一的運行結束時會在報警完成swapcontext後發生seg故障,至少這是我用gdb跟蹤它的地方。報警處理程序中的swapcontext之後的分段錯誤

這裏是我的源文件 main.c中

#include "umt.h" 

void f() 
{ 
    int x = 10; 
    printf("starting thread\n"); 
    while(x) 
    { 
     printf("thread %d\n", x); 
     sleep(1); 
     x--; 
    } 

} 

int main() 
{ 
    int x = 0, y, z; 
    umt_init(); 
    y = umt_thread_create(f); 
    printf("starting main\n"); 
    if(y == 0) 
    { 
     printf("Problems with creating thread\n"); 
     return; 
    } 
    x = 10; 
    z = 1; 
    while(x) 
    { 
     printf("main\n"); 
     x--; 
    } 
    umt_thread_join(y); 
    printf("done waiting\n"); 
    return 0; 
} 

UMT.h

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

#define TRUE  1 
#define FALSE  0 

typedef struct _umt_thread 
{ 
    int thread_id; 
    ucontext_t context; 
    void (*handler)(void); 
    int hasFinished; 
}umt_thread, *pumt_thread; 

void umt_init(); 

int umt_thread_create(void (*handler)(void)); 

void umt_thread_join(int thr); 

和umt.c

#include "umt.h" 

#define MAIN_CONTEXT  0 
#define STACK_SIZE   1638400 

int currentThread; 
char threadpool[15]; 

pumt_thread threads; 

void signal_thread_finish(); 

void thread_handler() 
{ 
    threads[currentThread].handler(); 
    signal_thread_finish(); 
} 

void thread_scheduler(); 

void signal_thread_finish() 
{ 
    threads[currentThread].hasFinished = TRUE; 
    threadpool[currentThread] = 0; 
    thread_scheduler(); 
} 

void thread_scheduler() 
{ 
    int nextThread = 0, curThread = 0; 
    int x = 0; 
    ucontext_t *con1, *con2; 

    nextThread = currentThread + 1; 
    while(1) 
    { 
     if(nextThread == 15) 
      nextThread = 0; 
     if(nextThread == currentThread) 
      break; 
     if(threadpool[nextThread] == 1) 
      break; 
     nextThread++; 
    } 

    if(nextThread == currentThread) 
     return; 
    curThread = currentThread; 
    currentThread = nextThread; 
    con1 = &(threads[curThread].context); 
    con2 = &(threads[nextThread].context); 
    x = swapcontext(con1, con2); 
} 

void umt_init() 
{ 
    ucontext_t context; 
    struct itimerval mytimer; 
    int i; 
    stack_t new_stack; 

    getcontext(&context); 

    threads = (pumt_thread)malloc(sizeof(umt_thread) * 15); 
    threads[MAIN_CONTEXT].thread_id = MAIN_CONTEXT; 
    threads[MAIN_CONTEXT].context = context; 

    threadpool[MAIN_CONTEXT] = 1; 
    for(i = 1;i<15;i++) 
    { 
     threadpool[i] = 0; 
    } 

    currentThread = 0; 

    new_stack.ss_sp = (char*)malloc(STACK_SIZE); 
    new_stack.ss_size = STACK_SIZE; 
    new_stack.ss_flags = 0; 
    i = sigaltstack(&new_stack, NULL); 
    if(i != 0) 
    { 
     printf("problems assigning new stack for signaling\n"); 
    } 

    signal(SIGALRM, thread_scheduler); 
    mytimer.it_interval.tv_sec = 0; 
    mytimer.it_interval.tv_usec = 10; 
    mytimer.it_value.tv_sec = 0; 
    mytimer.it_value.tv_usec = 5; 
    setitimer(ITIMER_REAL, &mytimer, 0); 
} 

int umt_thread_create(void (*handler)(void)) 
{ 
    ucontext_t context; 
    int i, pos; 

    for(i = 1;i<15;i++) 
    { 
     if(threadpool[i] == 0) 
     { 
      pos = i; 
      break; 
     } 
    } 
    if(i == 15) 
    { 
     printf("No empty space in the threadpool\n"); 
     return -1; 
    } 

    if(getcontext(&context) == -1) 
    { 
     printf("Problems getting context\n"); 
     return 0; 
    } 
    context.uc_link = 0;//&(threads[MAIN_CONTEXT].context); 
    context.uc_stack.ss_sp = (char*)malloc(STACK_SIZE); 
    if(context.uc_stack.ss_sp == NULL) 
    { 
     printf("Problems with allocating stack\n"); 
    } 
    context.uc_stack.ss_size = STACK_SIZE; 
    context.uc_stack.ss_flags = 0; 
    makecontext(&context, thread_handler, 0); 

    threads[pos].thread_id = pos; 
    threads[pos].context = context; 
    threads[pos].handler = handler; 
    threads[pos].hasFinished = FALSE; 

    threadpool[pos] = 1; 

    printf("Created thread on pos %d\n", pos); 

    return pos; 
} 

void umt_thread_join(int tid) 
{ 
    while(!threads[tid].hasFinished) 
    { 
    } 
} 

我嘗試了很多組合,並試圖追蹤通過指令,但不能得出一個結論或想法,以什麼可能會導致此seg錯誤。由於

回答

0

很少有什麼問題我看到的(有些是到段錯誤有關+其他一些評論)

  1. 您調度(thread_scheduler)應該是一個關鍵部分,如您應該阻止任何報警信號(或忽略它們),以便線程池的處理以不會破壞線程池的方式完成。你可以使用sigprocmask或一個易變的布爾變量來消除報警(注意這與用戶線程互斥不一樣,只是內部同步到你的調度邏輯)

  2. 你的時鐘滴答的方式太快恕我直言,這是微秒,而不是毫秒,所以tv_usec的1000微秒可能對測試更有意義。

  3. 小堆棧大小也可能導致seg故障,但看起來你的堆棧足夠大。

p.s.有一種更好的方式來處理連接,你現在已經浪費了大量的CPU週期,爲什麼不簡單地切換到一個稱爲連接的線程,直到它所等待的線程終止?