Как получить идентификатор потока из произвольного pthread_t?
У меня есть pthread_t, и я бы хотел изменить его близость к процессору. Проблема в том, что я использую glibc 2.3.2, у которого нет pthread_setaffinity_np(). Это нормально, потому что pthread_setaffinity_np() сам является оберткой sched_setaffinity(), которую можно вызывать, передавая идентификатор потока вместо процесса ID, чтобы установить сродство к произвольному потоку.
НО... Идентификатор потока, с которым может работать sched_setaffinity, является идентификатором потока ОС, который вы можете получить из gettid(). Это отличается от непрозрачного типа pthread_t, а gettid() возвращает только поток-идентификатор текущего потока. Мне нужно уметь устанавливать сродство к процессору произвольного потока.
К сожалению, я не могу получить доступ к частным частям pthread, что позволило бы мне украсть идентификатор потока, наведя pthread_t на struct pthread *
. Тем лучше, я полагаю, поскольку полагаться на частные реализации требует еще больших проблем.
Я также читал функцию pthread_getunique_np, однако это возвращает "уникальный интегральный идентификатор", который я не полагать, что это форма или форма, эквивалентная идентификатору потока ОС.
Следовательно, вопрос: как я могу получить идентификатор потока из произвольного pthread_t?
Ответы
Ответ 1
Так как pthread
не нужно реализовывать с потоками Linux (или вообще нитями ядра вообще), а некоторые реализации полностью пользовательские или смешанные, интерфейс pthread
не предоставляет функции доступа эти детали реализации, поскольку они не будут переносимыми (даже в реализациях pthread
в Linux). Библиотеки потоков, которые их используют, могут предоставить это как расширение, но, похоже, не все, что есть.
Помимо доступа к внутренним структурам данных библиотеки потоков (которые вы, по понятным причинам, не хотите, хотя с вашими предположениями о близости процессора и идентификаторах потоков Linux, ваш код в любом случае не будет переносимым), вы можете сыграть трюк во время создания, если вы управляете кодом, который создает потоки:
Дайте pthread_create()
функцию ввода, которая вызывает gettid()
(которая, кстати, вам может понадобиться с помощью макроса syscall
непосредственно, потому что она не всегда экспортируется libc
), сохраняет результат где-то, а затем вызывает исходную функцию ввода. Если у вас несколько потоков с одной и той же функцией ввода, вы можете передать инкрементный указатель в массив в аргументе arg
до pthread_create
, который затем будет передан в функцию ввода, которую вы создали для хранения идентификатора потока. pthread_t
возвращает значение pthread_create
в том же порядке, а затем вы сможете искать идентификаторы потоков Linux всех созданных вами потоков с учетом их значения pthread_t
.
Является ли этот трюк его достоинством, зависит от того, насколько важна настройка сродства к процессору в вашем случае, а не для доступа к внутренним структурам библиотеки потоков или в зависимости от библиотеки потоков, которая предоставляет pthread_setaffinity_np
.
Ответ 2
Фактически 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;
}
Ответ 3
pthread_t pthread_self()
этот возвращаемый ток pthread_t, который является идентификатором потока, вы можете преобразовать его в тип "unsigned int",
Ответ 4
Я бы предложил простой обходной путь с общим массивом int, где вы могли бы написать идентификатор потока из потоков для доступа к нему позже.
Надеюсь, что это поможет.
Ответ 5
В glibc 2.24 возвращаемый pthread_t
является указателем на непрозрачный struct pthread
. Вы можете найти определение в nptl/descr.h
.