CPU_ZERO "неопределенный символ" с использованием pthread_setaffinity_np в NASM - PullRequest
0 голосов
/ 08 января 2020

Я использую библиотеку pthreads в NASM под Ubuntu 18.04. Создание потока работает правильно, но я хочу назначить каждый поток отдельному ядру с помощью pthread_setaffinity_np.

Ниже приведен раздел кода, который я использую для инициализации потоков. Он компилируется как написано, но во время выполнения я получаю «неопределенный символ: CPU_ZERO».

Используя примеры из C, я вставил% define _GNU_SOURCE вверху программы, но я все еще получаю неопределенную ошибку CPU_ZERO символа.

section .data align=16

; For thread scheduling:
cpuset: times 4 dq 0

section .text

label_0:

mov rdi,ThreadID            ; ThreadCount
mov rsi,pthread_attr_t  ; Thread Attributes
mov rdx,Test_fn         ; Function Pointer
mov rcx,pthread_arg
call pthread_create wrt ..plt

; Set affinity mask
mov rdi,cpuset
call CPU_ZERO wrt ..plt
call pthread_self wrt ..plt
push rax
mov rdi,rax
mov rsi,cpuset
call CPU_SET wrt ..plt
pop rax
mov rdi,rax
mov rsi,32
mov rdx,cpuset
call pthread_setaffinity_np wrt ..plt
; check the result with pthread_getaffinity_np

mov rax,[tcounter]
add rax,8
mov [tcounter],rax
mov rbx,[Number_Of_Cores]
cmp rax,rbx
jl label_0

Мой вопрос: как мне использовать CPU_ZERO и CPU_SET в NASM (или на любом другом языке ассемблера; я могу перевести на NASM).

Спасибо за любую помощь.

Ответы [ 3 ]

3 голосов
/ 08 января 2020

CPU_ZERO и CPU_SET - это макросы C, а не функции, которые вы можете вызывать.

Вам придется развернуть собственную функцию для выполнения эквивалентного обнуления / установки.

2 голосов
/ 08 января 2020

Это макросы CPP, а не функции. Вы можете сказать из всех заглавных букв имена. А из того факта, что страница руководства называет их макросами.

Как обычно, в разделе примечаний страницы руководства есть подробности, которые полезны для asm:

Поскольку наборы ЦП - это битовые маски, выделенные в единицах длинных слов , фактическое количество ЦП в динамически распределенном наборе ЦП будет округлено до следующего кратного sizeof(unsigned long). Приложение должно считать содержимое этих дополнительных битов неопределенным.

Несмотря на сходство имен, обратите внимание, что константа CPU_SETSIZE указывает количество процессоров в типе данных cpu_set_t ( таким образом, это фактически число битов в битовой маске) ​​, в то время как аргумент setsize макросов CPU _ * _ S () имеет размер в байтах.

В моей системе ( Arch Linux, glib c 2.29-4)

/usr/include/bits/cpu-set.h говорит

...
#define __CPU_SETSIZE   1024
#define __NCPUBITS      (8 * sizeof (__cpu_mask))
...
typedef __CPU_MASK_TYPE __cpu_mask;  // ultimately unsigned long via some other headers
...
typedef struct
{
  __cpu_mask __bits[__CPU_SETSIZE / __NCPUBITS];
} cpu_set_t;

То есть cpu_set_t равно 1024 битам = 128 байтов = times 16 dq 0 или, по крайней мере, resq 16, в моей системе с этой конфигурацией ядра.


CPU_ZERO бесплатно в вашем случае; ваш статически распределенный cpu_set_t статически инициализируется нулями. По какой-то причине вы вводите его в .data вместо .bss, поэтому исполняемый файл должен фактически содержать эти нули, но с той же разницей.

Если вы хотите, например, обнулить один в стеке, например , rep stosd - это простой способ, или хранилища xorps xmm0, xmm0 и 8x movups также будут работать.


Так как высокая производительность не важна (код установки соответствия процессору, вероятно, выполняется только один раз), bts - очень удобный способ установки битов в битовой карте (CPU_SET) . Для места назначения памяти требуется битовый индекс, который может go за пределами dword, выбранного режимом адресации. bts mem, reg медленный и микрокодированный (как 10 мопов на Skylake), но хорош для размера кода. bts mem, imm - это всего 3 мопа, но or byte [mem + i/8], 1<<(i%8) - только 2 мопа.

or также позволяет вам установить более 1 бита за раз, или, более просто, просто mov сохранить несколько байтов которые содержат желаемый шаблон нулей и единиц.

Но TL: DR: это просто растровое изображение, манипулируйте им, как вам нравится, используя asm, или даже статически инициализируйте его ненулевыми значениями.

0 голосов
/ 23 января 2020

Мой подход к решению этой проблемы обобщен в моем ответе на Воспроизвести эти C типы в сборке? .

...