-1

プログラムをコンパイルしようとすると、次のエラーが発生します。

Field '__jmpbuf' could not be resolved

何時間も解決策を探しましたが、原因がどこにあるのかわかりません。

このThread.hファイルには、クラスのヘッダーが含まれています。プライベートメンバーがあります:

sigjmp_buf _env;

実装は Thread.cpp 内にあります。

#include "Thread.h"
#include <setjmp.h>
#include "translateAdd.h"
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>

#define COUNTER_INIT -1

int Thread::_idCounter = COUNTER_INIT;

Thread::Thread(void (*threadsFunc)(void))
: threadsFunction(threadsFunc), _stack(new char[STACK_SIZE]), _quantums(1)
{
      address_t sp, pc;

      sp = (address_t)_stack + STACK_SIZE - sizeof(address_t);
      pc = (address_t)threadsFunc;
      // set environment for later return
      sigsetjmp(_env, 1);
      (_env->__jmpbuf)[JB_SP] = translate_address(sp);
      (_env->__jmpbuf)[JB_PC] = translate_address(pc);
      sigemptyset(&_env->__saved_mask);

    _id = ++_idCounter;

    _state = READY;

}

編集:ubuntu 32ビットでEclipseをIDEとして使用する

編集:私のマシンでコンパイルされない別の完全な例:

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

#define SECOND 1000000
#define STACK_SIZE 4096

char stack1[STACK_SIZE];
char stack2[STACK_SIZE];

sigjmp_buf env[2];

#ifdef __x86_64__
/* code for 64 bit Intel arch */

typedef unsigned long address_t;
#define JB_SP 6
#define JB_PC 7

/* A translation is required when using an address of a variable.
   Use this as a black box in your code. */
address_t translate_address(address_t addr)
{
    address_t ret;
    asm volatile("xor    %%fs:0x30,%0\n"
        "rol    $0x11,%0\n"
                 : "=g" (ret)
                 : "0" (addr));
    return ret;
}

#else
/* code for 32 bit Intel arch */

typedef unsigned int address_t;
#define JB_SP 4
#define JB_PC 5 

/* A translation is required when using an address of a variable.
   Use this as a black box in your code. */
address_t translate_address(address_t addr)
{
    address_t ret;
    asm volatile("xor    %%gs:0x18,%0\n"
        "rol    $0x9,%0\n"
                 : "=g" (ret)
                 : "0" (addr));
    return ret;
}

#endif

void switchThreads(void)
{
  static int currentThread = 0;

  int ret_val = sigsetjmp(env[currentThread],1);
  printf("SWITCH: ret_val=%d\n", ret_val); 
  if (ret_val == 1) {
      return;
  }
  currentThread = 1 - currentThread;
  siglongjmp(env[currentThread],1);
}

void f(void)
{
  int i = 0;
  while(1){
    ++i;
    printf("in f (%d)\n",i);
    if (i % 3 == 0) {
      printf("f: switching\n");
      switchThreads();
    }
    usleep(SECOND);
  }
}

void g(void)
{
  int i = 0;
  while(1){
    ++i;
    printf("in g (%d)\n",i);
    if (i % 5 == 0) {
      printf("g: switching\n");
      switchThreads();
    }
    usleep(SECOND);
  }
}

void setup(void)
{
  address_t sp, pc;

  sp = (address_t)stack1 + STACK_SIZE - sizeof(address_t);
  pc = (address_t)f;
  sigsetjmp(env[0], 1);
  (env[0]->__jmpbuf)[JB_SP] = translate_address(sp);
  (env[0]->__jmpbuf)[JB_PC] = translate_address(pc);
  sigemptyset(&env[0]->__saved_mask);     

  sp = (address_t)stack2 + STACK_SIZE - sizeof(address_t);
  pc = (address_t)g;
  sigsetjmp(env[1], 1);
  (env[1]->__jmpbuf)[JB_SP] = translate_address(sp);
  (env[1]->__jmpbuf)[JB_PC] = translate_address(pc);
  sigemptyset(&env[1]->__saved_mask);         
}

int main(void)
{
  setup();      
  siglongjmp(env[0], 1);
  return 0;
}
4

1 に答える 1

0

本当に内部フィールドを使用する必要がある場合 (システム上のコンパイラでのみ有効です)、型を確認する必要があります。

typedef struct __jmp_buf_tag sigjmp_buf[1];

つまりsigjmp_buf、これはポインターではなく、単一の構造体を含む配列です。したがって、構造体の通常の配列のように使用します。

sigjmp_buf _env;

_env[0].__jmpbuf[x] = y;

この構造体の内部フィールドを使用しないことを強くお勧めします。Linuxには、協調スレッドを簡素化するための他の機能があります(これは、実装しているようです)。

于 2013-04-14T08:26:36.497 に答える