Могу ли я получить адрес стека потока из pthread_self () - PullRequest
2 голосов
/ 04 января 2012

Я хочу получить адрес стека потока через некоторую функцию, в которую мы можем передать pthread_self () . Является ли это возможным? Причина, по которой я это делаю, заключается в том, что я хочу написать свой собственный назначенный идентификатор потока для потока где-то в его стеке. Я могу писать ближе к концу стека (конец стековой памяти, а не текущий адрес стека. Конечно, мы можем ожидать, что приложение не достигнет дна стека и, следовательно, будет использовать пространство оттуда).

Другими словами, я хочу использовать стек потоков для размещения своего рода локальной переменной потока. Итак, у нас есть какая-то функция, подобная следующей, предоставляемой pthread?

stack_address = stack_address_for_thread( pthread_self() );

Я могу использовать синтаксис для локальных переменных потоков с помощью gcc для этой цели, но я нахожусь в ситуации, когда я не могу их использовать.

Ответы [ 4 ]

6 голосов
/ 04 января 2012

Возможно, лучше использовать pthread_key_create и pthread_key_getspecific и позволить реализации беспокоиться об этих деталях.

Хороший пример использования здесь:

pthread_key_create

Редактировать: Я должен уточнить - я предлагаю вам использовать предоставленный libpthread метод создания локальной информации о потоке, вместо того, чтобы катить свою собственную, помещая что-то в конец стека, где, возможно, ваша информация может быть потеряна.

2 голосов
/ 04 января 2012

Я хочу написать свой собственный назначенный идентификатор потока для потока

Есть несколько способов добиться этого.Самый очевидный:

__thread int my_id;

Я могу использовать синтаксис для локальных переменных потока с помощью gcc для этой цели, но я нахожусь в ситуации, когда не могу их использовать.

Вам нужно объяснить , почему вы не можете использовать локальные потоки.Высоки шансы, что другие решения, такие как pthread_getattr_np, также не будут работать.

2 голосов
/ 04 января 2012

В GCC проще объявить локальные переменные вашего потока с помощью ключевого слова __ thread , например

  __thread int i;
  extern __thread struct state s;
  static __thread char *p;

Это специфично для GCC (но я предполагаю, что clang также имеет его, и в новейших стандартах C ++ и будущих C есть что-то похожее), но менее хрупкое, чем хаки для указателей на основе upeon pthread_self() (и должно быть немного быстрее, но менее переносимо, чем pthread_key_getsspecific, как , предложенное Деннистоном )

Но я бы очень хотел, чтобы вы дали больше контекста и мотивации в своих вопросах.

0 голосов
/ 04 января 2012

Сначала получите дно стека и дайте ему разрешение на чтение / запись со следующим кодом.

pthread_attr_t attr;
void * stackaddr;
int * plocal_var;
size_t stacksize;

pthread_getattr_np(pthread_self(), &attr);
pthread_attr_getstack( &attr, &stackaddr, &stacksize );

printf( "stackaddr = %p, stacksize = %d\n", stackaddr, stacksize );

plocal_var = (int*)mmap( stackaddr, 4096, PROT_READ | PROT_WRITE, 
          MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0 );
// Now try to write something 
*plocal_var = 4;

и затем вы можете получить идентификатор потока с помощью функции get_thread_id () , показанной ниже. Обратите внимание, что вызов mmap размером 4096 приводит к увеличению границы стека на 4096, поэтому мы получаем 4096 при получении адреса локальной переменной.

int get_thread_id()
{
    pthread_attr_t attr;
    char * stackaddr;
    int * plocal_var;
    size_t stacksize;

    pthread_getattr_np(pthread_self(), &attr);
    pthread_attr_getstack( &attr, (void**)&stackaddr, &stacksize );

    //printf( "stackaddr = %p, stacksize = %d\n", stackaddr, stacksize );

    plocal_var = (int*)(stackaddr - 4096);

    return *plocal_var;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...