gpt4 book ai didi

c - 为什么 pthread_self 被标记为 attribute(const)?

转载 作者:太空狗 更新时间:2023-10-29 15:28:38 24 4
gpt4 key购买 nike

在 Glibc 的 pthread.h 中,pthread_self 函数是用 const 属性声明的:

extern pthread_t pthread_self (void) __THROW __attribute__ ((__const__));

在 GCC 中 that attribute means :

Many functions do not examine any values except their arguments, and have no effects except the return value. Basically this is just slightly more strict class than the pure attribute below, since function is not allowed to read global memory.

我想知道那应该是怎样的?由于它不接受任何参数,因此 pthread_self 只允许始终返回相同的值,但显然不是这种情况。也就是说,我希望 pthread_self 读取全局内存,因此最终被标记为 pure:

Many functions have no effects except the return value and their return value depends only on the parameters and/or global variables. Such a function can be subject to common subexpression elimination and loop optimization just as an arithmetic operator would be. These functions should be declared with the attribute pure.

x86-64 上的实现似乎实际上是在读取全局内存:

# define THREAD_SELF \
({ struct pthread *__self; \
asm ("mov %%fs:%c1,%0" : "=r" (__self) \
: "i" (offsetof (struct pthread, header.self))); \
__self;})

pthread_t
__pthread_self (void)
{
return (pthread_t) THREAD_SELF;
}
strong_alias (__pthread_self, pthread_self)

这是一个错误还是我没有看到什么?

最佳答案

该属性很可能是在假设 GCC 只会在本地(在函数内)使用它,并且永远无法将它用于过程间优化的假设下添加的。今天,一些 Glibc 开发人员质疑该属性的正确性,正是因为强大的过程间优化可能会导致错误编译;引用 post by Torvald Riegel to Glibc developers' mailing list ,

The const attribute is specified as asserting that the function does not examine any data except the arguments. __errno_location has no arguments, so it would have to return the same values every time. This works in a single-threaded program, but not in a multi-threaded one. Thus, I think that strictly speaking, it should not be const.

We could argue that this magically is meant to always be in the context of a specific thread. Ignoring that GCC doesn't define threads itself (especially in something like NPTL which is about creating a notion of threads), we could still assume that this works because in practice, the compiler and its passes can't leak knowledge across a function used in one thread and other one used in another thread.

(__errno_location()pthread_self() 都标有 __attribute__((const)) 并且不接收任何参数)。

这是一个可能会被强大的过程间分析错误编译的小例子:

#include <pthread.h>
#include <errno.h>
#include <stdlib.h>

static void *errno_pointer;

static void *thr(void *unused)
{
if (!errno_pointer || errno_pointer == &errno)
abort();
return 0;
}

int main()
{
errno_pointer = &errno;
pthread_t t;
pthread_create(&t, 0, thr, 0);
pthread_join(t, 0);
}

(编译器可以观察到 errno_pointer 是静态的,它不会转义翻译单元,并且唯一存储到它的存储分配相同的“常量”值,由 __errno_location() ,在 thr() 中测试)。我在 my email asking to improve documentation of pure/const attributes 中使用了这个例子,但不幸的是,它并没有引起太大的关注。

关于c - 为什么 pthread_self 被标记为 attribute(const)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36876996/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com