64 bit'de setjmp/longjmp

64 bit Ubuntu'da setjmp/longjmp kullanmayı denedim, ancak düzgün çalışmıyor, 32 bit Ubuntu'da çalışıyor. Herhangi bir fikir, ne oluyor? Aşağıdaki kod, yürütmeye çalışıyordum.

64 bitte, longjmp'ten sonra geri döneceği noktada askıda kalıyor. Wikipedia'nin setcontext hakkındaki makalesinde, 64 bit ile düzgün çalışmadığını söylüyor. setjmp ile aynı sorunu yaşıyor muyuz? Infact, setcontext ile ilgili problemden kaçınmak için setjmp 'i kullanmaya çalışıyordum, ancak 64 bit'de aynı sorun var gibi görünüyor.

#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, sadece bir amaç için setjmp ve longjmp işlevlerini test ediyordu. Bu sadece deneysel bir koddur.
katma yazar MetallicPriest, kaynak
C 'yi yeniden etiketlemek için C ++ diye bir şey yoktur.
katma yazar Alok Save, kaynak
Kodu yeniden yazmayı düşündünüz mü? A) longjmp vs gerekmiyor ve b) goto 'a ihtiyacınız yok mu?
katma yazar Ed Heal, kaynak
"Düzgün çalışmıyor" ile ne demek istediğini açıklaman gerek.
katma yazar Alan Stokes, kaynak

2 cevap

Her iş parçacığı için ayrı bir jmp_buf kullanmanız gerekir. Şu anda aynı olanı yeniden kullanıyorsunuz.

5
katma
Ah, mükemmel nokta. Düzeltecek ve daha sonra göreceksiniz: - p!
katma yazar MetallicPriest, kaynak
Teşekkürler Alan. Tam olarak sorun buydu. Şimdi iyi çalışıyor: -p!
katma yazar MetallicPriest, kaynak
Evet, genelde statik bir değişken olarak bir atlama tamponuna sahip olmanın pek bir anlamı yoktur. Sadece onu kullanan işlevin yığında bildir.
katma yazar Jens Gustedt, kaynak

Yerel değişkenlerinizi volatile olarak bildirmezseniz ve setjmp() 'i çağırdıktan sonra bunları değiştirirseniz, longjmp aradığınızda korunurlar.() .

(C99 standardında 7.13.2.1/3.)

Fakat burada geçerli görünmüyor, çünkü si ve tid değişmez.

1
katma
İlginç, içine bakacak.
katma yazar MetallicPriest, kaynak
Kesinlikle değil. setjmp 'ten sonra tid ve si değiştirilmez.
katma yazar jpalecek, kaynak
@jpalecek Hmm, bu iyi bir nokta.
katma yazar Alan Stokes, kaynak
Singhle UNIX Spec, bunu da açıklar .
katma yazar Alexey Frunze, kaynak