Воспроизвести эти C типов в сборке? - PullRequest
0 голосов
/ 16 января 2020

Я пытаюсь воспроизвести два непрозрачных типа данных из библиотеки pthreads в NASM. Этими типами данных являются pthread_attr_t и cpu_set_t из pthread_attr_setaffinity_np (см. http://man7.org/linux/man-pages/man3/pthread_attr_setaffinity_np.3.html).

Я создал простую C программу для вызова pthread_attr_setaffinity_np и прошел через нее с помощью gdb, чтобы проверить формат этих двух битовых масок (pthread_attr_t является маской сходства).

Когда я отлаживаю версию C с помощью gdb, я печатаю значения attr и cpus:

(gdb) p attr
$2 = {__size = '\000' <repeats 17 times>, "\020", '\000' <repeats 37 times>, __align = 0}

(gdb) p cpus
$3 = {__bits = {1, 0 <repeats 15 times>}}

Во что переводятся эти два формата для языка ассемблера?

Вот код C:

#define _GNU_SOURCE
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void* DoWork(void* args) {
    printf("ID: %lu, CPU: %d\n", pthread_self(), sched_getcpu());
    return 0;
}

int main() {   

    int numberOfProcessors = sysconf(_SC_NPROCESSORS_ONLN);
    printf("Number of processors: %d\n", numberOfProcessors);

    pthread_t threads[numberOfProcessors];

    pthread_attr_t attr;
    cpu_set_t cpus;
    pthread_attr_init(&attr);

    for (int i = 0; i < numberOfProcessors; i++) {
       CPU_ZERO(&cpus);
       CPU_SET(i, &cpus);
       pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpus);
       pthread_create(&threads[i], &attr, DoWork, NULL);
    }

    for (int i = 0; i < numberOfProcessors; i++) {
        pthread_join(threads[i], NULL);
    }

    return 0;
}

Большое спасибо за любую помощь.

1 Ответ

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

Довольно легко создавать потоки в NASM с помощью pthreads, но настройка маски сходства - это другой вопрос. Оказалось, что нет необходимости воспроизводить непрозрачные типы для использования на ассемблере, что было бы очень сложно.

Вместо этого я скомпилировал программу C в объектный файл и связал этот объектный файл с Объектный файл NASM для создания окончательного исполняемого файла. Функция main () в C получила другое имя, потому что ее нельзя скомпилировать в .exe, а на имя этой функции в программе NASM указано «extern». Вот последний C код:

#define _GNU_SOURCE
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

extern void * Test_fn();

int thread_create_in_C() {

    int numberOfProcessors = sysconf(_SC_NPROCESSORS_ONLN);

    if (numberOfProcessors >= 2){ // e.g. virtual cores
        numberOfProcessors = numberOfProcessors / 2; }

    printf("Number of processors: %d\n", numberOfProcessors);

    pthread_t threads[numberOfProcessors];

    pthread_attr_t attr;
    cpu_set_t cpus;
    pthread_attr_init(&attr);

    for (int i = 0; i < numberOfProcessors; i++) {
       CPU_ZERO(&cpus);
       CPU_SET(i, &cpus);
       printf("Core created %d\n", i);
       pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t),    &cpus);
       pthread_create(&threads[i], &attr, Test_fn, NULL);
    }

    for (int i = 0; i < numberOfProcessors; i++) {
        pthread_join(threads[i], NULL);
        printf("Core joined %d\n", i);
    }

    return numberOfProcessors;
}

В коде NASM у нас есть директива extern thread_create_in_ C с другими внешними элементами, которая ссылается на код C, а в C код, который у нас есть extern void * Test_fn (); для ссылки на функцию NASM, вызываемую каждым потоком.

Мы вызываем программу C в соответствующую точку в программе NASM с:

call thread_create_in_C wrt ..plt

Я советую всем, кому нужно установить маски сходства для потоков на ассемблере, использовать C программа, подобная приведенной выше, вместо того, чтобы пытаться копировать ее в сборке. Но для простого создания потока без масок соответствия библиотека pthreads - это все, что вам нужно.

...