Added IPCThreadState::blockUntilThreadAvailable() method.
Will be used by the system_server watchdog to monitor the availability of binder threads in the process to handle incoming IPC requests. Bug: 19297165 Change-Id: I39175f3869ad14da5620fddb47f454e6e4ee2b25
This commit is contained in:
parent
e88e366963
commit
376b822728
|
@ -76,14 +76,18 @@ public:
|
||||||
BpBinder* proxy);
|
BpBinder* proxy);
|
||||||
|
|
||||||
static void shutdown();
|
static void shutdown();
|
||||||
|
|
||||||
// Call this to disable switching threads to background scheduling when
|
// Call this to disable switching threads to background scheduling when
|
||||||
// receiving incoming IPC calls. This is specifically here for the
|
// receiving incoming IPC calls. This is specifically here for the
|
||||||
// Android system process, since it expects to have background apps calling
|
// Android system process, since it expects to have background apps calling
|
||||||
// in to it but doesn't want to acquire locks in its services while in
|
// in to it but doesn't want to acquire locks in its services while in
|
||||||
// the background.
|
// the background.
|
||||||
static void disableBackgroundScheduling(bool disable);
|
static void disableBackgroundScheduling(bool disable);
|
||||||
|
|
||||||
|
// Call blocks until the number of executing binder threads is less than
|
||||||
|
// the maximum number of binder threads threads allowed for this process.
|
||||||
|
void blockUntilThreadAvailable();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IPCThreadState();
|
IPCThreadState();
|
||||||
~IPCThreadState();
|
~IPCThreadState();
|
||||||
|
@ -101,9 +105,9 @@ private:
|
||||||
status_t getAndExecuteCommand();
|
status_t getAndExecuteCommand();
|
||||||
status_t executeCommand(int32_t command);
|
status_t executeCommand(int32_t command);
|
||||||
void processPendingDerefs();
|
void processPendingDerefs();
|
||||||
|
|
||||||
void clearCaller();
|
void clearCaller();
|
||||||
|
|
||||||
static void threadDestructor(void *st);
|
static void threadDestructor(void *st);
|
||||||
static void freeBuffer(Parcel* parcel,
|
static void freeBuffer(Parcel* parcel,
|
||||||
const uint8_t* data, size_t dataSize,
|
const uint8_t* data, size_t dataSize,
|
||||||
|
@ -114,7 +118,7 @@ private:
|
||||||
const pid_t mMyThreadId;
|
const pid_t mMyThreadId;
|
||||||
Vector<BBinder*> mPendingStrongDerefs;
|
Vector<BBinder*> mPendingStrongDerefs;
|
||||||
Vector<RefBase::weakref_type*> mPendingWeakDerefs;
|
Vector<RefBase::weakref_type*> mPendingWeakDerefs;
|
||||||
|
|
||||||
Parcel mIn;
|
Parcel mIn;
|
||||||
Parcel mOut;
|
Parcel mOut;
|
||||||
status_t mLastError;
|
status_t mLastError;
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
|
|
||||||
#include <utils/threads.h>
|
#include <utils/threads.h>
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
|
@ -71,25 +73,33 @@ private:
|
||||||
ProcessState(const ProcessState& o);
|
ProcessState(const ProcessState& o);
|
||||||
ProcessState& operator=(const ProcessState& o);
|
ProcessState& operator=(const ProcessState& o);
|
||||||
String8 makeBinderThreadName();
|
String8 makeBinderThreadName();
|
||||||
|
|
||||||
struct handle_entry {
|
struct handle_entry {
|
||||||
IBinder* binder;
|
IBinder* binder;
|
||||||
RefBase::weakref_type* refs;
|
RefBase::weakref_type* refs;
|
||||||
};
|
};
|
||||||
|
|
||||||
handle_entry* lookupHandleLocked(int32_t handle);
|
handle_entry* lookupHandleLocked(int32_t handle);
|
||||||
|
|
||||||
int mDriverFD;
|
int mDriverFD;
|
||||||
void* mVMStart;
|
void* mVMStart;
|
||||||
|
|
||||||
|
// Protects thread count variable below.
|
||||||
|
pthread_mutex_t mThreadCountLock;
|
||||||
|
pthread_cond_t mThreadCountDecrement;
|
||||||
|
// Number of binder threads current executing a command.
|
||||||
|
size_t mExecutingThreadsCount;
|
||||||
|
// Maximum number for binder threads allowed for this process.
|
||||||
|
size_t mMaxThreads;
|
||||||
|
|
||||||
mutable Mutex mLock; // protects everything below.
|
mutable Mutex mLock; // protects everything below.
|
||||||
|
|
||||||
Vector<handle_entry>mHandleToObject;
|
Vector<handle_entry>mHandleToObject;
|
||||||
|
|
||||||
bool mManagesContexts;
|
bool mManagesContexts;
|
||||||
context_check_func mBinderContextCheckFunc;
|
context_check_func mBinderContextCheckFunc;
|
||||||
void* mBinderContextUserData;
|
void* mBinderContextUserData;
|
||||||
|
|
||||||
KeyedVector<String16, sp<IBinder> >
|
KeyedVector<String16, sp<IBinder> >
|
||||||
mContexts;
|
mContexts;
|
||||||
|
|
||||||
|
|
|
@ -399,6 +399,17 @@ void IPCThreadState::flushCommands()
|
||||||
talkWithDriver(false);
|
talkWithDriver(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IPCThreadState::blockUntilThreadAvailable()
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&mProcess->mThreadCountLock);
|
||||||
|
while (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads) {
|
||||||
|
ALOGW("Waiting for thread to be free. mExecutingThreadsCount=%i mMaxThreads=%i\n",
|
||||||
|
mProcess->mExecutingThreadsCount, mProcess->mMaxThreads);
|
||||||
|
pthread_cond_wait(&mProcess->mThreadCountDecrement, &mProcess->mThreadCountLock);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&mProcess->mThreadCountLock);
|
||||||
|
}
|
||||||
|
|
||||||
status_t IPCThreadState::getAndExecuteCommand()
|
status_t IPCThreadState::getAndExecuteCommand()
|
||||||
{
|
{
|
||||||
status_t result;
|
status_t result;
|
||||||
|
@ -414,8 +425,17 @@ status_t IPCThreadState::getAndExecuteCommand()
|
||||||
<< getReturnString(cmd) << endl;
|
<< getReturnString(cmd) << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&mProcess->mThreadCountLock);
|
||||||
|
mProcess->mExecutingThreadsCount++;
|
||||||
|
pthread_mutex_unlock(&mProcess->mThreadCountLock);
|
||||||
|
|
||||||
result = executeCommand(cmd);
|
result = executeCommand(cmd);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&mProcess->mThreadCountLock);
|
||||||
|
mProcess->mExecutingThreadsCount--;
|
||||||
|
pthread_cond_broadcast(&mProcess->mThreadCountDecrement);
|
||||||
|
pthread_mutex_unlock(&mProcess->mThreadCountLock);
|
||||||
|
|
||||||
// After executing the command, ensure that the thread is returned to the
|
// After executing the command, ensure that the thread is returned to the
|
||||||
// foreground cgroup before rejoining the pool. The driver takes care of
|
// foreground cgroup before rejoining the pool. The driver takes care of
|
||||||
// restoring the priority, but doesn't do anything with cgroups so we
|
// restoring the priority, but doesn't do anything with cgroups so we
|
||||||
|
|
|
@ -42,12 +42,13 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
|
#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
|
||||||
|
#define DEFAULT_MAX_BINDER_THREADS 15
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
class PoolThread : public Thread
|
class PoolThread : public Thread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -294,7 +295,9 @@ void ProcessState::spawnPooledThread(bool isMain)
|
||||||
|
|
||||||
status_t ProcessState::setThreadPoolMaxThreadCount(size_t maxThreads) {
|
status_t ProcessState::setThreadPoolMaxThreadCount(size_t maxThreads) {
|
||||||
status_t result = NO_ERROR;
|
status_t result = NO_ERROR;
|
||||||
if (ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &maxThreads) == -1) {
|
if (ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &maxThreads) != -1) {
|
||||||
|
mMaxThreads = maxThreads;
|
||||||
|
} else {
|
||||||
result = -errno;
|
result = -errno;
|
||||||
ALOGE("Binder ioctl to set max threads failed: %s", strerror(-result));
|
ALOGE("Binder ioctl to set max threads failed: %s", strerror(-result));
|
||||||
}
|
}
|
||||||
|
@ -322,7 +325,7 @@ static int open_driver()
|
||||||
close(fd);
|
close(fd);
|
||||||
fd = -1;
|
fd = -1;
|
||||||
}
|
}
|
||||||
size_t maxThreads = 15;
|
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
|
||||||
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
|
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
|
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
|
||||||
|
@ -336,6 +339,10 @@ static int open_driver()
|
||||||
ProcessState::ProcessState()
|
ProcessState::ProcessState()
|
||||||
: mDriverFD(open_driver())
|
: mDriverFD(open_driver())
|
||||||
, mVMStart(MAP_FAILED)
|
, mVMStart(MAP_FAILED)
|
||||||
|
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
|
||||||
|
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
|
||||||
|
, mExecutingThreadsCount(0)
|
||||||
|
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
|
||||||
, mManagesContexts(false)
|
, mManagesContexts(false)
|
||||||
, mBinderContextCheckFunc(NULL)
|
, mBinderContextCheckFunc(NULL)
|
||||||
, mBinderContextUserData(NULL)
|
, mBinderContextUserData(NULL)
|
||||||
|
|
Loading…
Reference in New Issue