64ビットのsetjmp/longjmp

私は64ビットUbuntuで setjmp/longjmp を使用しようとしましたが、正しく動作しませんが、32ビットUbuntuで問題なく動作します。どんなアイデア、何が起こっている。以下は実行しようとしていたコードです。

64ビットでは、longjmpの後ろに戻るポイントでハングします。 setcontext に関するウィキペディアの記事では、64ビットで正しく動作しないと言われています。 setjmp についても同じ問題がありますか?実際には、 setcontext の問題を避けるために setjmp を使用しようとしていましたが、64ビットで同じ問題があるようです。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#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
Ed Healは、何らかの目的でsetjmpとlongjmpの機能をテストしていました。これは単なる実験コードです。
追加された 著者 MetallicPriest,
C にはこれに C ++ というものは何もありません。
追加された 著者 Alok Save,
a)あなたが longjmp などを必要とせず、b) goto を必要としないようにコードを書き直すことを検討しましたか?
追加された 著者 Ed Heal,
あなたは、「正しく動作しません」という意味を説明する必要があります。
追加された 著者 Alan Stokes,

2 答え

スレッドごとに個別の jmp_buf を使用する必要があります。現在、あなたは同じものを再使用しています。

5
追加された
ああ、優秀な点。修正して見てください: - p!
追加された 著者 MetallicPriest,
ありがとうアラン。それがまさに問題でした。今すぐうまく動作します:-p!
追加された 著者 MetallicPriest,
ええ、一般的に、ジャンプバッファを静的変数として持つことにはあまり意味がありません。それを使用する関数のスタックに宣言するだけです。
追加された 著者 Jens Gustedt,

ローカル変数 volatile を宣言せずに、 setjmp()を呼び出した後にそれらを変更すると、 longjmp ()

(C99規格では7.13.2.1/3)。

しかし、 si tid は変更されていないので、ここでは適用されないようです。

1
追加された
興味深い、それを調べます。
追加された 著者 MetallicPriest,
確かにそうではありません。 setjmp の後で tid si
追加された 著者 jpalecek,
@jpalecekうーん、それは良い点だ。
追加された 著者 Alan Stokes,
追加された 著者 Alexey Frunze,