int __system_property_read(const prop_info *pi, char *name, char *value) { if (__predict_false(compat_mode)) { return __system_property_read_compat(pi, name, value); } while (true) { uint32_t serial = __system_property_serial(pi); // acquire semantics size_t len = SERIAL_VALUE_LEN(serial); memcpy(value, pi->value, len + 1); // TODO: Fix the synchronization scheme here. // There is no fully supported way to implement this kind // of synchronization in C++11, since the memcpy races with // updates to pi, and the data being accessed is not atomic. // The following fence is unintuitive, but would be the // correct one if memcpy used memory_order_relaxed atomic accesses. // In practice it seems unlikely that the generated code would // would be any different, so this should be OK. atomic_thread_fence(memory_order_acquire); if (serial == load_const_atomic(&(pi->serial), memory_order_relaxed)) { if (name != 0) { strcpy(name, pi->name); } return len; } } }
void SystemProperties::ReadCallback(const prop_info* pi, void (*callback)(void* cookie, const char* name, const char* value, uint32_t serial), void* cookie) { // Read only properties don't need to copy the value to a temporary buffer, since it can never // change. if (is_read_only(pi->name)) { uint32_t serial = Serial(pi); if (pi->is_long()) { callback(cookie, pi->name, pi->long_value(), serial); } else { callback(cookie, pi->name, pi->value, serial); } return; } while (true) { uint32_t serial = Serial(pi); // acquire semantics size_t len = SERIAL_VALUE_LEN(serial); char value_buf[len + 1]; memcpy(value_buf, pi->value, len); value_buf[len] = '\0'; // TODO: see todo in Read function atomic_thread_fence(memory_order_acquire); if (serial == load_const_atomic(&(pi->serial), memory_order_relaxed)) { callback(cookie, pi->name, value_buf, serial); return; } } }
/** * Look up a property by name, copying its value and a * \0 terminator to the provided pointer. The total bytes * copied will be no greater than PROP_VALUE_MAX. * * \return The string length of the value. A property that * is not * defined is identical to a property with a * length 0 value. */ int __system_property_read(const prop_info *pi, char *name, char *value) { unsigned serial, len; for(;;) { serial = pi->serial; while(SERIAL_DIRTY(serial)) { struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = 100; futex_wait((volatile void *)&pi->serial, serial, 0); serial = pi->serial; } len = SERIAL_VALUE_LEN(serial); memcpy(value, pi->value, len + 1); if(serial == pi->serial) { if(name != 0) { strcpy(name, pi->name); } return len; } } }
int __system_property_read(const prop_info *pi, char *name, char *value) { unsigned serial, len; if (__predict_false(compat_mode)) { return __system_property_read_compat(pi, name, value); } for(;;) { serial = pi->serial; while(SERIAL_DIRTY(serial)) { __futex_wait((volatile void *)&pi->serial, serial, NULL); serial = pi->serial; } len = SERIAL_VALUE_LEN(serial); memcpy(value, pi->value, len + 1); ANDROID_MEMBAR_FULL(); if(serial == pi->serial) { if(name != 0) { strcpy(name, pi->name); } return len; } } }
void mb__system_property_read_callback(const prop_info* pi, void (*callback)(void* cookie, const char* name, const char* value, uint32_t serial), void* cookie) { #if MB_ENABLE_COMPAT_PROPERTIES // TODO (dimitry): do we need compat mode for this function? if (__predict_false(compat_mode)) { uint32_t serial = mb__system_property_serial_compat(pi); char name_buf[PROP_NAME_MAX]; char value_buf[PROP_VALUE_MAX]; mb__system_property_read_compat(pi, name_buf, value_buf); callback(cookie, name_buf, value_buf, serial); return; } #endif while (true) { uint32_t serial = mb__system_property_serial(pi); // acquire semantics size_t len = SERIAL_VALUE_LEN(serial); char value_buf[len + 1]; memcpy(value_buf, pi->value, len); value_buf[len] = '\0'; // TODO: see todo in __system_property_read function atomic_thread_fence(memory_order_acquire); if (serial == load_const_atomic(&(pi->serial), memory_order_relaxed)) { callback(cookie, pi->name, value_buf, serial); return; } } }
int mb__system_property_read(const prop_info* pi, char* name, char* value) { #if MB_ENABLE_COMPAT_PROPERTIES if (__predict_false(compat_mode)) { return mb__system_property_read_compat(pi, name, value); } #endif while (true) { uint32_t serial = mb__system_property_serial(pi); // acquire semantics size_t len = SERIAL_VALUE_LEN(serial); memcpy(value, pi->value, len + 1); // TODO: Fix the synchronization scheme here. // There is no fully supported way to implement this kind // of synchronization in C++11, since the memcpy races with // updates to pi, and the data being accessed is not atomic. // The following fence is unintuitive, but would be the // correct one if memcpy used memory_order_relaxed atomic accesses. // In practice it seems unlikely that the generated code would // would be any different, so this should be OK. atomic_thread_fence(memory_order_acquire); if (serial == load_const_atomic(&(pi->serial), memory_order_relaxed)) { if (name != nullptr) { size_t namelen = strlcpy(name, pi->name, PROP_NAME_MAX); if (namelen >= PROP_NAME_MAX) { LOGE("The property name length for \"%s\" is >= %d;" " please use __system_property_read_callback" " to read this property. (the name is truncated to \"%s\")", pi->name, PROP_NAME_MAX - 1, name); } } return len; } } }
int __system_property_read(const prop_info *pi, char *name, char *value) { unsigned serial, len; for(;;) { serial = *(unsigned*)((char*)pi + prop_name_max); while(SERIAL_DIRTY(serial)) { __futex_wait((volatile void *)((char*)pi + prop_name_max), serial, 0); serial = *(unsigned*)((char*)pi + prop_name_max); } len = SERIAL_VALUE_LEN(serial); memcpy(value, (char*)pi + prop_name_max + sizeof(pi->serial), len + 1); if(serial == *(unsigned*)((char*)pi + prop_name_max)) { if(name != 0) { strcpy(name, pi->name); } return len; } } }
int SystemProperties::Read(const prop_info* pi, char* name, char* value) { while (true) { uint32_t serial = Serial(pi); // acquire semantics size_t len = SERIAL_VALUE_LEN(serial); memcpy(value, pi->value, len + 1); // TODO: Fix the synchronization scheme here. // There is no fully supported way to implement this kind // of synchronization in C++11, since the memcpy races with // updates to pi, and the data being accessed is not atomic. // The following fence is unintuitive, but would be the // correct one if memcpy used memory_order_relaxed atomic accesses. // In practice it seems unlikely that the generated code would // would be any different, so this should be OK. atomic_thread_fence(memory_order_acquire); if (serial == load_const_atomic(&(pi->serial), memory_order_relaxed)) { if (name != nullptr) { size_t namelen = strlcpy(name, pi->name, PROP_NAME_MAX); if (namelen >= PROP_NAME_MAX) { async_safe_format_log(ANDROID_LOG_ERROR, "libc", "The property name length for \"%s\" is >= %d;" " please use __system_property_read_callback" " to read this property. (the name is truncated to \"%s\")", pi->name, PROP_NAME_MAX - 1, name); } } if (is_read_only(pi->name) && pi->is_long()) { async_safe_format_log( ANDROID_LOG_ERROR, "libc", "The property \"%s\" has a value with length %zu that is too large for" " __system_property_get()/__system_property_read(); use" " __system_property_read_callback() instead.", pi->name, strlen(pi->long_value())); } return len; } } }