1 /*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "rsContext.h"
18
19 #include "rsThreadIO.h"
20
21 using namespace android;
22 using namespace android::renderscript;
23
ThreadIO()24 ThreadIO::ThreadIO() : mUsingSocket(false) {
25 }
26
~ThreadIO()27 ThreadIO::~ThreadIO() {
28 }
29
init(bool useSocket)30 void ThreadIO::init(bool useSocket) {
31 mUsingSocket = useSocket;
32 mToCore.init(16 * 1024);
33
34 if (mUsingSocket) {
35 mToClientSocket.init();
36 mToCoreSocket.init();
37 } else {
38 mToClient.init(1024);
39 }
40 }
41
shutdown()42 void ThreadIO::shutdown() {
43 //LOGE("shutdown 1");
44 mToCore.shutdown();
45 //LOGE("shutdown 2");
46 }
47
coreFlush()48 void ThreadIO::coreFlush() {
49 //LOGE("coreFlush 1");
50 if (mUsingSocket) {
51 } else {
52 mToCore.flush();
53 }
54 //LOGE("coreFlush 2");
55 }
56
coreHeader(uint32_t cmdID,size_t dataLen)57 void * ThreadIO::coreHeader(uint32_t cmdID, size_t dataLen) {
58 //LOGE("coreHeader %i %i", cmdID, dataLen);
59 if (mUsingSocket) {
60 CoreCmdHeader hdr;
61 hdr.bytes = dataLen;
62 hdr.cmdID = cmdID;
63 mToCoreSocket.writeAsync(&hdr, sizeof(hdr));
64 } else {
65 mCoreCommandSize = dataLen;
66 mCoreCommandID = cmdID;
67 mCoreDataPtr = (uint8_t *)mToCore.reserve(dataLen);
68 mCoreDataBasePtr = mCoreDataPtr;
69 }
70 //LOGE("coreHeader ret %p", mCoreDataPtr);
71 return mCoreDataPtr;
72 }
73
coreData(const void * data,size_t dataLen)74 void ThreadIO::coreData(const void *data, size_t dataLen) {
75 //LOGE("coreData %p %i", data, dataLen);
76 mToCoreSocket.writeAsync(data, dataLen);
77 //LOGE("coreData ret %p", mCoreDataPtr);
78 }
79
coreCommit()80 void ThreadIO::coreCommit() {
81 //LOGE("coreCommit %p %p %i", mCoreDataPtr, mCoreDataBasePtr, mCoreCommandSize);
82 if (mUsingSocket) {
83 } else {
84 rsAssert((size_t)(mCoreDataPtr - mCoreDataBasePtr) <= mCoreCommandSize);
85 mToCore.commit(mCoreCommandID, mCoreCommandSize);
86 }
87 //LOGE("coreCommit ret");
88 }
89
coreCommitSync()90 void ThreadIO::coreCommitSync() {
91 //LOGE("coreCommitSync %p %p %i", mCoreDataPtr, mCoreDataBasePtr, mCoreCommandSize);
92 if (mUsingSocket) {
93 } else {
94 rsAssert((size_t)(mCoreDataPtr - mCoreDataBasePtr) <= mCoreCommandSize);
95 mToCore.commitSync(mCoreCommandID, mCoreCommandSize);
96 }
97 //LOGE("coreCommitSync ret");
98 }
99
clientShutdown()100 void ThreadIO::clientShutdown() {
101 //LOGE("coreShutdown 1");
102 mToClient.shutdown();
103 //LOGE("coreShutdown 2");
104 }
105
coreSetReturn(const void * data,size_t dataLen)106 void ThreadIO::coreSetReturn(const void *data, size_t dataLen) {
107 rsAssert(dataLen <= sizeof(mToCoreRet));
108 memcpy(&mToCoreRet, data, dataLen);
109 }
110
coreGetReturn(void * data,size_t dataLen)111 void ThreadIO::coreGetReturn(void *data, size_t dataLen) {
112 memcpy(data, &mToCoreRet, dataLen);
113 }
114
setTimoutCallback(void (* cb)(void *),void * dat,uint64_t timeout)115 void ThreadIO::setTimoutCallback(void (*cb)(void *), void *dat, uint64_t timeout) {
116 mToCore.setTimoutCallback(cb, dat, timeout);
117 }
118
119
playCoreCommands(Context * con,bool waitForCommand,uint64_t timeToWait)120 bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand, uint64_t timeToWait) {
121 bool ret = false;
122 uint64_t startTime = con->getTime();
123
124 while (!mToCore.isEmpty() || waitForCommand) {
125 uint32_t cmdID = 0;
126 uint32_t cmdSize = 0;
127 ret = true;
128 if (con->props.mLogTimes) {
129 con->timerSet(Context::RS_TIMER_IDLE);
130 }
131
132 uint64_t delay = 0;
133 if (waitForCommand) {
134 delay = timeToWait - (con->getTime() - startTime);
135 if (delay > timeToWait) {
136 delay = 0;
137 }
138 }
139 const void * data = mToCore.get(&cmdID, &cmdSize, delay);
140 if (!cmdSize) {
141 // exception or timeout occurred.
142 return false;
143 }
144 if (con->props.mLogTimes) {
145 con->timerSet(Context::RS_TIMER_INTERNAL);
146 }
147 waitForCommand = false;
148 //LOGV("playCoreCommands 3 %i %i", cmdID, cmdSize);
149
150 if (cmdID >= (sizeof(gPlaybackFuncs) / sizeof(void *))) {
151 rsAssert(cmdID < (sizeof(gPlaybackFuncs) / sizeof(void *)));
152 LOGE("playCoreCommands error con %p, cmd %i", con, cmdID);
153 mToCore.printDebugData();
154 }
155 gPlaybackFuncs[cmdID](con, data, cmdSize << 2);
156 mToCore.next();
157 }
158 return ret;
159 }
160
getClientHeader(size_t * receiveLen,uint32_t * usrID)161 RsMessageToClientType ThreadIO::getClientHeader(size_t *receiveLen, uint32_t *usrID) {
162 if (mUsingSocket) {
163 mToClientSocket.read(&mLastClientHeader, sizeof(mLastClientHeader));
164 } else {
165 size_t bytesData = 0;
166 const uint32_t *d = (const uint32_t *)mToClient.get(&mLastClientHeader.cmdID, (uint32_t*)&bytesData);
167 if (bytesData >= sizeof(uint32_t)) {
168 mLastClientHeader.userID = d[0];
169 mLastClientHeader.bytes = bytesData - sizeof(uint32_t);
170 } else {
171 mLastClientHeader.userID = 0;
172 mLastClientHeader.bytes = 0;
173 }
174 }
175 receiveLen[0] = mLastClientHeader.bytes;
176 usrID[0] = mLastClientHeader.userID;
177 return (RsMessageToClientType)mLastClientHeader.cmdID;
178 }
179
getClientPayload(void * data,size_t * receiveLen,uint32_t * usrID,size_t bufferLen)180 RsMessageToClientType ThreadIO::getClientPayload(void *data, size_t *receiveLen,
181 uint32_t *usrID, size_t bufferLen) {
182 receiveLen[0] = mLastClientHeader.bytes;
183 usrID[0] = mLastClientHeader.userID;
184 if (bufferLen < mLastClientHeader.bytes) {
185 return RS_MESSAGE_TO_CLIENT_RESIZE;
186 }
187 if (mUsingSocket) {
188 if (receiveLen[0]) {
189 mToClientSocket.read(data, receiveLen[0]);
190 }
191 return (RsMessageToClientType)mLastClientHeader.cmdID;
192 } else {
193 uint32_t bytesData = 0;
194 uint32_t commandID = 0;
195 const uint32_t *d = (const uint32_t *)mToClient.get(&commandID, &bytesData);
196 //LOGE("getMessageToClient 3 %i %i", commandID, bytesData);
197 //LOGE("getMessageToClient %i %i", commandID, *subID);
198 if (bufferLen >= receiveLen[0]) {
199 memcpy(data, d+1, receiveLen[0]);
200 mToClient.next();
201 return (RsMessageToClientType)commandID;
202 }
203 }
204 return RS_MESSAGE_TO_CLIENT_RESIZE;
205 }
206
sendToClient(RsMessageToClientType cmdID,uint32_t usrID,const void * data,size_t dataLen,bool waitForSpace)207 bool ThreadIO::sendToClient(RsMessageToClientType cmdID, uint32_t usrID, const void *data,
208 size_t dataLen, bool waitForSpace) {
209 ClientCmdHeader hdr;
210 hdr.bytes = dataLen;
211 hdr.cmdID = cmdID;
212 hdr.userID = usrID;
213 if (mUsingSocket) {
214 mToClientSocket.writeAsync(&hdr, sizeof(hdr));
215 if (dataLen) {
216 mToClientSocket.writeAsync(data, dataLen);
217 }
218 return true;
219 } else {
220 if (!waitForSpace) {
221 if (!mToClient.makeSpaceNonBlocking(dataLen + sizeof(hdr))) {
222 // Not enough room, and not waiting.
223 return false;
224 }
225 }
226
227 //LOGE("sendMessageToClient 2");
228 uint32_t *p = (uint32_t *)mToClient.reserve(dataLen + sizeof(usrID));
229 p[0] = usrID;
230 if (dataLen > 0) {
231 memcpy(p+1, data, dataLen);
232 }
233 mToClient.commit(cmdID, dataLen + sizeof(usrID));
234 //LOGE("sendMessageToClient 3");
235 return true;
236 }
237 return false;
238 }
239
240