Home | History | Annotate | Download | only in src
      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 
     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 
     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 
    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 
    132 OSCL_EXPORT_REF void CPVInterfaceProxy::Delete()
    133 //called under app thread context
    134 {
    135     this->~CPVInterfaceProxy();
    136     iAlloc->deallocate(this);
    137 }
    138 
    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 
    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 
    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 
    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 
    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 
    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 
    325 OSCL_EXPORT_REF void CPVInterfaceProxy::CancelCommand(TPVProxyId aProxyId, TPVProxyMsgId aMsgId)
    326 {
    327     CleanupCommands(FindInterface(aProxyId), false, aMsgId);
    328 }
    329 
    330 OSCL_EXPORT_REF void CPVInterfaceProxy::CancelAllCommands(TPVProxyId aProxyId)
    331 {
    332     CleanupCommands(FindInterface(aProxyId), true);
    333 }
    334 
    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 
    359 OSCL_EXPORT_REF void CPVInterfaceProxy::CancelNotification(TPVProxyId aProxyId, TPVProxyMsgId aMsgId)
    360 {
    361     CleanupNotifications(FindInterface(aProxyId), false, aMsgId);
    362 }
    363 
    364 OSCL_EXPORT_REF void CPVInterfaceProxy::CancelAllNotifications(TPVProxyId aProxyId)
    365 {
    366     CleanupNotifications(FindInterface(aProxyId), true);
    367 }
    368 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    614 int32 CPVInterfaceProxy::AppThreadLogon()
    615 {
    616     int32 err;
    617     OSCL_TRY(err, iPVApp.PVThreadLogon(*this););
    618     return err;
    619 }
    620 
    621 int32 CPVInterfaceProxy::AppThreadLogoff()
    622 {
    623     int32 err;
    624     OSCL_TRY(err, iPVApp.PVThreadLogoff(*this););
    625     return err;
    626 }
    627 
    628 int32 CPVInterfaceProxy::AppStartScheduler()
    629 {
    630     int32 err;
    631     OSCL_TRY(err, iPVScheduler->StartScheduler(&iInitSem););
    632     return err;
    633 }
    634 
    635