1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
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
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18
19
20 #ifndef PV_INTERFACE_PROXY_H_INCLUDED
21 #include "pv_interface_proxy.h"
22 #endif
23
24 #ifndef PV_INTERFACE_PROXY_HANDLER_H_INCLUDED
25 #include "pv_interface_proxy_handler.h"
26 #endif
27
28 #ifndef PV_INTERFACE_PROXY_NOTIFIER_H_INCLUDED
29 #include "pv_interface_proxy_notifier.h"
30 #endif
31
32 #ifndef OSCL_DLL_H_INCLUDED
33 #include "oscl_dll.h"
34 #endif
35
36 #include "oscl_mem.h"
37
38 #include "pvlogger.h"
39
40 #include "oscl_scheduler.h"
41 #include "oscl_error.h"
42 #include "oscl_error_trapcleanup.h"
43 #include "oscl_tls.h"
44
45
OSCL_DLL_ENTRY_POINT_DEFAULT()46 OSCL_DLL_ENTRY_POINT_DEFAULT()
47
48
49 //
50 //CPVInterfaceProxy
51 //
52
53 OSCL_EXPORT_REF CPVInterfaceProxy * CPVInterfaceProxy::NewL(
54 PVProxiedEngine& app
55 , Oscl_DefAlloc *alloc
56 , int32 stacksize
57 , uint32 nreserve1
58 , uint32 nreserve2
59 , int32 handlerPri
60 , int32 notifierPri)
61 //called under app thread context
62 {
63 OsclMemAllocator defallocL;
64 OsclAny *ptr = NULL;
65 if (alloc)
66 {
67 ptr = alloc->ALLOCATE(sizeof(CPVInterfaceProxy));
68 OsclError::LeaveIfNull(ptr);
69 }
70 else
71 {
72 ptr = defallocL.ALLOCATE(sizeof(CPVInterfaceProxy));
73 }
74 CPVInterfaceProxy *self = OSCL_PLACEMENT_NEW(ptr, CPVInterfaceProxy(app, alloc, stacksize));
75 int32 err;
76 err = self->CPVIConstructL(nreserve1, nreserve2, handlerPri, notifierPri);
77 if (err != OSCL_ERR_NONE)
78 {
79 self->Delete();
80 return NULL;
81 }
82 return self;
83 }
84
CPVInterfaceProxy(PVProxiedEngine & app,Oscl_DefAlloc * alloc,int32 stacksize)85 OSCL_EXPORT_REF CPVInterfaceProxy::CPVInterfaceProxy(PVProxiedEngine& app, Oscl_DefAlloc*alloc, int32 stacksize)
86 : iPVApp(app)
87 //called under app thread context
88 {
89 iCommandIdCounter = 0;
90 iProxyIdCounter = 0;
91 iHandler = NULL;
92 iPVScheduler = NULL;
93 iNotifier = NULL;
94 iStacksize = stacksize;
95 iStopped = true;
96 iAlloc = (alloc) ? alloc : &iDefAlloc;
97 iLogger = NULL;
98 }
99
ConstructL(uint32 nreserve1,uint32 nreserve2,int32 handlerPri,int32 notifierPri)100 OSCL_EXPORT_REF void CPVInterfaceProxy::ConstructL(uint32 nreserve1, uint32 nreserve2, int32 handlerPri, int32 notifierPri)
101 {
102 // Create the semaphores and critical sections
103 if (iInitSem.Create() != OsclProcStatus::SUCCESS_ERROR
104 || iExitedSem.Create() != OsclProcStatus::SUCCESS_ERROR
105 || iCounterCrit.Create() != OsclProcStatus::SUCCESS_ERROR
106 || iHandlerQueueCrit.Create() != OsclProcStatus::SUCCESS_ERROR
107 || iNotifierQueueCrit.Create() != OsclProcStatus::SUCCESS_ERROR
108 || iProxyListCrit.Create() != OsclProcStatus::SUCCESS_ERROR)
109 {
110 OsclError::Leave(OsclErrGeneral);
111 }
112 //reserve space in vectors...
113 if (nreserve1 > 0)
114 iProxyList.reserve(nreserve1);
115 if (nreserve2 > 0)
116 {
117 iCommandQueue.reserve(nreserve2);
118 // iNotificationQueue.reserve(nreserve2);
119 }
120
121 //create handler
122 OsclAny *ptr = iAlloc->ALLOCATE(sizeof(CPVInterfaceProxyHandler));
123 OsclError::LeaveIfNull(ptr);
124 iHandler = OSCL_PLACEMENT_NEW(ptr, CPVInterfaceProxyHandler(this, handlerPri));
125
126 //create notifier
127 ptr = iAlloc->ALLOCATE(sizeof(CPVInterfaceProxyNotifier));
128 OsclError::LeaveIfNull(ptr);
129 iNotifier = OSCL_PLACEMENT_NEW(ptr, CPVInterfaceProxyNotifier(this, notifierPri));
130 }
131
Delete()132 OSCL_EXPORT_REF void CPVInterfaceProxy::Delete()
133 //called under app thread context
134 {
135 this->~CPVInterfaceProxy();
136 iAlloc->deallocate(this);
137 }
138
~CPVInterfaceProxy()139 OSCL_EXPORT_REF CPVInterfaceProxy::~CPVInterfaceProxy()
140 //called under app thread context
141 {
142 //make sure thread was stopped.
143 StopPVThread();
144
145 CleanupAppThreadQueues();
146
147 //delete handler and notifier
148 if (iHandler)
149 {
150 iHandler->~CPVInterfaceProxyHandler();
151 iAlloc->deallocate(iHandler);
152 }
153 iHandler = NULL;
154 if (iNotifier)
155 {
156 iNotifier->~CPVInterfaceProxyNotifier();
157 iAlloc->deallocate(iNotifier);
158 }
159 iNotifier = NULL;
160
161 iCounterCrit.Close();
162 iHandlerQueueCrit.Close();
163 iNotifierQueueCrit.Close();
164 iProxyListCrit.Close();
165 iInitSem.Close();
166 iExitedSem.Close();
167 }
168
169 //forward...
170 TOsclThreadFuncRet OSCL_THREAD_DECL pvproxythreadmain(TOsclThreadFuncArg *aPtr);
171
StartPVThread()172 OSCL_EXPORT_REF bool CPVInterfaceProxy::StartPVThread()
173 //called under app thread context
174 {
175 if (!iStopped)
176 return false;//thread already active
177
178 //add notifier AO to app thread scheduler, if it has one.
179 if (PVThreadContext::ThreadHasScheduler())
180 {
181 //Add notification active object to API thread.
182 iNotifier->AddToScheduler();
183 iNotifier->PendForExec();
184 }
185
186 // Create the PV thread.
187 OsclProcStatus::eOsclProcError err;
188 err = iPVThread.Create((TOsclThreadFuncPtr)pvproxythreadmain,
189 iStacksize,
190 (TOsclThreadFuncArg)this);
191 if (err == OSCL_ERR_NONE)
192 {
193 iStopped = false;
194 //Wait for PV thread to initialize its scheduler.
195 if (iInitSem.Wait() != OsclProcStatus::SUCCESS_ERROR)
196 OsclError::Leave(OsclErrSystemCallFailed);//unexpected sem error
197 return true;
198 }
199 else
200 {
201 //error cleanup
202 iNotifier->RemoveFromScheduler();
203 return false;
204 }
205 }
206
StopPVThread()207 OSCL_EXPORT_REF void CPVInterfaceProxy::StopPVThread()
208 //called under app thread context.
209 {
210 //if called under the PV thread, we'll get deadlock..
211 //so don't allow it.
212 if (iPVThreadContext.IsSameThreadContext())
213 OsclError::Leave(OsclErrThreadContextIncorrect);
214
215 if (iStopped)
216 return ;
217
218 //deque notifier AO
219 iNotifierQueueCrit.Lock();
220 if (iNotifier && iNotifier->IsAdded())
221 iNotifier->RemoveFromScheduler();
222 iNotifierQueueCrit.Unlock();
223
224 //Stop the scheduler loop.
225 if (iPVScheduler)
226 iPVScheduler->StopScheduler();
227
228 //Wait for PV thread to finish up, then it's safe
229 //to delete the remaining stuff.
230 if (iExitedSem.Wait() != OsclProcStatus::SUCCESS_ERROR)
231 OsclError::Leave(OsclErrSystemCallFailed);//unexpected sem error
232
233 //let the destructor know it's exited.
234 iStopped = true;
235
236 //The thread will exit on its own, but go ahead and
237 //forcibly terminate it now to make sure it's cleaned
238 //up by the time this call returns.
239 iPVThread.Terminate(0);
240 }
241
DeliverNotifications(int32 aTargetCount,int32 & aNoticesPending)242 OSCL_EXPORT_REF void CPVInterfaceProxy::DeliverNotifications(int32 aTargetCount, int32& aNoticesPending)
243 //deliver notifications off the queue, from the app thread size
244 {
245 //make sure this isn't called under PV thread...
246 if (iPVThreadContext.IsSameThreadContext())
247 OsclError::Leave(OsclErrThreadContextIncorrect);
248
249 for (int32 count = 0; count < aTargetCount;)
250 {
251 //get next notification or cleanup message.
252 iNotifierQueueCrit.Lock();
253 CPVProxyMsg notice(0, 0, NULL);
254 if (iNotificationQueue.size() > 0)
255 {
256 notice = iNotificationQueue[0];
257 iNotificationQueue.erase(&iNotificationQueue[0]);
258 }
259 iNotifierQueueCrit.Unlock();
260
261 if (notice.iMsg)
262 {
263 count++;
264 CPVProxyInterface *ext = FindInterface(notice.iProxyId);
265 if (ext)
266 ext->iClient->HandleNotification(notice.iMsgId, notice.iMsg);
267 else
268 { //since messages are cleaned up when interfaces
269 //get unregistered, we should not get here.
270 OSCL_ASSERT(0);//debug error.
271 }
272 }
273 else
274 break;//no more messages.
275 }
276 //return number of notices left after trying to process
277 //the desired number.
278 iNotifierQueueCrit.Lock();
279 aNoticesPending = iNotificationQueue.size();
280 iNotifierQueueCrit.Unlock();
281 }
282
CleanupAppThreadQueues()283 void CPVInterfaceProxy::CleanupAppThreadQueues()
284 //cleanup memory allocated in App thread.
285 {
286 //un-sent commands...
287 iHandlerQueueCrit.Lock();
288 while (!iCommandQueue.empty())
289 {
290 CPVProxyMsg *msg = &iCommandQueue[0];
291 CPVProxyInterface *proxy = FindInterface(msg->iProxyId);
292 if (proxy)
293 proxy->iClient->CleanupCommand(msg->iMsgId, msg->iMsg);
294 iCommandQueue.erase(msg);
295 }
296 iCommandQueue.clear();
297 iCommandQueue.destroy();
298 iHandlerQueueCrit.Unlock();
299
300 //proxy list...
301 iProxyListCrit.Lock();
302 iProxyList.clear();
303 iProxyList.destroy();
304 iProxyListCrit.Unlock();
305 }
306
CleanupPVThreadQueues()307 void CPVInterfaceProxy::CleanupPVThreadQueues()
308 //cleanup memory allocated in PV thread.
309 {
310 //un-sent notifications
311 iNotifierQueueCrit.Lock();
312 while (!iNotificationQueue.empty())
313 {
314 CPVProxyMsg *msg = &iNotificationQueue[0];
315 CPVProxyInterface *proxy = FindInterface(msg->iProxyId);
316 if (proxy)
317 proxy->iServer->CleanupNotification(msg->iMsgId, msg->iMsg);
318 iNotificationQueue.erase(msg);
319 }
320 iNotificationQueue.clear();
321 iNotificationQueue.destroy();
322 iNotifierQueueCrit.Unlock();
323 }
324
CancelCommand(TPVProxyId aProxyId,TPVProxyMsgId aMsgId)325 OSCL_EXPORT_REF void CPVInterfaceProxy::CancelCommand(TPVProxyId aProxyId, TPVProxyMsgId aMsgId)
326 {
327 CleanupCommands(FindInterface(aProxyId), false, aMsgId);
328 }
329
CancelAllCommands(TPVProxyId aProxyId)330 OSCL_EXPORT_REF void CPVInterfaceProxy::CancelAllCommands(TPVProxyId aProxyId)
331 {
332 CleanupCommands(FindInterface(aProxyId), true);
333 }
334
CleanupCommands(CPVProxyInterface * aExt,bool aAll,TPVProxyMsgId aMsgId)335 void CPVInterfaceProxy::CleanupCommands(CPVProxyInterface *aExt, bool aAll, TPVProxyMsgId aMsgId)
336 {
337 if (!aExt)
338 return ;
339 iHandlerQueueCrit.Lock();
340 for (uint32 i = 0; i < iCommandQueue.size(); i++)
341 {
342 CPVProxyMsg *msg = &iCommandQueue[i];
343 if (msg->iProxyId == aExt->iProxyId
344 && (aAll || msg->iMsgId == aMsgId))
345 {
346 aExt->iClient->CleanupCommand(msg->iMsgId, msg->iMsg);
347 iCommandQueue.erase(msg);
348 i--;//move back one since vecter gets scrunched.
349 if (!aAll)
350 {
351 iHandlerQueueCrit.Unlock();
352 return ;
353 }
354 }
355 }
356 iHandlerQueueCrit.Unlock();
357 }
358
CancelNotification(TPVProxyId aProxyId,TPVProxyMsgId aMsgId)359 OSCL_EXPORT_REF void CPVInterfaceProxy::CancelNotification(TPVProxyId aProxyId, TPVProxyMsgId aMsgId)
360 {
361 CleanupNotifications(FindInterface(aProxyId), false, aMsgId);
362 }
363
CancelAllNotifications(TPVProxyId aProxyId)364 OSCL_EXPORT_REF void CPVInterfaceProxy::CancelAllNotifications(TPVProxyId aProxyId)
365 {
366 CleanupNotifications(FindInterface(aProxyId), true);
367 }
368
CleanupNotifications(CPVProxyInterface * aExt,bool aAll,TPVProxyMsgId aMsgId)369 void CPVInterfaceProxy::CleanupNotifications(CPVProxyInterface *aExt, bool aAll, TPVProxyMsgId aMsgId)
370 {
371 if (!aExt)
372 return ;
373 iNotifierQueueCrit.Lock();
374 for (uint i = 0; i < iNotificationQueue.size(); i++)
375 {
376 CPVProxyMsg *msg = &iNotificationQueue[i];
377 if (msg->iProxyId == aExt->iProxyId
378 && (aAll || msg->iMsgId == aMsgId))
379 {
380 aExt->iServer->CleanupNotification(msg->iMsgId, msg->iMsg);
381 iNotificationQueue.erase(msg);
382 i--;//move back one since vector gets scrunched.
383 if (!aAll)
384 {
385 iNotifierQueueCrit.Unlock();
386 return ;
387 }
388 }
389 }
390 iNotifierQueueCrit.Unlock();
391 }
392
CleanupInterfaceMessages(CPVProxyInterface * aExt)393 void CPVInterfaceProxy::CleanupInterfaceMessages(CPVProxyInterface *aExt)
394 //cleanup all extension messages for a particular interface.
395 {
396 CleanupCommands(aExt, true);
397 CleanupNotifications(aExt, true);
398 }
399
RegisterProxiedInterface(PVProxiedInterfaceServer & server_proxy,PVProxiedInterfaceClient & client_proxy)400 OSCL_EXPORT_REF TPVProxyId CPVInterfaceProxy::RegisterProxiedInterface(
401 PVProxiedInterfaceServer& server_proxy,
402 PVProxiedInterfaceClient& client_proxy)
403 //Proxy extensions call this to register themselves.
404 {
405 TPVProxyId id = ++iProxyIdCounter;
406 iProxyListCrit.Lock();
407 CPVProxyInterface proxy(id, &server_proxy, &client_proxy);
408 int32 err;
409 OSCL_TRY(err, iProxyList.push_back(proxy););
410 iProxyListCrit.Unlock();
411 OsclError::LeaveIfError(err);
412 return id;
413 }
414
UnregisterProxiedInterface(TPVProxyId aProxyId)415 OSCL_EXPORT_REF void CPVInterfaceProxy::UnregisterProxiedInterface(TPVProxyId aProxyId)
416 //Proxy extensions call this to unregister themselves.
417 {
418 iProxyListCrit.Lock();
419 CPVProxyInterface *ext = FindInterface(aProxyId, true);
420 if (ext)
421 {
422 //cleanup unprocessed messages and remove.
423 CleanupInterfaceMessages(ext);
424 iProxyList.erase(ext);
425 }
426 iProxyListCrit.Unlock();
427 }
428
SendCommand(TPVProxyId aProxyId,OsclAny * aCmd)429 OSCL_EXPORT_REF TPVProxyMsgId CPVInterfaceProxy::SendCommand(TPVProxyId aProxyId, OsclAny *aCmd)
430 //Proxy extensions call this to send commands from app side
431 //to PV side.
432 {
433 int32 err = OSCL_ERR_NONE;
434 iCounterCrit.Lock();
435 TPVProxyMsgId id = ++iCommandIdCounter;
436 iCounterCrit.Unlock();
437 iHandlerQueueCrit.Lock();
438 CPVProxyMsg msg(aProxyId, id, aCmd);
439 OSCL_TRY(err, iCommandQueue.push_back(msg););
440 //if the queue was empty, signal the AO.
441 //note: when the queue is empty it is safe to assume the handler AO has a request
442 //pending.
443 if (iCommandQueue.size() == 1)
444 iHandler->PendComplete(OSCL_REQUEST_ERR_NONE);
445 iHandlerQueueCrit.Unlock();
446 //propagate any allocation failure...
447 OsclError::LeaveIfError(err);
448 return id;
449 }
450
SendNotification(TPVProxyId aProxyId,OsclAny * aResp)451 OSCL_EXPORT_REF TPVProxyMsgId CPVInterfaceProxy::SendNotification(TPVProxyId aProxyId, OsclAny *aResp)
452 //Proxy extensions call this to send notifications from PV
453 //side to app side.
454 {
455 int32 err = OSCL_ERR_NONE;
456 iCounterCrit.Lock();
457 TPVProxyMsgId id = ++iCommandIdCounter;
458 iCounterCrit.Unlock();
459 iNotifierQueueCrit.Lock();
460 CPVProxyMsg msg(aProxyId, id, aResp);
461 OSCL_TRY(err, iNotificationQueue.push_back(msg););
462 //if the queue was empty and the notifier is scheduled,
463 //signal it.
464 //note: when the queue is empty it is safe to assume the notifier AO has a request
465 //pending.
466 if (iNotifier
467 && iNotifier->IsAdded()
468 && iNotificationQueue.size() == 1)
469 iNotifier->PendComplete(OSCL_REQUEST_ERR_NONE);
470 iNotifierQueueCrit.Unlock();
471 //propagate any allocation failure...
472 OsclError::LeaveIfError(err);
473 return id;
474 }
475
FindInterface(TPVProxyId aId,bool locked)476 CPVProxyInterface * CPVInterfaceProxy::FindInterface(TPVProxyId aId, bool locked)
477 //lookup a registered proxy interface
478 {
479 if (!locked)
480 iProxyListCrit.Lock();
481 for (uint32 i = 0; i < iProxyList.size(); i++)
482 {
483 if (iProxyList[i].iProxyId == aId)
484 {
485 if (!locked)
486 iProxyListCrit.Unlock();
487 return &iProxyList[i];
488 }
489 }
490 if (!locked)
491 iProxyListCrit.Unlock();
492 return NULL;
493 }
494
InThread()495 void CPVInterfaceProxy::InThread()
496 //this is the guts of the proxy thread routine.
497 //it's a separate routine since it needs to be
498 //run under a trap handler in order to avoid any
499 //Cbase 66 panic from the cleanup stack.
500 {
501 int32 errTerm(OsclErrNone);
502 int32 errSched(OsclErrNone);
503
504 //create & install scheduler
505 OsclScheduler::Init("PVProxy");
506 iPVScheduler = OsclExecScheduler::Current();
507
508 iPVThreadContext.EnterThreadContext();
509
510 //add handler to scheduler
511 iHandler->AddToScheduler();
512 iHandler->PendForExec();
513
514 //App thread logon...
515 int32 err;
516 err = AppThreadLogon();
517 if (err != OsclErrNone)
518 errTerm = err;
519
520 //Start scheduler. This call blocks until scheduler is
521 //either stopped or exits due to an error.
522 err = AppStartScheduler();
523 if (err != OsclErrNone)
524 {
525 errSched = err;
526 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "appstartscheduler error %d...", errSched));
527 }
528
529
530 //Cleanup un-processed data.
531 CleanupPVThreadQueues();
532
533 //App thread logoff...
534 err = AppThreadLogoff();
535 if (err != OSCL_ERR_NONE)
536 errTerm = err;
537
538 //Deque the handler AO
539 iHandlerQueueCrit.Lock();
540 iHandler->RemoveFromScheduler();
541 iHandlerQueueCrit.Unlock();
542
543 iPVThreadContext.ExitThreadContext();
544
545 //Uninstall scheduler
546 OsclScheduler::Cleanup();
547 iPVScheduler = NULL;
548
549 //Generate panics if any leaves happened.
550 OSCL_ASSERT(errTerm == OsclErrNone);//EPVProxyPanicEngineLeave
551 OSCL_ASSERT(errSched == OsclErrNone);//EPVProxyPanicSchedulerLeave
552 }
553
554 ////////////////////////////////
555 // OS-specific Thread routines
556 ////////////////////////////////
557
558
559 #include "oscl_mem_audit.h"
560
pvproxythreadmain(TOsclThreadFuncArg * aPtr)561 TOsclThreadFuncRet OSCL_THREAD_DECL pvproxythreadmain(TOsclThreadFuncArg *aPtr)
562 //PV Thread main routine
563 {
564
565 CPVInterfaceProxy *proxy = (CPVInterfaceProxy *) aPtr;
566
567 //Init OSCL and create logger.
568 OsclBase::Init();
569 OsclErrorTrap::Init();
570 OsclMem::Init();
571 PVLogger::Init();
572
573 //Call the proxied app routine to create its logger appenders.
574 proxy->iPVApp.CreateLoggerAppenders();
575 proxy->iLogger = PVLogger::GetLoggerObject("pvproxy");
576
577 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, proxy->iLogger, PVLOGMSG_NOTICE, (0, "PVPROXY:Proxy Thread 0x%x Entry...", OsclExecScheduler::GetId()));
578
579
580 int32 leave;
581 OSCL_TRY(leave, proxy->InThread(););
582
583 if (leave != OsclErrNone)
584 {
585 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, proxy->iLogger, PVLOGMSG_ERR, (0, "PVPROXY:Proxy Thread 0x%x Exit: Leave Reason %d", OsclExecScheduler::GetId(), leave));
586 }
587 else
588 {
589 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, proxy->iLogger, PVLOGMSG_NOTICE, (0, "PVPROXY:Proxy Thread 0x%x Exit: Normal", OsclExecScheduler::GetId()));
590 }
591
592 //Cleanup logger.
593 PVLogger::Cleanup();
594
595 OsclMem::Cleanup();
596 proxy->iLogger = NULL;
597 OsclErrorTrap::Cleanup();
598 OsclBase::Cleanup();
599
600 //Signal & Exit
601 proxy->iExitedSem.Signal();
602
603 return 0;
604 }
605
CPVIConstructL(uint32 & aNreserve1,uint32 & aNreserve2,int32 & aHandlerPri,int32 & aNotifierPri)606 int32 CPVInterfaceProxy::CPVIConstructL(uint32 &aNreserve1, uint32 &aNreserve2, int32 &aHandlerPri, int32 &aNotifierPri)
607 {
608 int32 err;
609 OSCL_TRY(err, ConstructL(aNreserve1, aNreserve2, aHandlerPri, aNotifierPri););
610 return err;
611 }
612
613
AppThreadLogon()614 int32 CPVInterfaceProxy::AppThreadLogon()
615 {
616 int32 err;
617 OSCL_TRY(err, iPVApp.PVThreadLogon(*this););
618 return err;
619 }
620
AppThreadLogoff()621 int32 CPVInterfaceProxy::AppThreadLogoff()
622 {
623 int32 err;
624 OSCL_TRY(err, iPVApp.PVThreadLogoff(*this););
625 return err;
626 }
627
AppStartScheduler()628 int32 CPVInterfaceProxy::AppStartScheduler()
629 {
630 int32 err;
631 OSCL_TRY(err, iPVScheduler->StartScheduler(&iInitSem););
632 return err;
633 }
634
635