am 24eca800: Merge change I887f355f into eclair-mr2
Merge commit '24eca800d4b34e7d13fbcbc1ab74c9d91ff6a4e1' into eclair-mr2-plus-aosp * commit '24eca800d4b34e7d13fbcbc1ab74c9d91ff6a4e1': Propagate background scheduling class across processes.
This commit is contained in:
@@ -76,6 +76,13 @@ public class BinderInternal {
|
||||
*/
|
||||
public static final native IBinder getContextObject();
|
||||
|
||||
/**
|
||||
* Special for system process to not allow incoming calls to run at
|
||||
* background scheduling priority.
|
||||
* @hide
|
||||
*/
|
||||
public static final native void disableBackgroundScheduling(boolean disable);
|
||||
|
||||
static native final void handleGc();
|
||||
|
||||
public static void forceGc(String reason) {
|
||||
|
||||
@@ -670,6 +670,12 @@ static void android_os_BinderInternal_joinThreadPool(JNIEnv* env, jobject clazz)
|
||||
android::IPCThreadState::self()->joinThreadPool();
|
||||
}
|
||||
|
||||
static void android_os_BinderInternal_disableBackgroundScheduling(JNIEnv* env,
|
||||
jobject clazz, jboolean disable)
|
||||
{
|
||||
IPCThreadState::disableBackgroundScheduling(disable ? true : false);
|
||||
}
|
||||
|
||||
static void android_os_BinderInternal_handleGc(JNIEnv* env, jobject clazz)
|
||||
{
|
||||
LOGV("Gc has executed, clearing binder ops");
|
||||
@@ -682,6 +688,7 @@ static const JNINativeMethod gBinderInternalMethods[] = {
|
||||
/* name, signature, funcPtr */
|
||||
{ "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
|
||||
{ "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool },
|
||||
{ "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },
|
||||
{ "handleGc", "()V", (void*)android_os_BinderInternal_handleGc }
|
||||
};
|
||||
|
||||
|
||||
@@ -120,11 +120,7 @@ jint android_os_Process_myUid(JNIEnv* env, jobject clazz)
|
||||
|
||||
jint android_os_Process_myTid(JNIEnv* env, jobject clazz)
|
||||
{
|
||||
#ifdef HAVE_GETTID
|
||||
return gettid();
|
||||
#else
|
||||
return getpid();
|
||||
#endif
|
||||
return androidGetTid();
|
||||
}
|
||||
|
||||
jint android_os_Process_getUidForName(JNIEnv* env, jobject clazz, jstring name)
|
||||
@@ -191,15 +187,11 @@ jint android_os_Process_getGidForName(JNIEnv* env, jobject clazz, jstring name)
|
||||
|
||||
void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
|
||||
{
|
||||
if (grp > ANDROID_TGROUP_MAX || grp < 0) {
|
||||
signalExceptionForGroupError(env, clazz, EINVAL);
|
||||
int res = androidSetThreadSchedulingGroup(pid, grp);
|
||||
if (res != NO_ERROR) {
|
||||
signalExceptionForGroupError(env, clazz, res == BAD_VALUE ? EINVAL : errno);
|
||||
return;
|
||||
}
|
||||
|
||||
if (set_sched_policy(pid, (grp == ANDROID_TGROUP_BG_NONINTERACT) ?
|
||||
SP_BACKGROUND : SP_FOREGROUND)) {
|
||||
signalExceptionForGroupError(env, clazz, errno);
|
||||
}
|
||||
}
|
||||
|
||||
void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
|
||||
@@ -275,22 +267,15 @@ void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jin
|
||||
void android_os_Process_setThreadPriority(JNIEnv* env, jobject clazz,
|
||||
jint pid, jint pri)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (pri >= ANDROID_PRIORITY_BACKGROUND) {
|
||||
rc = set_sched_policy(pid, SP_BACKGROUND);
|
||||
} else if (getpriority(PRIO_PROCESS, pid) >= ANDROID_PRIORITY_BACKGROUND) {
|
||||
rc = set_sched_policy(pid, SP_FOREGROUND);
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
signalExceptionForGroupError(env, clazz, errno);
|
||||
return;
|
||||
}
|
||||
|
||||
if (setpriority(PRIO_PROCESS, pid, pri) < 0) {
|
||||
signalExceptionForPriorityError(env, clazz, errno);
|
||||
int rc = androidSetThreadPriority(pid, pri);
|
||||
if (rc != 0) {
|
||||
if (rc == INVALID_OPERATION) {
|
||||
signalExceptionForPriorityError(env, clazz, errno);
|
||||
} else {
|
||||
signalExceptionForGroupError(env, clazz, errno);
|
||||
}
|
||||
}
|
||||
|
||||
//LOGI("Setting priority of %d: %d, getpriority returns %d\n",
|
||||
// pid, pri, getpriority(PRIO_PROCESS, pid));
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
DUMP_TRANSACTION = B_PACK_CHARS('_','D','M','P'),
|
||||
INTERFACE_TRANSACTION = B_PACK_CHARS('_', 'N', 'T', 'F'),
|
||||
|
||||
// Corresponds to tfOneWay -- an asynchronous call.
|
||||
// Corresponds to TF_ONE_WAY -- an asynchronous call.
|
||||
FLAG_ONEWAY = 0x00000001
|
||||
};
|
||||
|
||||
|
||||
@@ -68,6 +68,13 @@ public:
|
||||
|
||||
static void shutdown();
|
||||
|
||||
// Call this to disable switching threads to background scheduling when
|
||||
// receiving incoming IPC calls. This is specifically here for the
|
||||
// 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
|
||||
// the background.
|
||||
static void disableBackgroundScheduling(bool disable);
|
||||
|
||||
private:
|
||||
IPCThreadState();
|
||||
~IPCThreadState();
|
||||
@@ -93,9 +100,10 @@ private:
|
||||
void* cookie);
|
||||
|
||||
const sp<ProcessState> mProcess;
|
||||
const pid_t mMyThreadId;
|
||||
Vector<BBinder*> mPendingStrongDerefs;
|
||||
Vector<RefBase::weakref_type*> mPendingWeakDerefs;
|
||||
|
||||
|
||||
Parcel mIn;
|
||||
Parcel mOut;
|
||||
status_t mLastError;
|
||||
|
||||
@@ -124,6 +124,24 @@ typedef int (*android_create_thread_fn)(android_thread_func_t entryFunction,
|
||||
|
||||
extern void androidSetCreateThreadFunc(android_create_thread_fn func);
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Extra functions working with raw pids.
|
||||
|
||||
// Get pid for the current thread.
|
||||
extern pid_t androidGetTid();
|
||||
|
||||
// Change the scheduling group of a particular thread. The group
|
||||
// should be one of the ANDROID_TGROUP constants. Returns BAD_VALUE if
|
||||
// grp is out of range, else another non-zero value with errno set if
|
||||
// the operation failed.
|
||||
extern int androidSetThreadSchedulingGroup(pid_t tid, int grp);
|
||||
|
||||
// Change the priority AND scheduling group of a particular thread. The priority
|
||||
// should be one of the ANDROID_PRIORITY constants. Returns INVALID_OPERATION
|
||||
// if the priority set failed, else another value if just the group set failed;
|
||||
// in either case errno is set.
|
||||
extern int androidSetThreadPriority(pid_t tid, int prio);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -292,6 +292,7 @@ static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static bool gHaveTLS = false;
|
||||
static pthread_key_t gTLS = 0;
|
||||
static bool gShutdown = false;
|
||||
static bool gDisableBackgroundScheduling = false;
|
||||
|
||||
IPCThreadState* IPCThreadState::self()
|
||||
{
|
||||
@@ -332,6 +333,11 @@ void IPCThreadState::shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
void IPCThreadState::disableBackgroundScheduling(bool disable)
|
||||
{
|
||||
gDisableBackgroundScheduling = disable;
|
||||
}
|
||||
|
||||
sp<ProcessState> IPCThreadState::process()
|
||||
{
|
||||
return mProcess;
|
||||
@@ -386,6 +392,11 @@ void IPCThreadState::joinThreadPool(bool isMain)
|
||||
|
||||
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
|
||||
|
||||
// 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 default/foreground
|
||||
// one to avoid performing an initial transaction in the background.
|
||||
androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_DEFAULT);
|
||||
|
||||
status_t result;
|
||||
do {
|
||||
int32_t cmd;
|
||||
@@ -427,19 +438,13 @@ void IPCThreadState::joinThreadPool(bool isMain)
|
||||
}
|
||||
|
||||
// After executing the command, ensure that the thread is returned to the
|
||||
// default cgroup and priority before rejoining the pool. This is a failsafe
|
||||
// in case the command implementation failed to properly restore the thread's
|
||||
// scheduling parameters upon completion.
|
||||
int my_id;
|
||||
#ifdef HAVE_GETTID
|
||||
my_id = gettid();
|
||||
#else
|
||||
my_id = getpid();
|
||||
#endif
|
||||
if (!set_sched_policy(my_id, SP_FOREGROUND)) {
|
||||
// success; reset the priority as well
|
||||
setpriority(PRIO_PROCESS, my_id, ANDROID_PRIORITY_NORMAL);
|
||||
}
|
||||
// default cgroup before rejoining the pool. The driver takes care of
|
||||
// restoring the priority, but doesn't do anything with cgroups so we
|
||||
// need to take care of that here in userspace. Note that we do make
|
||||
// sure to go in the foreground after executing a transaction, but
|
||||
// there are other callbacks into user code that could have changed
|
||||
// our group so we want to make absolutely sure it is put back.
|
||||
androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_DEFAULT);
|
||||
|
||||
// Let this thread exit the thread pool if it is no longer
|
||||
// needed and it is not the main process thread.
|
||||
@@ -583,10 +588,10 @@ status_t IPCThreadState::clearDeathNotification(int32_t handle, BpBinder* proxy)
|
||||
}
|
||||
|
||||
IPCThreadState::IPCThreadState()
|
||||
: mProcess(ProcessState::self())
|
||||
: mProcess(ProcessState::self()), mMyThreadId(androidGetTid())
|
||||
{
|
||||
pthread_setspecific(gTLS, this);
|
||||
clearCaller();
|
||||
clearCaller();
|
||||
mIn.setDataCapacity(256);
|
||||
mOut.setDataCapacity(256);
|
||||
}
|
||||
@@ -930,6 +935,17 @@ status_t IPCThreadState::executeCommand(int32_t cmd)
|
||||
mCallingPid = tr.sender_pid;
|
||||
mCallingUid = tr.sender_euid;
|
||||
|
||||
bool doBackground = !gDisableBackgroundScheduling &&
|
||||
getpriority(PRIO_PROCESS, mMyThreadId)
|
||||
>= ANDROID_PRIORITY_BACKGROUND;
|
||||
if (doBackground) {
|
||||
// We have inherited a background priority from the caller.
|
||||
// Ensure this thread is in the background scheduling class,
|
||||
// since the driver won't modify scheduling classes for us.
|
||||
androidSetThreadSchedulingGroup(mMyThreadId,
|
||||
ANDROID_TGROUP_BG_NONINTERACT);
|
||||
}
|
||||
|
||||
//LOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid);
|
||||
|
||||
Parcel reply;
|
||||
@@ -967,6 +983,13 @@ status_t IPCThreadState::executeCommand(int32_t cmd)
|
||||
mCallingPid = origPid;
|
||||
mCallingUid = origUid;
|
||||
|
||||
if (doBackground) {
|
||||
// We moved to the background scheduling group to execute
|
||||
// this transaction, so now that we are done go back in the
|
||||
// foreground.
|
||||
androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_DEFAULT);
|
||||
}
|
||||
|
||||
IF_LOG_TRANSACTIONS() {
|
||||
TextOutput::Bundle _b(alog);
|
||||
alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj "
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <utils/threads.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <cutils/sched_policy.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
@@ -269,6 +271,53 @@ void androidSetCreateThreadFunc(android_create_thread_fn func)
|
||||
gCreateThreadFn = func;
|
||||
}
|
||||
|
||||
pid_t androidGetTid()
|
||||
{
|
||||
#ifdef HAVE_GETTID
|
||||
return gettid();
|
||||
#else
|
||||
return getpid();
|
||||
#endif
|
||||
}
|
||||
|
||||
int androidSetThreadSchedulingGroup(pid_t tid, int grp)
|
||||
{
|
||||
if (grp > ANDROID_TGROUP_MAX || grp < 0) {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
if (set_sched_policy(tid, (grp == ANDROID_TGROUP_BG_NONINTERACT) ?
|
||||
SP_BACKGROUND : SP_FOREGROUND)) {
|
||||
return PERMISSION_DENIED;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int androidSetThreadPriority(pid_t tid, int pri)
|
||||
{
|
||||
int rc = 0;
|
||||
int lasterr = 0;
|
||||
|
||||
if (pri >= ANDROID_PRIORITY_BACKGROUND) {
|
||||
rc = set_sched_policy(tid, SP_BACKGROUND);
|
||||
} else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND) {
|
||||
rc = set_sched_policy(tid, SP_FOREGROUND);
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
lasterr = errno;
|
||||
}
|
||||
|
||||
if (setpriority(PRIO_PROCESS, tid, pri) < 0) {
|
||||
rc = INVALID_OPERATION;
|
||||
} else {
|
||||
errno = lasterr;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
namespace android {
|
||||
|
||||
/*
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.server;
|
||||
|
||||
import com.android.server.am.ActivityManagerService;
|
||||
import com.android.server.status.StatusBarService;
|
||||
import com.android.internal.os.BinderInternal;
|
||||
import com.android.internal.os.SamplingProfilerIntegration;
|
||||
|
||||
import dalvik.system.VMRuntime;
|
||||
@@ -80,6 +81,8 @@ class ServerThread extends Thread {
|
||||
android.os.Process.setThreadPriority(
|
||||
android.os.Process.THREAD_PRIORITY_FOREGROUND);
|
||||
|
||||
BinderInternal.disableBackgroundScheduling(true);
|
||||
|
||||
String factoryTestStr = SystemProperties.get("ro.factorytest");
|
||||
int factoryTest = "".equals(factoryTestStr) ? SystemServer.FACTORY_TEST_OFF
|
||||
: Integer.parseInt(factoryTestStr);
|
||||
|
||||
Reference in New Issue
Block a user