diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
commit | d5193d9394c5e58176d7bcdf50ef017f8a3b9e1e (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /libs/utils/ProcessState.cpp | |
parent | 43aa2b1cbf7a03e248e10f4d0fec0463257cd52d (diff) | |
download | frameworks_native-d5193d9394c5e58176d7bcdf50ef017f8a3b9e1e.zip frameworks_native-d5193d9394c5e58176d7bcdf50ef017f8a3b9e1e.tar.gz frameworks_native-d5193d9394c5e58176d7bcdf50ef017f8a3b9e1e.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'libs/utils/ProcessState.cpp')
-rw-r--r-- | libs/utils/ProcessState.cpp | 398 |
1 files changed, 0 insertions, 398 deletions
diff --git a/libs/utils/ProcessState.cpp b/libs/utils/ProcessState.cpp deleted file mode 100644 index 4567df6..0000000 --- a/libs/utils/ProcessState.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/* - * Copyright (C) 2005 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 "ProcessState" - -#include <cutils/process_name.h> - -#include <utils/ProcessState.h> - -#include <utils/Atomic.h> -#include <utils/BpBinder.h> -#include <utils/IPCThreadState.h> -#include <utils/Log.h> -#include <utils/String8.h> -#include <utils/IServiceManager.h> -#include <utils/String8.h> -#include <utils/threads.h> - -#include <private/utils/binder_module.h> -#include <private/utils/Static.h> - -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <sys/stat.h> - -#define BINDER_VM_SIZE (1*1024*1024) - -static bool gSingleProcess = false; - - -// --------------------------------------------------------------------------- - -namespace android { - -// Global variables -int mArgC; -const char* const* mArgV; -int mArgLen; - -class PoolThread : public Thread -{ -public: - PoolThread(bool isMain) - : mIsMain(isMain) - { - } - -protected: - virtual bool threadLoop() - { - IPCThreadState::self()->joinThreadPool(mIsMain); - return false; - } - - const bool mIsMain; -}; - -sp<ProcessState> ProcessState::self() -{ - if (gProcess != NULL) return gProcess; - - AutoMutex _l(gProcessMutex); - if (gProcess == NULL) gProcess = new ProcessState; - return gProcess; -} - -void ProcessState::setSingleProcess(bool singleProcess) -{ - gSingleProcess = singleProcess; -} - - -void ProcessState::setContextObject(const sp<IBinder>& object) -{ - setContextObject(object, String16("default")); -} - -sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller) -{ - if (supportsProcesses()) { - return getStrongProxyForHandle(0); - } else { - return getContextObject(String16("default"), caller); - } -} - -void ProcessState::setContextObject(const sp<IBinder>& object, const String16& name) -{ - AutoMutex _l(mLock); - mContexts.add(name, object); -} - -sp<IBinder> ProcessState::getContextObject(const String16& name, const sp<IBinder>& caller) -{ - mLock.lock(); - sp<IBinder> object( - mContexts.indexOfKey(name) >= 0 ? mContexts.valueFor(name) : NULL); - mLock.unlock(); - - //printf("Getting context object %s for %p\n", String8(name).string(), caller.get()); - - if (object != NULL) return object; - - // Don't attempt to retrieve contexts if we manage them - if (mManagesContexts) { - LOGE("getContextObject(%s) failed, but we manage the contexts!\n", - String8(name).string()); - return NULL; - } - - IPCThreadState* ipc = IPCThreadState::self(); - { - Parcel data, reply; - // no interface token on this magic transaction - data.writeString16(name); - data.writeStrongBinder(caller); - status_t result = ipc->transact(0 /*magic*/, 0, data, &reply, 0); - if (result == NO_ERROR) { - object = reply.readStrongBinder(); - } - } - - ipc->flushCommands(); - - if (object != NULL) setContextObject(object, name); - return object; -} - -bool ProcessState::supportsProcesses() const -{ - return mDriverFD >= 0; -} - -void ProcessState::startThreadPool() -{ - AutoMutex _l(mLock); - if (!mThreadPoolStarted) { - mThreadPoolStarted = true; - spawnPooledThread(true); - } -} - -bool ProcessState::isContextManager(void) const -{ - return mManagesContexts; -} - -bool ProcessState::becomeContextManager(context_check_func checkFunc, void* userData) -{ - if (!mManagesContexts) { - AutoMutex _l(mLock); - mBinderContextCheckFunc = checkFunc; - mBinderContextUserData = userData; - if (mDriverFD >= 0) { - int dummy = 0; -#if defined(HAVE_ANDROID_OS) - status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy); -#else - status_t result = INVALID_OPERATION; -#endif - if (result == 0) { - mManagesContexts = true; - } else if (result == -1) { - mBinderContextCheckFunc = NULL; - mBinderContextUserData = NULL; - LOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno)); - } - } else { - // If there is no driver, our only world is the local - // process so we can always become the context manager there. - mManagesContexts = true; - } - } - return mManagesContexts; -} - -ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle) -{ - const size_t N=mHandleToObject.size(); - if (N <= (size_t)handle) { - handle_entry e; - e.binder = NULL; - e.refs = NULL; - status_t err = mHandleToObject.insertAt(e, N, handle+1-N); - if (err < NO_ERROR) return NULL; - } - return &mHandleToObject.editItemAt(handle); -} - -sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) -{ - sp<IBinder> result; - - AutoMutex _l(mLock); - - handle_entry* e = lookupHandleLocked(handle); - - if (e != NULL) { - // We need to create a new BpBinder if there isn't currently one, OR we - // are unable to acquire a weak reference on this current one. See comment - // in getWeakProxyForHandle() for more info about this. - IBinder* b = e->binder; - if (b == NULL || !e->refs->attemptIncWeak(this)) { - b = new BpBinder(handle); - e->binder = b; - if (b) e->refs = b->getWeakRefs(); - result = b; - } else { - // This little bit of nastyness is to allow us to add a primary - // reference to the remote proxy when this team doesn't have one - // but another team is sending the handle to us. - result.force_set(b); - e->refs->decWeak(this); - } - } - - return result; -} - -wp<IBinder> ProcessState::getWeakProxyForHandle(int32_t handle) -{ - wp<IBinder> result; - - AutoMutex _l(mLock); - - handle_entry* e = lookupHandleLocked(handle); - - if (e != NULL) { - // We need to create a new BpBinder if there isn't currently one, OR we - // are unable to acquire a weak reference on this current one. The - // attemptIncWeak() is safe because we know the BpBinder destructor will always - // call expungeHandle(), which acquires the same lock we are holding now. - // We need to do this because there is a race condition between someone - // releasing a reference on this BpBinder, and a new reference on its handle - // arriving from the driver. - IBinder* b = e->binder; - if (b == NULL || !e->refs->attemptIncWeak(this)) { - b = new BpBinder(handle); - result = b; - e->binder = b; - if (b) e->refs = b->getWeakRefs(); - } else { - result = b; - e->refs->decWeak(this); - } - } - - return result; -} - -void ProcessState::expungeHandle(int32_t handle, IBinder* binder) -{ - AutoMutex _l(mLock); - - handle_entry* e = lookupHandleLocked(handle); - - // This handle may have already been replaced with a new BpBinder - // (if someone failed the AttemptIncWeak() above); we don't want - // to overwrite it. - if (e && e->binder == binder) e->binder = NULL; -} - -void ProcessState::setArgs(int argc, const char* const argv[]) -{ - mArgC = argc; - mArgV = (const char **)argv; - - mArgLen = 0; - for (int i=0; i<argc; i++) { - mArgLen += strlen(argv[i]) + 1; - } - mArgLen--; -} - -int ProcessState::getArgC() const -{ - return mArgC; -} - -const char* const* ProcessState::getArgV() const -{ - return mArgV; -} - -void ProcessState::setArgV0(const char* txt) -{ - if (mArgV != NULL) { - strncpy((char*)mArgV[0], txt, mArgLen); - set_process_name(txt); - } -} - -void ProcessState::spawnPooledThread(bool isMain) -{ - if (mThreadPoolStarted) { - int32_t s = android_atomic_add(1, &mThreadPoolSeq); - char buf[32]; - sprintf(buf, "Binder Thread #%d", s); - LOGV("Spawning new pooled thread, name=%s\n", buf); - sp<Thread> t = new PoolThread(isMain); - t->run(buf); - } -} - -static int open_driver() -{ - if (gSingleProcess) { - return -1; - } - - int fd = open("/dev/binder", O_RDWR); - if (fd >= 0) { - fcntl(fd, F_SETFD, FD_CLOEXEC); - int vers; -#if defined(HAVE_ANDROID_OS) - status_t result = ioctl(fd, BINDER_VERSION, &vers); -#else - status_t result = -1; - errno = EPERM; -#endif - if (result == -1) { - LOGE("Binder ioctl to obtain version failed: %s", strerror(errno)); - close(fd); - fd = -1; - } - if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) { - LOGE("Binder driver protocol does not match user space protocol!"); - close(fd); - fd = -1; - } -#if defined(HAVE_ANDROID_OS) - size_t maxThreads = 15; - result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads); - if (result == -1) { - LOGE("Binder ioctl to set max threads failed: %s", strerror(errno)); - } -#endif - - } else { - LOGW("Opening '/dev/binder' failed: %s\n", strerror(errno)); - } - return fd; -} - -ProcessState::ProcessState() - : mDriverFD(open_driver()) - , mVMStart(MAP_FAILED) - , mManagesContexts(false) - , mBinderContextCheckFunc(NULL) - , mBinderContextUserData(NULL) - , mThreadPoolStarted(false) - , mThreadPoolSeq(1) -{ - if (mDriverFD >= 0) { - // XXX Ideally, there should be a specific define for whether we - // have mmap (or whether we could possibly have the kernel module - // availabla). -#if !defined(HAVE_WIN32_IPC) - // mmap the binder, providing a chunk of virtual address space to receive transactions. - mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); - if (mVMStart == MAP_FAILED) { - // *sigh* - LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n"); - close(mDriverFD); - mDriverFD = -1; - } -#else - mDriverFD = -1; -#endif - } - if (mDriverFD < 0) { - // Need to run without the driver, starting our own thread pool. - } -} - -ProcessState::~ProcessState() -{ -} - -}; // namespace android |