]>
Commit | Line | Data |
---|---|---|
92a42be0 SL |
1 | // RUN: %clangxx -O0 -g %s -lutil -o %t && %run %t |
2 | // This test depends on the glibc layout of struct sem_t and checks that we | |
3 | // don't leave sem_t::private uninitialized. | |
2c00a5a8 | 4 | // UNSUPPORTED: android, lsan-x86, ubsan, target-is-mips64, target-is-mips64el |
5bcae85e | 5 | #include <features.h> |
92a42be0 SL |
6 | #include <assert.h> |
7 | #include <semaphore.h> | |
8 | #include <string.h> | |
5bcae85e | 9 | #include <stdint.h> |
92a42be0 | 10 | |
2c00a5a8 XL |
11 | // On powerpc64be semval_t must be 64 bits even with "old" versions of glibc. |
12 | #if __PPC64__ && __BIG_ENDIAN__ | |
13 | typedef uint64_t semval_t; | |
14 | ||
5bcae85e | 15 | // This condition needs to correspond to __HAVE_64B_ATOMICS macro in glibc. |
2c00a5a8 | 16 | #elif (defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) || \ |
5bcae85e SL |
17 | defined(__s390x__) || defined(__sparc64__) || defined(__alpha__) || \ |
18 | defined(__ia64__) || defined(__m68k__)) && __GLIBC_PREREQ(2, 21) | |
19 | typedef uint64_t semval_t; | |
20 | #else | |
21 | typedef unsigned semval_t; | |
22 | #endif | |
23 | ||
7cac9316 XL |
24 | // glibc 2.21 has introduced some changes in the way the semaphore value is |
25 | // handled for 32-bit platforms, but since these changes are not ABI-breaking | |
26 | // they are not versioned. On newer platforms such as ARM, there is only one | |
27 | // version of the symbol, so it's enough to check the glibc version. However, | |
28 | // for old platforms such as i386, glibc contains two or even three versions of | |
29 | // the sem_init symbol, and the sanitizers always pick the oldest one. | |
30 | // Therefore, it is not enough to rely on the __GLIBC_PREREQ macro - we should | |
31 | // instead check the platform as well to make sure we only expect the new | |
32 | // behavior on platforms where the older symbols do not exist. | |
33 | #if defined(__arm__) && __GLIBC_PREREQ(2, 21) | |
34 | #define GET_SEM_VALUE(V) ((V) >> 1) | |
35 | #else | |
36 | #define GET_SEM_VALUE(V) (V) | |
37 | #endif | |
38 | ||
5bcae85e | 39 | void my_sem_init(bool priv, int value, semval_t *a, unsigned char *b) { |
92a42be0 SL |
40 | sem_t sem; |
41 | memset(&sem, 0xAB, sizeof(sem)); | |
42 | sem_init(&sem, priv, value); | |
43 | ||
44 | char *p = (char *)&sem; | |
5bcae85e SL |
45 | memcpy(a, p, sizeof(semval_t)); |
46 | memcpy(b, p + sizeof(semval_t), sizeof(char)); | |
92a42be0 SL |
47 | |
48 | sem_destroy(&sem); | |
49 | } | |
50 | ||
51 | int main() { | |
5bcae85e | 52 | semval_t a; |
92a42be0 SL |
53 | unsigned char b; |
54 | ||
55 | my_sem_init(false, 42, &a, &b); | |
7cac9316 | 56 | assert(GET_SEM_VALUE(a) == 42); |
92a42be0 SL |
57 | assert(b != 0xAB); |
58 | ||
59 | my_sem_init(true, 43, &a, &b); | |
7cac9316 | 60 | assert(GET_SEM_VALUE(a) == 43); |
92a42be0 SL |
61 | assert(b != 0xAB); |
62 | } |