DISALLOW_COPY_AND_ASSIGN(prop_bt);
};
-struct prop_area {
- uint32_t bytes_used;
- atomic_uint_least32_t serial;
- uint32_t magic;
- uint32_t version;
- uint32_t reserved[28];
- char data[0];
+class prop_area {
+public:
prop_area(const uint32_t magic, const uint32_t version) :
- magic(magic), version(version) {
- atomic_init(&serial, 0);
- memset(reserved, 0, sizeof(reserved));
+ magic_(magic), version_(version) {
+ atomic_init(&serial_, 0);
+ memset(reserved_, 0, sizeof(reserved_));
// Allocate enough space for the root node.
- bytes_used = sizeof(prop_bt);
+ bytes_used_ = sizeof(prop_bt);
}
+ const prop_info *find(const char *name);
+ bool add(const char *name, unsigned int namelen,
+ const char *value, unsigned int valuelen);
+
+ bool foreach(void (*propfn)(const prop_info *pi, void *cookie), void *cookie);
+
+ atomic_uint_least32_t *serial() { return &serial_; }
+ uint32_t magic() const { return magic_; }
+ uint32_t version() const { return version_; }
+
private:
+ void *allocate_obj(const size_t size, uint_least32_t *const off);
+ prop_bt *new_prop_bt(const char *name, uint8_t namelen, uint_least32_t *const off);
+ prop_info *new_prop_info(const char *name, uint8_t namelen,
+ const char *value, uint8_t valuelen,
+ uint_least32_t *const off);
+ void *to_prop_obj(uint_least32_t off);
+ prop_bt *to_prop_bt(atomic_uint_least32_t *off_p);
+ prop_info *to_prop_info(atomic_uint_least32_t *off_p);
+
+ prop_bt *root_node();
+
+ prop_bt *find_prop_bt(prop_bt *const bt, const char *name,
+ uint8_t namelen, bool alloc_if_needed);
+
+ const prop_info *find_property(prop_bt *const trie, const char *name,
+ uint8_t namelen, const char *value,
+ uint8_t valuelen, bool alloc_if_needed);
+
+ bool foreach_property(prop_bt *const trie,
+ void (*propfn)(const prop_info *pi, void *cookie),
+ void *cookie);
+
+ uint32_t bytes_used_;
+ atomic_uint_least32_t serial_;
+ uint32_t magic_;
+ uint32_t version_;
+ uint32_t reserved_[28];
+ char data_[0];
+
DISALLOW_COPY_AND_ASSIGN(prop_area);
};
}
prop_area* pa = reinterpret_cast<prop_area*>(map_result);
- if ((pa->magic != PROP_AREA_MAGIC) || (pa->version != PROP_AREA_VERSION &&
- pa->version != PROP_AREA_VERSION_COMPAT)) {
+ if ((pa->magic() != PROP_AREA_MAGIC) ||
+ (pa->version() != PROP_AREA_VERSION &&
+ pa->version() != PROP_AREA_VERSION_COMPAT)) {
munmap(pa, pa_size);
return -1;
}
- if (pa->version == PROP_AREA_VERSION_COMPAT) {
+ if (pa->version() == PROP_AREA_VERSION_COMPAT) {
compat_mode = true;
}
return map_result;
}
-static void *allocate_obj(const size_t size, uint_least32_t *const off)
+void *prop_area::allocate_obj(const size_t size, uint_least32_t *const off)
{
- prop_area *pa = __system_property_area__;
const size_t aligned = BIONIC_ALIGN(size, sizeof(uint_least32_t));
- if (pa->bytes_used + aligned > pa_data_size) {
+ if (bytes_used_ + aligned > pa_data_size) {
return NULL;
}
- *off = pa->bytes_used;
- pa->bytes_used += aligned;
- return pa->data + *off;
+ *off = bytes_used_;
+ bytes_used_ += aligned;
+ return data_ + *off;
}
-static prop_bt *new_prop_bt(const char *name, uint8_t namelen, uint_least32_t *const off)
+prop_bt *prop_area::new_prop_bt(const char *name, uint8_t namelen, uint_least32_t *const off)
{
uint_least32_t new_offset;
void *const p = allocate_obj(sizeof(prop_bt) + namelen + 1, &new_offset);
return NULL;
}
-static prop_info *new_prop_info(const char *name, uint8_t namelen,
+prop_info *prop_area::new_prop_info(const char *name, uint8_t namelen,
const char *value, uint8_t valuelen, uint_least32_t *const off)
{
uint_least32_t new_offset;
return NULL;
}
-static void *to_prop_obj(uint_least32_t off)
+void *prop_area::to_prop_obj(uint_least32_t off)
{
if (off > pa_data_size)
return NULL;
- if (!__system_property_area__)
- return NULL;
- return (__system_property_area__->data + off);
+ return (data_ + off);
}
-static inline prop_bt *to_prop_bt(atomic_uint_least32_t* off_p) {
+inline prop_bt *prop_area::to_prop_bt(atomic_uint_least32_t* off_p) {
uint_least32_t off = atomic_load_explicit(off_p, memory_order_consume);
return reinterpret_cast<prop_bt*>(to_prop_obj(off));
}
-static inline prop_info *to_prop_info(atomic_uint_least32_t* off_p) {
+inline prop_info *prop_area::to_prop_info(atomic_uint_least32_t* off_p) {
uint_least32_t off = atomic_load_explicit(off_p, memory_order_consume);
return reinterpret_cast<prop_info*>(to_prop_obj(off));
}
-static inline prop_bt *root_node()
+inline prop_bt *prop_area::root_node()
{
return reinterpret_cast<prop_bt*>(to_prop_obj(0));
}
return strncmp(one, two, one_len);
}
-static prop_bt *find_prop_bt(prop_bt *const bt, const char *name,
- uint8_t namelen, bool alloc_if_needed)
+prop_bt *prop_area::find_prop_bt(prop_bt *const bt, const char *name,
+ uint8_t namelen, bool alloc_if_needed)
{
prop_bt* current = bt;
}
}
-static const prop_info *find_property(prop_bt *const trie, const char *name,
+const prop_info *prop_area::find_property(prop_bt *const trie, const char *name,
uint8_t namelen, const char *value, uint8_t valuelen,
bool alloc_if_needed)
{
cookie->count++;
}
-static int foreach_property(prop_bt *const trie,
+bool prop_area::foreach_property(prop_bt *const trie,
void (*propfn)(const prop_info *pi, void *cookie), void *cookie)
{
if (!trie)
- return -1;
+ return false;
uint_least32_t left_offset = atomic_load_explicit(&trie->left, memory_order_relaxed);
if (left_offset != 0) {
const int err = foreach_property(to_prop_bt(&trie->left), propfn, cookie);
if (err < 0)
- return -1;
+ return false;
}
uint_least32_t prop_offset = atomic_load_explicit(&trie->prop, memory_order_relaxed);
if (prop_offset != 0) {
prop_info *info = to_prop_info(&trie->prop);
if (!info)
- return -1;
+ return false;
propfn(info, cookie);
}
uint_least32_t children_offset = atomic_load_explicit(&trie->children, memory_order_relaxed);
if (children_offset != 0) {
const int err = foreach_property(to_prop_bt(&trie->children), propfn, cookie);
if (err < 0)
- return -1;
+ return false;
}
uint_least32_t right_offset = atomic_load_explicit(&trie->right, memory_order_relaxed);
if (right_offset != 0) {
const int err = foreach_property(to_prop_bt(&trie->right), propfn, cookie);
if (err < 0)
- return -1;
+ return false;
}
- return 0;
+ return true;
+}
+
+const prop_info *prop_area::find(const char *name) {
+ return find_property(root_node(), name, strlen(name), nullptr, 0, false);
+}
+
+bool prop_area::add(const char *name, unsigned int namelen,
+ const char *value, unsigned int valuelen) {
+ return find_property(root_node(), name, namelen, value, valuelen, true);
+}
+
+bool prop_area::foreach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
+ return foreach_property(root_node(), propfn, cookie);
}
int __system_properties_init()
return -1;
}
// Make sure this read fulfilled before __system_property_serial
- return atomic_load_explicit(&(pa->serial), memory_order_acquire);
+ return atomic_load_explicit(pa->serial(), memory_order_acquire);
}
const prop_info *__system_property_find(const char *name)
if (__predict_false(compat_mode)) {
return __system_property_find_compat(name);
}
- return find_property(root_node(), name, strlen(name), NULL, 0, false);
+
+ if (!__system_property_area__) {
+ return nullptr;
+ }
+
+ return __system_property_area__->find(name);
}
// The C11 standard doesn't allow atomic loads from const fields,
__futex_wake(&pi->serial, INT32_MAX);
atomic_store_explicit(
- &pa->serial,
- atomic_load_explicit(&pa->serial, memory_order_relaxed) + 1,
+ pa->serial(),
+ atomic_load_explicit(pa->serial(), memory_order_relaxed) + 1,
memory_order_release);
- __futex_wake(&pa->serial, INT32_MAX);
+ __futex_wake(pa->serial(), INT32_MAX);
return 0;
}
const char *value, unsigned int valuelen)
{
prop_area *pa = __system_property_area__;
- const prop_info *pi;
if (namelen >= PROP_NAME_MAX)
return -1;
if (namelen < 1)
return -1;
- pi = find_property(root_node(), name, namelen, value, valuelen, true);
- if (!pi)
+ if (!__system_property_area__) {
+ return -1;
+ }
+
+ bool ret = __system_property_area__->add(name, namelen, value, valuelen);
+ if (!ret)
return -1;
// There is only a single mutator, but we want to make sure that
// updates are visible to a reader waiting for the update.
atomic_store_explicit(
- &pa->serial,
- atomic_load_explicit(&pa->serial, memory_order_relaxed) + 1,
+ pa->serial(),
+ atomic_load_explicit(pa->serial(), memory_order_relaxed) + 1,
memory_order_release);
- __futex_wake(&pa->serial, INT32_MAX);
+ __futex_wake(pa->serial(), INT32_MAX);
return 0;
}
uint32_t my_serial;
do {
- __futex_wait(&pa->serial, serial, NULL);
- my_serial = atomic_load_explicit(&pa->serial, memory_order_acquire);
+ __futex_wait(pa->serial(), serial, NULL);
+ my_serial = atomic_load_explicit(pa->serial(), memory_order_acquire);
} while (my_serial == serial);
return my_serial;
return __system_property_foreach_compat(propfn, cookie);
}
- return foreach_property(root_node(), propfn, cookie);
+ if (!__system_property_area__) {
+ return -1;
+ }
+
+ return __system_property_area__->foreach(propfn, cookie) ? 0 : -1;
}