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; } } }
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; } } }