sl@0: // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // Name : timerhandler.cpp sl@0: // Part of : librt-timer specific cpp file sl@0: // This is a project specific source file for building the sl@0: // timer related functions as part of librt library. sl@0: // sl@0: // sl@0: sl@0: sl@0: #include "sysif.h" sl@0: #include "timerhandler.h" sl@0: #include "timerclient.h" sl@0: #include "timerserver.h" sl@0: #include "timermessage.h" sl@0: #include "timer.h" sl@0: #include <pthread.h> sl@0: sl@0: #ifdef __WINSCW__ sl@0: #include <pls.h> // For emulator WSD API sl@0: const TUid KLibrtUid3 = {0x2001E553}; sl@0: #elif defined __X86GCC__ sl@0: CTimerReqHandler gTimerHandler; sl@0: #endif sl@0: sl@0: sl@0: CTimerReqHandler* getTimerHandler() sl@0: { sl@0: #ifdef __WINSCW__ sl@0: // Access the PLS of this process sl@0: CTimerReqHandler* lTimerHandlerPtr = Pls<CTimerReqHandler>(KLibrtUid3); sl@0: return lTimerHandlerPtr; sl@0: #elif defined __X86GCC__ sl@0: return &gTimerHandler; sl@0: #else sl@0: static CTimerReqHandler sgTimerHandler; sl@0: return &sgTimerHandler; sl@0: #endif sl@0: } sl@0: sl@0: sl@0: CTimerReqHandler::CTimerReqHandler() : iTimers(CTimerReqHandler::KTimersGran) sl@0: { sl@0: iTimersLock.CreateLocal(); sl@0: iServConnectLock.CreateLocal(); sl@0: iTimerSemaphore.CreateLocal(0); sl@0: } sl@0: sl@0: sl@0: CTimerReqHandler::~CTimerReqHandler() sl@0: { sl@0: iTimersLock.Close(); sl@0: iTimers.ResetAndDestroy(); sl@0: iTimerSemaphore.Close(); sl@0: iServ.Close(); sl@0: iServConnectLock.Close(); sl@0: } sl@0: sl@0: //method to create a timer sl@0: TInt CTimerReqHandler::CreateTimer(TInt& aTimerId, struct sigevent *aSig) sl@0: { sl@0: TInt lRet = KErrNone; sl@0: if(iTimers.Count() >= MAXTIMERLIMIT) sl@0: { sl@0: lRet = KErrWouldBlock; sl@0: } sl@0: sl@0: if(lRet == KErrNone) sl@0: { sl@0: if(aSig != NULL) sl@0: { sl@0: switch(aSig->sigev_notify) sl@0: { sl@0: case SIGEV_SIGNAL: sl@0: #if (!defined SYMBIAN_OE_POSIX_SIGNALS || !defined SYMBIAN_OE_LIBRT) sl@0: { sl@0: aTimerId = -1; sl@0: lRet = KErrNotSupported; sl@0: break; sl@0: } sl@0: #else sl@0: sl@0: if(aSig->sigev_signo < 1 || aSig->sigev_signo > SIGRTMAX) sl@0: { sl@0: aTimerId = -1; sl@0: lRet = KErrArgument; sl@0: } sl@0: #endif sl@0: sl@0: case SIGEV_NONE: sl@0: case SIGEV_THREAD: sl@0: break; sl@0: default: sl@0: aTimerId = -1; sl@0: lRet = KErrArgument; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: if(lRet == KErrNone) sl@0: { sl@0: RHeap* oldHeap = User::SwitchHeap(Backend()->Heap()); sl@0: CRtTimer *lTimer = CRtTimer::New(aSig); sl@0: if(NULL == lTimer) sl@0: { sl@0: aTimerId = -1; sl@0: lRet = KErrNoMemory; sl@0: User::SwitchHeap(oldHeap); sl@0: } sl@0: else sl@0: { sl@0: aTimerId = lTimer->iTimerId; sl@0: iTimersLock.Wait(); sl@0: TRAP(lRet, iTimers.AppendL(lTimer)); sl@0: User::SwitchHeap(oldHeap); sl@0: iTimersLock.Signal(); sl@0: } sl@0: } sl@0: } sl@0: sl@0: return lRet; sl@0: } sl@0: sl@0: //method to delete a timer sl@0: TInt CTimerReqHandler::RemoveTimer(const TInt& aTimerId) sl@0: { sl@0: if(FindTimer(aTimerId)== NULL) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: TInt lRet = Connect(); sl@0: if(lRet == KErrNone) sl@0: { sl@0: session.OnDemandConnect(iServer); sl@0: lRet = session.DeleteTimer(aTimerId); sl@0: } sl@0: return lRet; sl@0: } sl@0: sl@0: //method to set a new timeout value for a timer sl@0: TInt CTimerReqHandler::SetTime(const TInt& aTimerId, TInt aFlag, const struct itimerspec *aIpTime, sl@0: struct itimerspec *aOpTime) sl@0: { sl@0: TInt lRet = Connect(); sl@0: if(lRet == KErrNone) sl@0: { sl@0: CRtTimer* lTimer = FindTimer(aTimerId); sl@0: if(lTimer != NULL) sl@0: lRet = lTimer->SetTime(aFlag, aIpTime, aOpTime); sl@0: else sl@0: lRet = KErrArgument; sl@0: } sl@0: sl@0: return lRet; sl@0: } sl@0: sl@0: //method to makesure that the timer server is started only once on demand. sl@0: TInt CTimerReqHandler::Connect() sl@0: { sl@0: TInt lRet = KErrNone; sl@0: sl@0: iServConnectLock.Wait(); sl@0: if(!iIsServStarted) sl@0: { sl@0: lRet = StartTimerServer(); sl@0: if(lRet == KErrNone) sl@0: iIsServStarted = ETrue; sl@0: } sl@0: iServConnectLock.Signal(); sl@0: return lRet; sl@0: } sl@0: sl@0: //start up function for the timer server. sl@0: static TInt sTimerServer(TAny*) sl@0: { sl@0: RHeap *oldHeap = User::SwitchHeap(Backend()->Heap()); sl@0: CTrapCleanup* cleanup = CTrapCleanup::New(); sl@0: TRAPD(ret, CTimerServer::NewTimerServerL()); sl@0: delete cleanup; sl@0: User::SwitchHeap(oldHeap); sl@0: return ret; sl@0: } sl@0: sl@0: //method to start the timer server sl@0: TInt CTimerReqHandler::StartTimerServer() sl@0: { sl@0: TRequestStatus status; sl@0: TInt lRet = iServ.Create(KNullDesC, sTimerServer, sl@0: KDefaultStackSize, NULL, (TAny*)NULL); sl@0: if(lRet == KErrNone) sl@0: { sl@0: iServ.SetPriority(EPriorityAbsoluteHigh);// match the signal server priority. sl@0: iServ.Rendezvous(status); sl@0: iServ.Resume(); //get this ready sl@0: User::WaitForRequest(status); sl@0: } sl@0: return lRet; sl@0: } sl@0: sl@0: //method to get the "time to expiration" of a timer sl@0: TInt CTimerReqHandler::Time(const TInt& aTimerId, struct itimerspec *aTime) sl@0: { sl@0: CRtTimer* lTimer = FindTimer(aTimerId); sl@0: if(lTimer == NULL) sl@0: return KErrArgument; sl@0: return lTimer->Time(aTime); sl@0: } sl@0: sl@0: //method to get the overruns for a timer sl@0: TInt CTimerReqHandler::OverrunCount(const TInt& aTimerId, TInt& aOverrunCount) sl@0: { sl@0: CRtTimer* lTimer = FindTimer(aTimerId); sl@0: if(lTimer == NULL) sl@0: return KErrArgument; sl@0: return lTimer->OverrunCount(aOverrunCount); sl@0: } sl@0: sl@0: //find the timer with the given timer id sl@0: CRtTimer* CTimerReqHandler::FindTimer(const TInt& aTimerId) sl@0: { sl@0: CRtTimer* lRtTimerP = NULL; sl@0: iTimersLock.Wait(); sl@0: TInt lTimerCount = iTimers.Count(); sl@0: for(TInt lIdx =0; lIdx < lTimerCount; lIdx++) sl@0: { sl@0: if(iTimers[lIdx]->iTimerId == aTimerId) sl@0: { sl@0: lRtTimerP = (iTimers[lIdx]); sl@0: break; sl@0: } sl@0: } sl@0: iTimersLock.Signal(); sl@0: return lRtTimerP; sl@0: } sl@0: