Reproduce these C types in assembly?

依然范特西╮ 提交于 2020-02-08 09:58:33

问题


I am trying to reproduce two opaque data types from the pthreads library in NASM. These data types are pthread_attr_t and cpu_set_t from pthread_attr_setaffinity_np (see http://man7.org/linux/man-pages/man3/pthread_attr_setaffinity_np.3.html).

I created a simple C program to call pthread_attr_setaffinity_np and stepped through it with gdb to examine the format of those two bitmasks (pthread_attr_t is an affinity mask).

When I debug the C version with gdb, I print the values of attr and 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>}}

What do those two type formats translate into for assembly language?

Here is the C code:

#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;
}

Thanks very much for any help.


回答1:


It's fairly easy to create threads in NASM using pthreads, but setting the affinity mask is another matter. It turned out to be unnecessary to reproduce the opaque types to use in assembly language, which would be very difficult.

Instead, I compiled the C program to an object file, and linked that object file with the NASM object file to produce the final executable. The main() function in C got a different name because it's not to be compiled to an .exe, and that function name is referenced with an "extern" in the NASM program. Here's the final C code:

#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;
}

In the NASM code, we have an "extern thread_create_in_C" directive with the other externs, to reference the C code, and in the C code we have extern void * Test_fn(); to reference the NASM function to be called by each thread.

We call the C program at the appropriate point in the NASM program with:

call thread_create_in_C wrt ..plt

My suggestion to anyone who needs to set affinity masks for threads in assembly language is to use a C program like the one above instead of trying to replicate it in assembly. But for simple thread creation without affinity masks, the pthreads library is all you need.



来源:https://stackoverflow.com/questions/59776532/reproduce-these-c-types-in-assembly

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!