liblog: don't cache property size values and move to own file
Don't cache the property size values since they're only queried at the start of logd and only once during dumpstate. Initializing SerializedLogBuffer, which includes all of the logd queries, takes under 100us without the cache, certainly fast enough that this cache is unneeded. Move these functions to their own file in preparation for removing them from liblog. Test: log sizes set appropriately Change-Id: I15a2fd687dcffb4eab2f22ee0825ca86e40cdba3
This commit is contained in:
parent
fcaed0effa
commit
d2743ef5c9
|
@ -17,6 +17,7 @@
|
|||
liblog_sources = [
|
||||
"log_event_list.cpp",
|
||||
"log_event_write.cpp",
|
||||
"log_size.cpp",
|
||||
"logger_name.cpp",
|
||||
"logger_read.cpp",
|
||||
"logger_write.cpp",
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <private/android_logger.h>
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include <android-base/parseint.h>
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <sys/system_properties.h>
|
||||
#endif
|
||||
|
||||
bool __android_logger_valid_buffer_size(unsigned long value) {
|
||||
return LOG_BUFFER_MIN_SIZE <= value && value <= LOG_BUFFER_MAX_SIZE;
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
static std::optional<unsigned long> GetBufferSizeProperty(const std::string& key) {
|
||||
char value[PROP_VALUE_MAX] = {};
|
||||
if (__system_property_get(key.c_str(), value) <= 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
uint32_t size;
|
||||
if (!android::base::ParseByteCount(value, &size)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!__android_logger_valid_buffer_size(size)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
unsigned long __android_logger_get_buffer_size(log_id_t log_id) {
|
||||
std::string buffer_name = android_log_id_to_name(log_id);
|
||||
std::array<std::string, 4> properties = {
|
||||
"persist.logd.size." + buffer_name,
|
||||
"ro.logd.size." + buffer_name,
|
||||
"persist.logd.size",
|
||||
"ro.logd.size",
|
||||
};
|
||||
|
||||
for (const auto& property : properties) {
|
||||
if (auto size = GetBufferSizeProperty(property)) {
|
||||
return *size;
|
||||
}
|
||||
}
|
||||
|
||||
char value[PROP_VALUE_MAX] = {};
|
||||
if (__system_property_get("ro.config.low_ram", value) > 0 && !strcmp(value, "true")) {
|
||||
return LOG_BUFFER_MIN_SIZE;
|
||||
}
|
||||
|
||||
return LOG_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Default to 1MB for host.
|
||||
unsigned long __android_logger_get_buffer_size(log_id_t) {
|
||||
return 1024 * 1024;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -364,153 +364,6 @@ int __android_log_security() {
|
|||
return do_cache2_char(&security);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interface that represents the logd buffer size determination so that others
|
||||
* need not guess our intentions.
|
||||
*/
|
||||
|
||||
/* cache structure */
|
||||
struct cache_property {
|
||||
struct cache cache;
|
||||
char property[PROP_VALUE_MAX];
|
||||
};
|
||||
|
||||
static void refresh_cache_property(struct cache_property* cache, const char* key) {
|
||||
if (!cache->cache.pinfo) {
|
||||
cache->cache.pinfo = __system_property_find(key);
|
||||
if (!cache->cache.pinfo) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
cache->cache.serial = __system_property_serial(cache->cache.pinfo);
|
||||
__system_property_read(cache->cache.pinfo, 0, cache->property);
|
||||
}
|
||||
|
||||
bool __android_logger_valid_buffer_size(unsigned long value) {
|
||||
return LOG_BUFFER_MIN_SIZE <= value && value <= LOG_BUFFER_MAX_SIZE;
|
||||
}
|
||||
|
||||
struct cache2_property_size {
|
||||
pthread_mutex_t lock;
|
||||
uint32_t serial;
|
||||
const char* key_persist;
|
||||
struct cache_property cache_persist;
|
||||
const char* key_ro;
|
||||
struct cache_property cache_ro;
|
||||
unsigned long (*const evaluate)(const struct cache2_property_size* self);
|
||||
};
|
||||
|
||||
static inline unsigned long do_cache2_property_size(struct cache2_property_size* self) {
|
||||
uint32_t current_serial;
|
||||
int change_detected;
|
||||
unsigned long v;
|
||||
|
||||
if (pthread_mutex_trylock(&self->lock)) {
|
||||
/* We are willing to accept some race in this context */
|
||||
return self->evaluate(self);
|
||||
}
|
||||
|
||||
change_detected = check_cache(&self->cache_persist.cache) || check_cache(&self->cache_ro.cache);
|
||||
current_serial = __system_property_area_serial();
|
||||
if (current_serial != self->serial) {
|
||||
change_detected = 1;
|
||||
}
|
||||
if (change_detected) {
|
||||
refresh_cache_property(&self->cache_persist, self->key_persist);
|
||||
refresh_cache_property(&self->cache_ro, self->key_ro);
|
||||
self->serial = current_serial;
|
||||
}
|
||||
v = self->evaluate(self);
|
||||
|
||||
pthread_mutex_unlock(&self->lock);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static unsigned long property_get_size_from_cache(const struct cache_property* cache) {
|
||||
char* cp;
|
||||
unsigned long value = strtoul(cache->property, &cp, 10);
|
||||
|
||||
switch (*cp) {
|
||||
case 'm':
|
||||
case 'M':
|
||||
value *= 1024;
|
||||
[[fallthrough]];
|
||||
case 'k':
|
||||
case 'K':
|
||||
value *= 1024;
|
||||
[[fallthrough]];
|
||||
case '\0':
|
||||
break;
|
||||
|
||||
default:
|
||||
value = 0;
|
||||
}
|
||||
|
||||
if (!__android_logger_valid_buffer_size(value)) {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static unsigned long evaluate_property_get_size(const struct cache2_property_size* self) {
|
||||
unsigned long size = property_get_size_from_cache(&self->cache_persist);
|
||||
if (size) {
|
||||
return size;
|
||||
}
|
||||
return property_get_size_from_cache(&self->cache_ro);
|
||||
}
|
||||
|
||||
unsigned long __android_logger_get_buffer_size(log_id_t logId) {
|
||||
static const char global_tunable[] = "persist.logd.size"; /* Settings App */
|
||||
static const char global_default[] = "ro.logd.size"; /* BoardConfig.mk */
|
||||
static struct cache2_property_size global = {
|
||||
/* clang-format off */
|
||||
PTHREAD_MUTEX_INITIALIZER, 0,
|
||||
global_tunable, { { NULL, 0xFFFFFFFF }, {} },
|
||||
global_default, { { NULL, 0xFFFFFFFF }, {} },
|
||||
evaluate_property_get_size
|
||||
/* clang-format on */
|
||||
};
|
||||
char key_persist[strlen(global_tunable) + strlen(".security") + 1];
|
||||
char key_ro[strlen(global_default) + strlen(".security") + 1];
|
||||
struct cache2_property_size local = {
|
||||
/* clang-format off */
|
||||
PTHREAD_MUTEX_INITIALIZER, 0,
|
||||
key_persist, { { NULL, 0xFFFFFFFF }, {} },
|
||||
key_ro, { { NULL, 0xFFFFFFFF }, {} },
|
||||
evaluate_property_get_size
|
||||
/* clang-format on */
|
||||
};
|
||||
unsigned long property_size, default_size;
|
||||
|
||||
default_size = do_cache2_property_size(&global);
|
||||
if (!default_size) {
|
||||
char value[PROP_VALUE_MAX] = {};
|
||||
if (__system_property_get("ro.config.low_ram", value) == 0 || strcmp(value, "true") != 0) {
|
||||
default_size = LOG_BUFFER_SIZE;
|
||||
} else {
|
||||
default_size = LOG_BUFFER_MIN_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(key_persist, sizeof(key_persist), "%s.%s", global_tunable,
|
||||
android_log_id_to_name(logId));
|
||||
snprintf(key_ro, sizeof(key_ro), "%s.%s", global_default, android_log_id_to_name(logId));
|
||||
property_size = do_cache2_property_size(&local);
|
||||
|
||||
if (!property_size) {
|
||||
property_size = default_size;
|
||||
}
|
||||
|
||||
if (!property_size) {
|
||||
property_size = LOG_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
return property_size;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int __android_log_is_loggable(int prio, const char*, int) {
|
||||
|
|
|
@ -34,16 +34,6 @@ using android::base::Join;
|
|||
using android::base::Split;
|
||||
using android::base::StringPrintf;
|
||||
|
||||
#ifndef __ANDROID__
|
||||
unsigned long __android_logger_get_buffer_size(log_id_t) {
|
||||
return 1024 * 1024;
|
||||
}
|
||||
|
||||
bool __android_logger_valid_buffer_size(unsigned long) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
char* android::uidToName(uid_t) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -40,17 +40,6 @@ using android::base::ParseInt;
|
|||
using android::base::ParseUint;
|
||||
using android::base::Split;
|
||||
|
||||
#ifndef __ANDROID__
|
||||
// This is hard coded to 1MB on host. On device use persist.logd.size to configure.
|
||||
unsigned long __android_logger_get_buffer_size(log_id_t) {
|
||||
return 1 * 1024 * 1024;
|
||||
}
|
||||
|
||||
bool __android_logger_valid_buffer_size(unsigned long) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
char* android::uidToName(uid_t) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -30,16 +30,6 @@
|
|||
#define MIN_TAG_ID 1000
|
||||
#define TAG_MOD 10
|
||||
|
||||
#ifndef __ANDROID__
|
||||
unsigned long __android_logger_get_buffer_size(log_id_t) {
|
||||
return 1024 * 1024;
|
||||
}
|
||||
|
||||
bool __android_logger_valid_buffer_size(unsigned long) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
char* android::uidToName(uid_t) {
|
||||
return strdup("fake");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue