From 26bc1aefec6d048996b5f1f7d0dbcf01bd743815 Mon Sep 17 00:00:00 2001 From: Pierre Langlois Date: Wed, 14 Jan 2015 18:55:29 +0000 Subject: libkdbinder: import ProcessState and IPCThreadState ProcessState and IPCThreadState are respectively per process and per thread objects. The ProcessState object is a singleton and IPCThreadState is stored in thread local storage. ProcessState is responsible for managing a thread pool for servers. IPCThreadState represents a thread that can either wait for incoming transactions or issue one to another thread connected to the bus. This brings the following (partially implemented) API: - static ProcessState::self() Get the ProcessState object for the current process, create it if it does not exist. - ProcessState::startThreadPool() - ProcessState::spawnPooledThread() - ProcessState::getStrongProxyForHandle(int32_t handle) Return a binder proxy object (BpBinder) corresponding to the given handle. Contrary to Binder, handle 0 is be invalid and does not represent the service manager. - ProcessState::setThreadPoolMaxThreadCount(size_t maxThreads) - static IPCThreadState::self() Get the IPCThreadState object for the current thread, create it if it does not exist. - IPCThreadState::getCallingPid() - IPCThreadState::getCallingUid() - IPCThreadState::flushCommands(); This call makes sure that all pending commands to binder are done. We do not need this. - IPCThreadState::joinThreadPool() Add the current thread to the process's thread pool. This call is blocking as each thread in the pool awaits for incoming transactions. - IPCThreadState::stopProcess() - IPCThreadState::transact(int32_t handle, uint32_t code, // const Parcel& data, // Parcel *reply, uint32_t flags = 0) Issue a transaction to the BpBinder object refered to by handle on the bus. - IPCThreadState::requestDeathNotification(int32_t handle, BpBinder *proxy); - IPCThreadState::clearDeathNotification(int32_t handle, BpBinder *proxy); Get the current thread to call proxy when the given handle dies. Change-Id: I40e6972dfdc6df1d28f043c88fd442b0e13b5d01 --- include/kdbinder/binder/IPCThreadState.h | 62 +++++++++++++++ include/kdbinder/binder/ProcessState.h | 55 +++++++++++++ include/kdbinder/private/binder/Static.h | 34 ++++++++ libs/kdbinder/Android.mk | 3 + libs/kdbinder/binder/IPCThreadState.cpp | 131 +++++++++++++++++++++++++++++++ libs/kdbinder/binder/ProcessState.cpp | 59 ++++++++++++++ libs/kdbinder/binder/Static.cpp | 27 +++++++ 7 files changed, 371 insertions(+) create mode 100644 include/kdbinder/binder/IPCThreadState.h create mode 100644 include/kdbinder/binder/ProcessState.h create mode 100644 include/kdbinder/private/binder/Static.h create mode 100644 libs/kdbinder/binder/IPCThreadState.cpp create mode 100644 libs/kdbinder/binder/ProcessState.cpp create mode 100644 libs/kdbinder/binder/Static.cpp diff --git a/include/kdbinder/binder/IPCThreadState.h b/include/kdbinder/binder/IPCThreadState.h new file mode 100644 index 0000000..776eefa --- /dev/null +++ b/include/kdbinder/binder/IPCThreadState.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2015 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. + */ + +#ifndef INCLUDE_KDBINDER_BINDER_IPCTHREADSTATE_H_ +#define INCLUDE_KDBINDER_BINDER_IPCTHREADSTATE_H_ + +#include + +#include +#include + +namespace android { + +class IPCThreadState : public virtual RefBase { + public: + static IPCThreadState* self(); + + pid_t getCallingPid() const; + uid_t getCallingUid() const; + + void flushCommands(); + + void joinThreadPool(bool isMain = true); + + void stopProcess(bool immediate = true); + + status_t transact(int32_t handle, + uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); + + status_t requestDeathNotification(int32_t handle, + BpBinder *proxy); + status_t clearDeathNotification(int32_t handle, + BpBinder *proxy); + + private: + IPCThreadState(); + ~IPCThreadState() {} + + static void threadDestructor(void *st); + + const pid_t mMyThreadId; +}; + +} // namespace android + +#endif // INCLUDE_KDBINDER_BINDER_IPCTHREADSTATE_H_ diff --git a/include/kdbinder/binder/ProcessState.h b/include/kdbinder/binder/ProcessState.h new file mode 100644 index 0000000..e2fe43d --- /dev/null +++ b/include/kdbinder/binder/ProcessState.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2015 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. + */ + +#ifndef INCLUDE_KDBINDER_BINDER_PROCESSSTATE_H_ +#define INCLUDE_KDBINDER_BINDER_PROCESSSTATE_H_ + +#include + +#include +#include + +namespace android { + +class ProcessState : public virtual RefBase { + public: + static sp self(); + + void startThreadPool(); + + void spawnPooledThread(bool isMain); + + sp getStrongProxyForHandle(int32_t handle); + + status_t setThreadPoolMaxThreadCount(size_t maxThreads); + + private: + friend class IPCThreadState; + + ProcessState(); + ~ProcessState() = default; + + ProcessState(const ProcessState& o); + ProcessState& operator=(const ProcessState& o); + + mutable Mutex mLock; // protects everything below. + bool mThreadPoolStarted; + volatile int32_t mThreadPoolSeq; +}; + +} // namespace android + +#endif // INCLUDE_KDBINDER_BINDER_PROCESSSTATE_H_ diff --git a/include/kdbinder/private/binder/Static.h b/include/kdbinder/private/binder/Static.h new file mode 100644 index 0000000..fb5743d --- /dev/null +++ b/include/kdbinder/private/binder/Static.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2015 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. + */ + +// All static variables go here, to control initialization and +// destruction order in the library. + +#ifndef INCLUDE_PRIVATE_KDBINDER_STATIC_H_ +#define INCLUDE_PRIVATE_KDBINDER_STATIC_H_ + +#include + +#include + +namespace android { + +extern Mutex gProcessMutex; +extern sp gProcess; + +} // namespace android + +#endif // INCLUDE_PRIVATE_KDBINDER_STATIC_H_ diff --git a/libs/kdbinder/Android.mk b/libs/kdbinder/Android.mk index 3546d13..3e94fd2 100644 --- a/libs/kdbinder/Android.mk +++ b/libs/kdbinder/Android.mk @@ -16,6 +16,9 @@ kdbinder_sources := \ binder/Binder.cpp \ binder/BpBinder.cpp \ binder/IInterface.cpp \ + binder/ProcessState.cpp \ + binder/IPCThreadState.cpp \ + binder/Static.cpp \ kdbus/bus.cpp \ kdbus/connection.cpp \ kdbus/iterable.cpp \ diff --git a/libs/kdbinder/binder/IPCThreadState.cpp b/libs/kdbinder/binder/IPCThreadState.cpp new file mode 100644 index 0000000..3b6969c --- /dev/null +++ b/libs/kdbinder/binder/IPCThreadState.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2015 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. + */ + +#if LOG_NDEBUG +#define LOG_THREADPOOL(...) +#else +#define LOG_THREADPOOL(...) ALOG(LOG_DEBUG, "threadpool", __VA_ARGS__) +#endif + +#include + +#include + +#include +#include + +#include + +namespace android { + +static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER; +static bool gHaveTLS = false; +static pthread_key_t gTLS = 0; + +thread_local IPCThreadState* TLS; + +IPCThreadState::IPCThreadState() + : mMyThreadId(gettid()) { + pthread_setspecific(gTLS, this); +} + +void IPCThreadState::threadDestructor(void *st) { + IPCThreadState* const self = static_cast(st); + delete self; +} + +IPCThreadState* IPCThreadState::self() { + if (gHaveTLS) { +restart: + const pthread_key_t k = gTLS; + IPCThreadState* st = static_cast(pthread_getspecific(k)); + if (st != nullptr) { + return st; + } + return new IPCThreadState; + } + + pthread_mutex_lock(&gTLSMutex); + if (!gHaveTLS) { + if (pthread_key_create(&gTLS, threadDestructor) != 0) { + pthread_mutex_unlock(&gTLSMutex); + return nullptr; + } + gHaveTLS = true; + } + pthread_mutex_unlock(&gTLSMutex); + goto restart; +} + +pid_t IPCThreadState::getCallingPid() const { + // TODO: unimplemented. + return 0; +} + +uid_t IPCThreadState::getCallingUid() const { + // TODO: unimplemented. + return 0; +} + +void IPCThreadState::flushCommands() { + // TODO: unimplemented. +} + +void IPCThreadState::joinThreadPool(bool /*isMain*/) { + LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", + (void*)pthread_self(), getpid()); + + // This thread may have been spawned by a thread that was in the background + // scheduling group, so first we will make sure it is in the foreground + // one to avoid performing an initial transaction in the background. + set_sched_policy(mMyThreadId, SP_FOREGROUND); + + int result = 0; + + do { + // TODO: Handle incoming messages. + } while (result == 0); + + LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%u\n", + (void*)pthread_self(), getpid(), result); +} + +void IPCThreadState::stopProcess(bool /*immediate*/) { + // TODO: unimplemented. +} + +status_t IPCThreadState::transact(int32_t /*handle*/, + uint32_t /*code*/, + const Parcel& /*data*/, + Parcel* /*reply*/, + uint32_t /*flags*/) { + // TODO: Send a message. + return UNKNOWN_TRANSACTION; +} + +status_t IPCThreadState::requestDeathNotification(int32_t /*handle*/, + BpBinder * /*proxy*/) { + // TODO: unimplemented. + return UNKNOWN_TRANSACTION; +} + +status_t IPCThreadState::clearDeathNotification(int32_t /*handle*/, + BpBinder * /*proxy*/) { + // TODO: unimplemented. + return UNKNOWN_TRANSACTION; +} + +} // namespace android diff --git a/libs/kdbinder/binder/ProcessState.cpp b/libs/kdbinder/binder/ProcessState.cpp new file mode 100644 index 0000000..225fb01 --- /dev/null +++ b/libs/kdbinder/binder/ProcessState.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2015 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. + */ +#define LOG_TAG "kdbinder.ProcessState" + +#include +#include +#include + +namespace android { + +ProcessState::ProcessState() : mThreadPoolStarted(false) { + // TODO: unimplemented. +} + +sp ProcessState::self() { + Mutex::Autolock _l(gProcessMutex); + if (gProcess != NULL) { + return gProcess; + } + gProcess = new ProcessState; + return gProcess; +} + +void ProcessState::startThreadPool() { + AutoMutex _l(mLock); + if (!mThreadPoolStarted) { + mThreadPoolStarted = true; + spawnPooledThread(true); + } +} + +void ProcessState::spawnPooledThread(bool /*isMain*/) { + // TODO: unimplemented. +} + +sp ProcessState::getStrongProxyForHandle(int32_t /*handle*/) { + // TODO: unimplemented. + return NULL; +} + +status_t ProcessState::setThreadPoolMaxThreadCount(size_t /*maxThreads*/) { + // TODO: unimplemented. + return NO_ERROR; +} + +} // namespace android diff --git a/libs/kdbinder/binder/Static.cpp b/libs/kdbinder/binder/Static.cpp new file mode 100644 index 0000000..7c87a69 --- /dev/null +++ b/libs/kdbinder/binder/Static.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2015 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. + */ + +// All static variables go here, to control initialization and +// destruction order in the library. + +#include + +namespace android { + +Mutex gProcessMutex; +sp gProcess; + +} // namespace android -- cgit v1.2.3