Подтвердить что ты не робот

Как получить идентификатор потока из произвольного 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?

4b9b3361

Ответ 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.