~xnox/ubuntu/trusty/gcc-arm-linux-androideabi/dima

« back to all changes in this revision

Viewing changes to android/bionic/libstdc++/src/one_time_construction.cpp

  • Committer: Package Import Robot
  • Author(s): Dmitrijs Ledkovs
  • Date: 2013-07-05 10:12:24 UTC
  • Revision ID: package-import@ubuntu.com-20130705101224-6qo3e8jbz8p31aa1
Tags: upstream-0.20130705.1
ImportĀ upstreamĀ versionĀ 0.20130705.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * one_time_construction.cpp
 
3
 *
 
4
 * Copyright 2006 The Android Open Source Project
 
5
 *
 
6
 * This file contains C++ ABI support functions for one time
 
7
 * constructors as defined in the "Run-time ABI for the ARM Architecture"
 
8
 * section 4.4.2
 
9
 */
 
10
 
 
11
#include <stddef.h>
 
12
#include <sys/atomics.h>
 
13
#include <endian.h>
 
14
#include <bionic_futex.h>
 
15
#include <bionic_atomic_inline.h>
 
16
 
 
17
// ARM C++ ABI and Itanium/x86 C++ ABI has different definition for
 
18
// one time construction:
 
19
//
 
20
//    ARM C++ ABI defines the LSB of guard variable should be tested
 
21
//    by compiler-generated code before calling __cxa_guard_acquire et al.
 
22
//
 
23
//    The Itanium/x86 C++ ABI defines the low-order _byte_ should be
 
24
//    tested instead.
 
25
//
 
26
//    Meanwhile, guard variable are 32bit aligned for ARM, and 64bit
 
27
//    aligned for x86.
 
28
//
 
29
// Reference documentation:
 
30
//
 
31
//    section 3.2.3 of ARM IHI 0041C (for ARM)
 
32
//    section 3.3.2 of the Itanium C++ ABI specification v1.83 (for x86).
 
33
//
 
34
// There is no C++ ABI available for other ARCH. But the gcc source
 
35
// shows all other ARCH follow the definition of Itanium/x86 C++ ABI.
 
36
 
 
37
 
 
38
#if defined(__arm__)
 
39
// The ARM C++ ABI mandates that guard variable are
 
40
// 32-bit aligned, 32-bit values. And only its LSB is tested by
 
41
// the compiler-generated code before calling
 
42
// __cxa_guard_acquire.
 
43
//
 
44
typedef union {
 
45
    int volatile state;
 
46
    int32_t aligner;
 
47
} _guard_t;
 
48
 
 
49
const static int ready = 0x1;
 
50
const static int pending = 0x2;
 
51
const static int waiting = 0x6;
 
52
 
 
53
#else   // GCC sources indicates all none-arm follow the same ABI
 
54
// The Itanium/x86 C++ ABI mandates that guard variables
 
55
// are 64-bit aligned, 64-bit values. Also, the least-significant
 
56
// byte is tested by the compiler-generated code before, we calling
 
57
// __cxa_guard_acquire. We can access it through the first
 
58
// 32-bit word in the union below.
 
59
//
 
60
typedef union {
 
61
    int volatile state;
 
62
    int64_t aligner;
 
63
} _guard_t;
 
64
 
 
65
const static int ready     = letoh32(0x1);
 
66
const static int pending   = letoh32(0x100);
 
67
const static int waiting   = letoh32(0x10000);
 
68
#endif
 
69
 
 
70
extern "C" int __cxa_guard_acquire(_guard_t* gv)
 
71
{
 
72
    // 0 -> pending, return 1
 
73
    // pending -> waiting, wait and return 0
 
74
    // waiting: untouched, wait and return 0
 
75
    // ready: untouched, return 0
 
76
 
 
77
retry:
 
78
    if (__bionic_cmpxchg(0, pending, &gv->state) == 0) {
 
79
        ANDROID_MEMBAR_FULL();
 
80
        return 1;
 
81
    }
 
82
    __bionic_cmpxchg(pending, waiting, &gv->state); // Indicate there is a waiter
 
83
    __futex_wait(&gv->state, waiting, NULL);
 
84
 
 
85
    if (gv->state != ready) // __cxa_guard_abort was called, let every thread try since there is no return code for this condition
 
86
        goto retry;
 
87
 
 
88
    ANDROID_MEMBAR_FULL();
 
89
    return 0;
 
90
}
 
91
 
 
92
extern "C" void __cxa_guard_release(_guard_t* gv)
 
93
{
 
94
    // pending -> ready
 
95
    // waiting -> ready, and wake
 
96
 
 
97
    ANDROID_MEMBAR_FULL();
 
98
    if (__bionic_cmpxchg(pending, ready, &gv->state) == 0) {
 
99
        return;
 
100
    }
 
101
 
 
102
    gv->state = ready;
 
103
    __futex_wake(&gv->state, 0x7fffffff);
 
104
}
 
105
 
 
106
extern "C" void __cxa_guard_abort(_guard_t* gv)
 
107
{
 
108
    ANDROID_MEMBAR_FULL();
 
109
    gv->state= 0;
 
110
    __futex_wake(&gv->state, 0x7fffffff);
 
111
}