Как получить идентификатор потока из произвольного pthread_t? - PullRequest
38 голосов
/ 17 февраля 2009

У меня есть pthread_t, и я хотел бы изменить его привязку к процессору. Проблема в том, что я использую glibc 2.3.2, который не имеет pthread_setaffinity_np () . Это нормально, хотя, потому что pthread_setaffinity_np () сама по себе является оболочкой sched_setaffinity () , которая может быть вызвана путем передачи идентификатора потока вместо идентификатора процесса для установки соответствия для произвольного потока.

НО ... Идентификатор потока, с которым может работать sched_setaffinity, является идентификатором потока ОС, который вы можете получить из системного вызова gettid () . Это отличается от непрозрачного типа pthread_t , и gettid () будет возвращать только идентификатор потока текущего потока . Мне нужно иметь возможность установить привязку к процессору произвольного потока.

К сожалению, я не могу получить доступ к закрытым частям pthread, что позволило бы мне украсть идентификатор потока, приведя pthread_t к struct pthread *. Тем лучше, я полагаю, поскольку использование частных реализаций требует даже больше неприятностей.

Я также читал о функции pthread_getunique_np , однако это возвращает «уникальный интегральный идентификатор» - который, я не верю, каким-либо образом соответствует форме или форме, эквивалентной потоку ОС ID.

Отсюда возникает вопрос: как я могу получить идентификатор потока из произвольного pthread_t?

Ответы [ 5 ]

33 голосов
/ 18 февраля 2009

Поскольку pthread s не нужно реализовывать с потоками Linux (или вообще с потоками ядра), а некоторые реализации полностью пользовательские или смешанные, интерфейс pthread s не предоставляет функций получить доступ к этим деталям реализации, так как они не будут переносимы (даже при реализации pthread в Linux). Библиотеки потоков, использующие их, могут предоставить это в качестве расширения, но, похоже, не существует ни одной из них.

Помимо доступа к внутренним структурам данных библиотеки потоков (что, по понятным причинам, вам не нужно, хотя, учитывая ваши предположения о сродстве процессоров и идентификаторах потоков Linux, ваш код в любом случае не будет переносимым), вы, возможно, сможете подшутить во время создания, если вы управляете кодом, который создает потоки:

Дайте pthread_create() функцию ввода, которая вызывает gettid() (что, кстати, вам, вероятно, придется делать с использованием макроса syscall напрямую, поскольку он не всегда экспортируется libc), сохраняет результат где-то , а затем вызывает исходную функцию ввода. Если у вас несколько потоков с одной и той же функцией ввода, вы можете передать инкрементный указатель в массив в аргументе arg в pthread_create, который затем будет передан в функцию ввода, созданную вами для хранения идентификатора потока. Store pthread_t возвращает значение pthread_create в том же порядке, и тогда вы сможете искать идентификаторы потоков Linux всех созданных вами потоков по их значению pthread_t.

Стоит ли этот трюк, зависит от того, насколько важна настройка соответствия ЦП в вашем случае, в отличие от отсутствия доступа к внутренним структурам библиотеки потоков или от библиотеки потоков, предоставляющей pthread_setaffinity_np.

12 голосов
/ 10 сентября 2013

На самом деле pthread_self возвращает pthread_t, а не целочисленный идентификатор потока, с которым вы можете работать, следующая вспомогательная функция обеспечит вам переносимость в различных системах POSIX.

uint64_t gettid() {
    pthread_t ptid = pthread_self();
    uint64_t threadId = 0;
    memcpy(&threadId, &ptid, std::min(sizeof(threadId), sizeof(ptid)));
    return threadId;
}
1 голос
/ 21 сентября 2017

В glibc 2.24 pthread_t возвращает только указатель на непрозрачный struct pthread. Вы можете посмотреть определение в nptl/descr.h.

1 голос
/ 06 сентября 2013
pthread_t pthread_self()

это возвращаемый текущий pthread_t, который является идентификатором потока, вы можете преобразовать его в тип "unsigned int",

1 голос
/ 18 февраля 2009

Я бы предложил простой обходной путь с общим массивом int, где вы могли бы записать идентификатор потока из потоков, чтобы получить к нему доступ позже.

Надеюсь, это поможет.

...