/* * Copyright (C) 2009 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. */ #include "rsContext.h" #include "rsThreadIO.h" using namespace android; using namespace android::renderscript; ThreadIO::ThreadIO() : mUsingSocket(false) { } ThreadIO::~ThreadIO() { } void ThreadIO::init(bool useSocket) { mUsingSocket = useSocket; mToCore.init(16 * 1024); if (mUsingSocket) { mToClientSocket.init(); mToCoreSocket.init(); } else { mToClient.init(1024); } } void ThreadIO::shutdown() { //LOGE("shutdown 1"); mToCore.shutdown(); //LOGE("shutdown 2"); } void ThreadIO::coreFlush() { //LOGE("coreFlush 1"); if (mUsingSocket) { } else { mToCore.flush(); } //LOGE("coreFlush 2"); } void * ThreadIO::coreHeader(uint32_t cmdID, size_t dataLen) { //LOGE("coreHeader %i %i", cmdID, dataLen); if (mUsingSocket) { CoreCmdHeader hdr; hdr.bytes = dataLen; hdr.cmdID = cmdID; mToCoreSocket.writeAsync(&hdr, sizeof(hdr)); } else { mCoreCommandSize = dataLen; mCoreCommandID = cmdID; mCoreDataPtr = (uint8_t *)mToCore.reserve(dataLen); mCoreDataBasePtr = mCoreDataPtr; } //LOGE("coreHeader ret %p", mCoreDataPtr); return mCoreDataPtr; } void ThreadIO::coreData(const void *data, size_t dataLen) { //LOGE("coreData %p %i", data, dataLen); mToCoreSocket.writeAsync(data, dataLen); //LOGE("coreData ret %p", mCoreDataPtr); } void ThreadIO::coreCommit() { //LOGE("coreCommit %p %p %i", mCoreDataPtr, mCoreDataBasePtr, mCoreCommandSize); if (mUsingSocket) { } else { rsAssert((size_t)(mCoreDataPtr - mCoreDataBasePtr) <= mCoreCommandSize); mToCore.commit(mCoreCommandID, mCoreCommandSize); } //LOGE("coreCommit ret"); } void ThreadIO::coreCommitSync() { //LOGE("coreCommitSync %p %p %i", mCoreDataPtr, mCoreDataBasePtr, mCoreCommandSize); if (mUsingSocket) { } else { rsAssert((size_t)(mCoreDataPtr - mCoreDataBasePtr) <= mCoreCommandSize); mToCore.commitSync(mCoreCommandID, mCoreCommandSize); } //LOGE("coreCommitSync ret"); } void ThreadIO::clientShutdown() { //LOGE("coreShutdown 1"); mToClient.shutdown(); //LOGE("coreShutdown 2"); } void ThreadIO::coreSetReturn(const void *data, size_t dataLen) { rsAssert(dataLen <= sizeof(mToCoreRet)); memcpy(&mToCoreRet, data, dataLen); } void ThreadIO::coreGetReturn(void *data, size_t dataLen) { memcpy(data, &mToCoreRet, dataLen); } bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand) { bool ret = false; while (!mToCore.isEmpty() || waitForCommand) { uint32_t cmdID = 0; uint32_t cmdSize = 0; ret = true; if (con->props.mLogTimes) { con->timerSet(Context::RS_TIMER_IDLE); } const void * data = mToCore.get(&cmdID, &cmdSize); if (!cmdSize) { // exception occured, probably shutdown. return false; } if (con->props.mLogTimes) { con->timerSet(Context::RS_TIMER_INTERNAL); } waitForCommand = false; //LOGV("playCoreCommands 3 %i %i", cmdID, cmdSize); if (cmdID >= (sizeof(gPlaybackFuncs) / sizeof(void *))) { rsAssert(cmdID < (sizeof(gPlaybackFuncs) / sizeof(void *))); LOGE("playCoreCommands error con %p, cmd %i", con, cmdID); mToCore.printDebugData(); } gPlaybackFuncs[cmdID](con, data, cmdSize << 2); mToCore.next(); } return ret; } RsMessageToClientType ThreadIO::getClientHeader(size_t *receiveLen, uint32_t *usrID) { if (mUsingSocket) { mToClientSocket.read(&mLastClientHeader, sizeof(mLastClientHeader)); } else { size_t bytesData = 0; const uint32_t *d = (const uint32_t *)mToClient.get(&mLastClientHeader.cmdID, (uint32_t*)&bytesData); if (bytesData >= sizeof(uint32_t)) { mLastClientHeader.userID = d[0]; mLastClientHeader.bytes = bytesData - sizeof(uint32_t); } else { mLastClientHeader.userID = 0; mLastClientHeader.bytes = 0; } } receiveLen[0] = mLastClientHeader.bytes; usrID[0] = mLastClientHeader.userID; return (RsMessageToClientType)mLastClientHeader.cmdID; } RsMessageToClientType ThreadIO::getClientPayload(void *data, size_t *receiveLen, uint32_t *usrID, size_t bufferLen) { receiveLen[0] = mLastClientHeader.bytes; usrID[0] = mLastClientHeader.userID; if (bufferLen < mLastClientHeader.bytes) { return RS_MESSAGE_TO_CLIENT_RESIZE; } if (mUsingSocket) { if (receiveLen[0]) { mToClientSocket.read(data, receiveLen[0]); } return (RsMessageToClientType)mLastClientHeader.cmdID; } else { uint32_t bytesData = 0; uint32_t commandID = 0; const uint32_t *d = (const uint32_t *)mToClient.get(&commandID, &bytesData); //LOGE("getMessageToClient 3 %i %i", commandID, bytesData); //LOGE("getMessageToClient %i %i", commandID, *subID); if (bufferLen >= receiveLen[0]) { memcpy(data, d+1, receiveLen[0]); mToClient.next(); return (RsMessageToClientType)commandID; } } return RS_MESSAGE_TO_CLIENT_RESIZE; } bool ThreadIO::sendToClient(RsMessageToClientType cmdID, uint32_t usrID, const void *data, size_t dataLen, bool waitForSpace) { ClientCmdHeader hdr; hdr.bytes = dataLen; hdr.cmdID = cmdID; hdr.userID = usrID; if (mUsingSocket) { mToClientSocket.writeAsync(&hdr, sizeof(hdr)); if (dataLen) { mToClientSocket.writeAsync(data, dataLen); } return true; } else { if (!waitForSpace) { if (!mToClient.makeSpaceNonBlocking(dataLen + sizeof(hdr))) { // Not enough room, and not waiting. return false; } } //LOGE("sendMessageToClient 2"); uint32_t *p = (uint32_t *)mToClient.reserve(dataLen + sizeof(usrID)); p[0] = usrID; if (dataLen > 0) { memcpy(p+1, data, dataLen); } mToClient.commit(cmdID, dataLen + sizeof(usrID)); //LOGE("sendMessageToClient 3"); return true; } return false; }