summaryrefslogtreecommitdiff
path: root/leveldb/port/port_android.h
blob: 13df9c943a753c59c8f23f87c5680fbff75101ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
//
// See port_example.h for documentation for the following types/functions.

#ifndef STORAGE_LEVELDB_PORT_PORT_ANDROID_H_
#define STORAGE_LEVELDB_PORT_PORT_ANDROID_H_

#include <endian.h>
#include <pthread.h>
#include <stdint.h>
#include <cstdatomic>
#include <string>
#include <cctype>

// Collapse the plethora of ARM flavors available to an easier to manage set
// Defs reference is at https://wiki.edubuntu.org/ARM/Thumb2PortingHowto
#if defined(__ARM_ARCH_6__) || \
    defined(__ARM_ARCH_6J__) || \
    defined(__ARM_ARCH_6K__) || \
    defined(__ARM_ARCH_6Z__) || \
    defined(__ARM_ARCH_6T2__) || \
    defined(__ARM_ARCH_6ZK__) || \
    defined(__ARM_ARCH_7__) || \
    defined(__ARM_ARCH_7R__) || \
    defined(__ARM_ARCH_7A__)
#define ARMV6_OR_7 1
#endif

extern "C" {
  size_t fread_unlocked(void *a, size_t b, size_t c, FILE *d);
  size_t fwrite_unlocked(const void *a, size_t b, size_t c, FILE *d);
  int fflush_unlocked(FILE *f);
  int fdatasync (int fd);
}

namespace leveldb {
namespace port {

static const bool kLittleEndian = __BYTE_ORDER == __LITTLE_ENDIAN;

class CondVar;

class Mutex {
 public:
  Mutex();
  ~Mutex();

  void Lock();
  void Unlock();
  void AssertHeld() {
    //TODO(gabor): How can I implement this?
  }

 private:
  friend class CondVar;
  pthread_mutex_t mu_;

  // No copying
  Mutex(const Mutex&);
  void operator=(const Mutex&);
};

class CondVar {
 public:
  explicit CondVar(Mutex* mu);
  ~CondVar();
  void Wait();
  void Signal();
  void SignalAll();
 private:
  Mutex* mu_;
  pthread_cond_t cv_;
};

#ifndef ARMV6_OR_7
// On ARM chipsets <V6, 0xffff0fa0 is the hard coded address of a 
// memory barrier function provided by the kernel.
typedef void (*LinuxKernelMemoryBarrierFunc)(void);
LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier ATTRIBUTE_WEAK =
    (LinuxKernelMemoryBarrierFunc) 0xffff0fa0;
#endif

// Storage for a lock-free pointer
class AtomicPointer {
 private:
  void* rep_;

  inline void MemoryBarrier() const {
    // TODO(gabor): This only works on Android instruction sets >= V6
#ifdef ARMV6_OR_7
    __asm__ __volatile__("dmb" : : : "memory");
#else
    pLinuxKernelMemoryBarrier();
#endif
  }

 public:
  AtomicPointer() { }
  explicit AtomicPointer(void* v) : rep_(v) { }
  inline void* Acquire_Load() const {
    void* r = rep_;
    MemoryBarrier();
    return r;
  }
  inline void Release_Store(void* v) {
    MemoryBarrier();
    rep_ = v;
  }
  inline void* NoBarrier_Load() const {
    void* r = rep_;
    return r;
  }
  inline void NoBarrier_Store(void* v) {
    rep_ = v;
  }
};

// TODO(gabor): Implement compress
inline bool Snappy_Compress(
    const char* input,
    size_t input_length,
    std::string* output) {
  return false;
}

// TODO(gabor): Implement uncompress
inline bool Snappy_Uncompress(
    const char* input_data,
    size_t input_length,
    std::string* output) {
  return false;
}

inline uint64_t ThreadIdentifier() {
  pthread_t tid = pthread_self();
  uint64_t r = 0;
  memcpy(&r, &tid, sizeof(r) < sizeof(tid) ? sizeof(r) : sizeof(tid));
  return r;
}

inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) {
  return false;
}

}
}

#endif  // STORAGE_LEVELDB_PORT_PORT_ANDROID_H_