]>
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. | |
4 | // UNSUPPORTED: android | |
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 | |
5bcae85e SL |
11 | // This condition needs to correspond to __HAVE_64B_ATOMICS macro in glibc. |
12 | #if (defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) || \ | |
13 | defined(__s390x__) || defined(__sparc64__) || defined(__alpha__) || \ | |
14 | defined(__ia64__) || defined(__m68k__)) && __GLIBC_PREREQ(2, 21) | |
15 | typedef uint64_t semval_t; | |
16 | #else | |
17 | typedef unsigned semval_t; | |
18 | #endif | |
19 | ||
7cac9316 XL |
20 | // glibc 2.21 has introduced some changes in the way the semaphore value is |
21 | // handled for 32-bit platforms, but since these changes are not ABI-breaking | |
22 | // they are not versioned. On newer platforms such as ARM, there is only one | |
23 | // version of the symbol, so it's enough to check the glibc version. However, | |
24 | // for old platforms such as i386, glibc contains two or even three versions of | |
25 | // the sem_init symbol, and the sanitizers always pick the oldest one. | |
26 | // Therefore, it is not enough to rely on the __GLIBC_PREREQ macro - we should | |
27 | // instead check the platform as well to make sure we only expect the new | |
28 | // behavior on platforms where the older symbols do not exist. | |
29 | #if defined(__arm__) && __GLIBC_PREREQ(2, 21) | |
30 | #define GET_SEM_VALUE(V) ((V) >> 1) | |
31 | #else | |
32 | #define GET_SEM_VALUE(V) (V) | |
33 | #endif | |
34 | ||
5bcae85e | 35 | void my_sem_init(bool priv, int value, semval_t *a, unsigned char *b) { |
92a42be0 SL |
36 | sem_t sem; |
37 | memset(&sem, 0xAB, sizeof(sem)); | |
38 | sem_init(&sem, priv, value); | |
39 | ||
40 | char *p = (char *)&sem; | |
5bcae85e SL |
41 | memcpy(a, p, sizeof(semval_t)); |
42 | memcpy(b, p + sizeof(semval_t), sizeof(char)); | |
92a42be0 SL |
43 | |
44 | sem_destroy(&sem); | |
45 | } | |
46 | ||
47 | int main() { | |
5bcae85e | 48 | semval_t a; |
92a42be0 SL |
49 | unsigned char b; |
50 | ||
51 | my_sem_init(false, 42, &a, &b); | |
7cac9316 | 52 | assert(GET_SEM_VALUE(a) == 42); |
92a42be0 SL |
53 | assert(b != 0xAB); |
54 | ||
55 | my_sem_init(true, 43, &a, &b); | |
7cac9316 | 56 | assert(GET_SEM_VALUE(a) == 43); |
92a42be0 SL |
57 | assert(b != 0xAB); |
58 | } |