2011-10-28 165 views
0

我試過在64位的Ubuntu上使用setjmp/longjmp,但是它不能正常工作,而它在32位Ubuntu中可以正常工作。任何想法,發生了什麼。以下是我試圖執行的代碼。64位的setjmp/longjmp

在64位上,它掛起,在longjmp之後它返回的位置。在維基百科關於setcontext的文章中,它表示它無法在64位下正常工作。我們是否有與setjmp相同的問題?事實上,我試圖使用setjmp,以避免setcontext的問題,但它似乎在64位上有相同的問題。

#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <string.h> 
#include <string> 
#include <setjmp.h> 

#define NOFTHREADS 2 

#define DATASIZE  500 
#define SETSIZE   (DATASIZE/NOFTHREADS) 

int data[DATASIZE]; 
pthread_mutex_t sumMutex; 
pthread_mutex_t prodMutex; 
int sum; 
double prod; 
static jmp_buf buf; 
int jmp_onced[NOFTHREADS+1]; 

#define lock pthread_mutex_lock 
#define unlock pthread_mutex_unlock 

void *SumThread(void *pParam) 
{ 
    unsigned int tid = *((unsigned int*)(pParam)); 
    int si = tid * SETSIZE; 
    int i, j, oi, local_sum; 
    double local_prod; 
    pthread_attr_t attr; 

    if (setjmp(buf)) 
    printf("%d: tid %u back! <<<<<<<<<\n", getpid(), tid); 
    if (jmp_onced[tid]) 
    goto end_this; 

    printf("%d: >>>>>>>>>>>>> tid %u, starting <<<<<<<<<<<<\n\n", getpid(), tid); 

    for(oi = 0; oi < 5; oi++) 
    { 
    local_sum = 0; 
    local_prod = 1.0; 
    for(i = si; i < (si+SETSIZE); i++) 
    { 
     local_sum = local_sum + data[i]; 
     if (data[i ]) 
     local_prod *= 0.005 * data[i]; 
    } 

    lock(&sumMutex); 
    sum += local_sum; 
    unlock(&sumMutex); 

    lock(&prodMutex); 
    prod *= local_prod; 
    unlock(&prodMutex); 
    } 

    printf("%d: !!!!!!!!!!!!!!tid %u done!!!!!!!!!!!!!!\n\n", getpid(), tid); 
    jmp_onced[tid] = 1; 
    longjmp(buf, 1); 

end_this: 
    printf("%d: ****** tid %u is exiting! ******\n", getpid(), tid); 
    return 0; 
} 

void real_main() 
{ 
    pthread_t hThread[NOFTHREADS]; 
    int index[NOFTHREADS]; 
    int i, pid, err; 
    time_t t1 = time(NULL); 

    printf("%d: Inside real_main, primary thread = %lx!\n", getpid(), pthread_self()); 
    for(i = 0; i < NOFTHREADS; i++) 
    { 
     index[i] = i; 
     pthread_create(&hThread[i], NULL, SumThread, &index[i]); 
    } 
    for(i = 0; i < NOFTHREADS; i++) 
     pthread_join(hThread[i], NULL); 

    printf("Sum of numbers from 1 to %d is %d\n", DATASIZE, sum); 
    printf("Prod of numbers from 1 to %d is %g\n", DATASIZE, prod); 
    printf("\n\n[[[[[ %d(child of %d): Time taken = %lu seconds ]]]]]\n\n", getpid(), getppid(), time(NULL) - t1); 
} 

int main(int argc, char **argv) 
{ 
    int pid, i, err; 

    printf("size of long is %d\n", sizeof(long)); 

    sumMutex = PTHREAD_MUTEX_INITIALIZER; 
    prodMutex = PTHREAD_MUTEX_INITIALIZER; 
    printf("pid = %d, @sumMutex = %lx, @prodMutex = %lx\n", getpid(), (long)&sumMutex, (long)&prodMutex); 

    for(i = 0; i < DATASIZE; i++) 
    data[i] = i+1; 

    switch(pid = fork()) 
    { 
    case -1: 
    printf("fork failed"); 
    break; 
    case 0: // Child 
    printf("Child pid() = %d\n", getpid()); 
    real_main(); 
    break; 
    default:// Leader 
    printf("Parent pid() = %d\n", getpid()); 
    real_main(); 
    } 

    printf("getppid() = %d, getpid() = %d\n", getppid(), getpid()); 
    return 0; 
} 
+0

重新標記'C'在這裏沒有任何'C++'。 –

+1

你需要解釋你的意思是「它無法正常工作」。 –

+0

你有沒有考慮重寫代碼,以便a)你不需要'longjmp'等等b)你不需要'goto'? –

回答

5

您需要爲每個線程使用單獨的jmp_buf。目前您正在重複使用同一個。

+0

啊,很好的一點。將解決,然後看到:-P! – MetallicPriest

+0

謝謝Alan。這正是問題所在。現在它的工作很好:-p! – MetallicPriest

+2

是的,一般來說,將跳轉緩衝區作爲靜態變量沒有多大意義。只需在使用它的函數中將其聲明在堆棧中。 –

1

如果你不聲明你的局部變量volatile,而你打電話setjmp()後改變他們,那麼他們不能保證當你調用longjmp()被保存下來。

(7.13.2.1/3在C99標準。)

但這似乎並不適用於此,因爲sitid不會改變。

+0

有趣的,將研究它。 – MetallicPriest

+1

當然不是。 'tid'和'si'在'setjmp'後面沒有改變 – jpalecek

+0

@jpalecek嗯,這是一個很好的觀點。 –