• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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