Loading include/binder/IBinder.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -52,7 +52,7 @@ public: DUMP_TRANSACTION = B_PACK_CHARS('_','D','M','P'), DUMP_TRANSACTION = B_PACK_CHARS('_','D','M','P'), INTERFACE_TRANSACTION = B_PACK_CHARS('_', 'N', 'T', 'F'), 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 FLAG_ONEWAY = 0x00000001 }; }; Loading include/binder/IPCThreadState.h +9 −1 Original line number Original line Diff line number Diff line Loading @@ -68,6 +68,13 @@ public: static void shutdown(); 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: private: IPCThreadState(); IPCThreadState(); ~IPCThreadState(); ~IPCThreadState(); Loading @@ -93,6 +100,7 @@ private: void* cookie); void* cookie); const sp<ProcessState> mProcess; const sp<ProcessState> mProcess; const pid_t mMyThreadId; Vector<BBinder*> mPendingStrongDerefs; Vector<BBinder*> mPendingStrongDerefs; Vector<RefBase::weakref_type*> mPendingWeakDerefs; Vector<RefBase::weakref_type*> mPendingWeakDerefs; Loading include/utils/threads.h +18 −0 Original line number Original line Diff line number Diff line Loading @@ -124,6 +124,24 @@ typedef int (*android_create_thread_fn)(android_thread_func_t entryFunction, extern void androidSetCreateThreadFunc(android_create_thread_fn func); 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 #ifdef __cplusplus } } #endif #endif Loading libs/binder/IPCThreadState.cpp +38 −15 Original line number Original line Diff line number Diff line Loading @@ -292,6 +292,7 @@ static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER; static bool gHaveTLS = false; static bool gHaveTLS = false; static pthread_key_t gTLS = 0; static pthread_key_t gTLS = 0; static bool gShutdown = false; static bool gShutdown = false; static bool gDisableBackgroundScheduling = false; IPCThreadState* IPCThreadState::self() IPCThreadState* IPCThreadState::self() { { Loading Loading @@ -332,6 +333,11 @@ void IPCThreadState::shutdown() } } } } void IPCThreadState::disableBackgroundScheduling(bool disable) { gDisableBackgroundScheduling = disable; } sp<ProcessState> IPCThreadState::process() sp<ProcessState> IPCThreadState::process() { { return mProcess; return mProcess; Loading Loading @@ -386,6 +392,11 @@ void IPCThreadState::joinThreadPool(bool isMain) mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); 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; status_t result; do { do { int32_t cmd; int32_t cmd; Loading Loading @@ -427,19 +438,13 @@ void IPCThreadState::joinThreadPool(bool isMain) } } // After executing the command, ensure that the thread is returned to the // After executing the command, ensure that the thread is returned to the // default cgroup and priority before rejoining the pool. This is a failsafe // default cgroup before rejoining the pool. The driver takes care of // in case the command implementation failed to properly restore the thread's // restoring the priority, but doesn't do anything with cgroups so we // scheduling parameters upon completion. // need to take care of that here in userspace. Note that we do make int my_id; // sure to go in the foreground after executing a transaction, but #ifdef HAVE_GETTID // there are other callbacks into user code that could have changed my_id = gettid(); // our group so we want to make absolutely sure it is put back. #else androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_DEFAULT); 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); } // Let this thread exit the thread pool if it is no longer // Let this thread exit the thread pool if it is no longer // needed and it is not the main process thread. // needed and it is not the main process thread. Loading Loading @@ -583,7 +588,7 @@ status_t IPCThreadState::clearDeathNotification(int32_t handle, BpBinder* proxy) } } IPCThreadState::IPCThreadState() IPCThreadState::IPCThreadState() : mProcess(ProcessState::self()) : mProcess(ProcessState::self()), mMyThreadId(androidGetTid()) { { pthread_setspecific(gTLS, this); pthread_setspecific(gTLS, this); clearCaller(); clearCaller(); Loading Loading @@ -930,6 +935,17 @@ status_t IPCThreadState::executeCommand(int32_t cmd) mCallingPid = tr.sender_pid; mCallingPid = tr.sender_pid; mCallingUid = tr.sender_euid; 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); //LOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid); Parcel reply; Parcel reply; Loading Loading @@ -967,6 +983,13 @@ status_t IPCThreadState::executeCommand(int32_t cmd) mCallingPid = origPid; mCallingPid = origPid; mCallingUid = origUid; 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() { IF_LOG_TRANSACTIONS() { TextOutput::Bundle _b(alog); TextOutput::Bundle _b(alog); alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj " alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj " Loading libs/utils/Threads.cpp +49 −0 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,8 @@ #include <utils/threads.h> #include <utils/threads.h> #include <utils/Log.h> #include <utils/Log.h> #include <cutils/sched_policy.h> #include <stdio.h> #include <stdio.h> #include <stdlib.h> #include <stdlib.h> #include <memory.h> #include <memory.h> Loading Loading @@ -269,6 +271,53 @@ void androidSetCreateThreadFunc(android_create_thread_fn func) gCreateThreadFn = 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 { namespace android { /* /* Loading Loading
include/binder/IBinder.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -52,7 +52,7 @@ public: DUMP_TRANSACTION = B_PACK_CHARS('_','D','M','P'), DUMP_TRANSACTION = B_PACK_CHARS('_','D','M','P'), INTERFACE_TRANSACTION = B_PACK_CHARS('_', 'N', 'T', 'F'), 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 FLAG_ONEWAY = 0x00000001 }; }; Loading
include/binder/IPCThreadState.h +9 −1 Original line number Original line Diff line number Diff line Loading @@ -68,6 +68,13 @@ public: static void shutdown(); 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: private: IPCThreadState(); IPCThreadState(); ~IPCThreadState(); ~IPCThreadState(); Loading @@ -93,6 +100,7 @@ private: void* cookie); void* cookie); const sp<ProcessState> mProcess; const sp<ProcessState> mProcess; const pid_t mMyThreadId; Vector<BBinder*> mPendingStrongDerefs; Vector<BBinder*> mPendingStrongDerefs; Vector<RefBase::weakref_type*> mPendingWeakDerefs; Vector<RefBase::weakref_type*> mPendingWeakDerefs; Loading
include/utils/threads.h +18 −0 Original line number Original line Diff line number Diff line Loading @@ -124,6 +124,24 @@ typedef int (*android_create_thread_fn)(android_thread_func_t entryFunction, extern void androidSetCreateThreadFunc(android_create_thread_fn func); 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 #ifdef __cplusplus } } #endif #endif Loading
libs/binder/IPCThreadState.cpp +38 −15 Original line number Original line Diff line number Diff line Loading @@ -292,6 +292,7 @@ static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER; static bool gHaveTLS = false; static bool gHaveTLS = false; static pthread_key_t gTLS = 0; static pthread_key_t gTLS = 0; static bool gShutdown = false; static bool gShutdown = false; static bool gDisableBackgroundScheduling = false; IPCThreadState* IPCThreadState::self() IPCThreadState* IPCThreadState::self() { { Loading Loading @@ -332,6 +333,11 @@ void IPCThreadState::shutdown() } } } } void IPCThreadState::disableBackgroundScheduling(bool disable) { gDisableBackgroundScheduling = disable; } sp<ProcessState> IPCThreadState::process() sp<ProcessState> IPCThreadState::process() { { return mProcess; return mProcess; Loading Loading @@ -386,6 +392,11 @@ void IPCThreadState::joinThreadPool(bool isMain) mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); 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; status_t result; do { do { int32_t cmd; int32_t cmd; Loading Loading @@ -427,19 +438,13 @@ void IPCThreadState::joinThreadPool(bool isMain) } } // After executing the command, ensure that the thread is returned to the // After executing the command, ensure that the thread is returned to the // default cgroup and priority before rejoining the pool. This is a failsafe // default cgroup before rejoining the pool. The driver takes care of // in case the command implementation failed to properly restore the thread's // restoring the priority, but doesn't do anything with cgroups so we // scheduling parameters upon completion. // need to take care of that here in userspace. Note that we do make int my_id; // sure to go in the foreground after executing a transaction, but #ifdef HAVE_GETTID // there are other callbacks into user code that could have changed my_id = gettid(); // our group so we want to make absolutely sure it is put back. #else androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_DEFAULT); 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); } // Let this thread exit the thread pool if it is no longer // Let this thread exit the thread pool if it is no longer // needed and it is not the main process thread. // needed and it is not the main process thread. Loading Loading @@ -583,7 +588,7 @@ status_t IPCThreadState::clearDeathNotification(int32_t handle, BpBinder* proxy) } } IPCThreadState::IPCThreadState() IPCThreadState::IPCThreadState() : mProcess(ProcessState::self()) : mProcess(ProcessState::self()), mMyThreadId(androidGetTid()) { { pthread_setspecific(gTLS, this); pthread_setspecific(gTLS, this); clearCaller(); clearCaller(); Loading Loading @@ -930,6 +935,17 @@ status_t IPCThreadState::executeCommand(int32_t cmd) mCallingPid = tr.sender_pid; mCallingPid = tr.sender_pid; mCallingUid = tr.sender_euid; 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); //LOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid); Parcel reply; Parcel reply; Loading Loading @@ -967,6 +983,13 @@ status_t IPCThreadState::executeCommand(int32_t cmd) mCallingPid = origPid; mCallingPid = origPid; mCallingUid = origUid; 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() { IF_LOG_TRANSACTIONS() { TextOutput::Bundle _b(alog); TextOutput::Bundle _b(alog); alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj " alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj " Loading
libs/utils/Threads.cpp +49 −0 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,8 @@ #include <utils/threads.h> #include <utils/threads.h> #include <utils/Log.h> #include <utils/Log.h> #include <cutils/sched_policy.h> #include <stdio.h> #include <stdio.h> #include <stdlib.h> #include <stdlib.h> #include <memory.h> #include <memory.h> Loading Loading @@ -269,6 +271,53 @@ void androidSetCreateThreadFunc(android_create_thread_fn func) gCreateThreadFn = 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 { namespace android { /* /* Loading