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;
    }
  }
}
Beispiel #3
0
/**
 * 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;
    }
  }
}