platform_system_core/liblog/rwlock.h
Tom Cherry 2a6811b4d1 liblog: use a rwlock for writer initialization
The current system of using atomics isn't thread safe and may result
in doubly closing FDs or closing actively used FDs.  The safest way to
do this is to use a rwlock, which should not have a much higher
overhead than the atomics do, as a vast majority of the time, there
will not be writers.

This moves us further away from using the transport interface, which
will be removed.  Each writer should be self contained, without a
separate open or available function.

Also, keep the pmsg fd open if it is opened by
__android_log_pmsg_file_write().  This fd was closed due to issues
with zygote, but it looks like it is only called by recovery now, so
there is no reason to close this fd at the end of that function.

Test: logging works, liblog-unit-tests
Change-Id: I345c9a5d18c55b11a280c8362df854784abf46fd
2019-12-12 16:19:08 -08:00

39 lines
1.3 KiB
C++

/*
* Copyright (C) 2019 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.
*/
#pragma once
#include <pthread.h>
// As of the end of Dec 2019, std::shared_mutex is *not* simply a pthread_rwlock, but rather a
// combination of std::mutex and std::condition variable, which is obviously less efficient. This
// immitates what std::shared_mutex should be doing and is compatible with std::shared_lock and
// std::unique_lock.
class RwLock {
public:
RwLock() {}
~RwLock() {}
void lock() { pthread_rwlock_wrlock(&rwlock_); }
void unlock() { pthread_rwlock_unlock(&rwlock_); }
void lock_shared() { pthread_rwlock_rdlock(&rwlock_); }
void unlock_shared() { pthread_rwlock_unlock(&rwlock_); }
private:
pthread_rwlock_t rwlock_ = PTHREAD_RWLOCK_INITIALIZER;
};