uiacceltk/hitchcock/goommonitor/src/goomthresholdcrossedao.inl
changeset 0 15bf7259bb7c
equal deleted inserted replaced
-1:000000000000 0:15bf7259bb7c
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  A Synch Object thread for EGL resource monitoring
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 typedef void* EGLSync;
       
    20 typedef EGLSync (*eglCreateSync)(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
       
    21 typedef EGLBoolean (*eglDestroySync)(EGLDisplay dpy, EGLSync sync);
       
    22 typedef EGLint (*eglClientWaitSync)(EGLDisplay dpy, EGLSync sync, EGLint flags, TUint64 timeout);
       
    23 #ifndef EGL_SYNC_CONDITION_KHR
       
    24 #define EGL_SYNC_CONDITION_KHR  0x30f8
       
    25 #endif
       
    26 
       
    27 
       
    28 _LIT(KGoomAsyncWaitThreadName,"goom_asy");
       
    29 
       
    30 NONSHARABLE_CLASS(CGoomThresholdCrossed): public CActive
       
    31     {
       
    32     public:
       
    33     CGoomThresholdCrossed(CMemoryMonitor& aMonitor, TUint aAction, TInt aThreshold)
       
    34         :CActive(CActive::EPriorityHigh), 
       
    35         iMarkerState(KErrNotFound),
       
    36         iActiveThreshold(aThreshold),
       
    37         iAction(aAction),
       
    38         iThread(RThread().Id()),
       
    39         iMonitor(aMonitor)
       
    40         {
       
    41         FUNC_LOG;
       
    42         CActiveScheduler::Add(this);
       
    43         iSema.CreateLocal();
       
    44         iStop.CreateLocal();
       
    45         iThreadName.Append(KGoomAsyncWaitThreadName);
       
    46         iThreadName.AppendNum(aAction); // assuming single observer for an action
       
    47         RequestNotifications();
       
    48         }
       
    49 
       
    50     // ---------------------------------------------------------------------------
       
    51     // Thread name
       
    52     // Thread name consists on constant part and action that triggers the ao 
       
    53     // ---------------------------------------------------------------------------
       
    54     //
       
    55     const TDesC& ThreadName()
       
    56         {
       
    57         FUNC_LOG;
       
    58         return iThreadName;
       
    59         }
       
    60     
       
    61     void Stop()
       
    62         {
       
    63         if (!iPaused)
       
    64             {
       
    65             iStop.Wait();
       
    66             iPaused = ETrue;
       
    67             ResetThresholds();
       
    68             }
       
    69          }   
       
    70     void Continue()
       
    71         {
       
    72         if (iPaused)
       
    73             {
       
    74             iStop.Signal();
       
    75             iPaused = EFalse;
       
    76             }
       
    77         }
       
    78     // ---------------------------------------------------------------------------
       
    79     // Destructor
       
    80     // Standard destructor, cancels pending request and releases egl wait
       
    81     // ---------------------------------------------------------------------------
       
    82     //
       
    83     ~CGoomThresholdCrossed()
       
    84         {
       
    85         FUNC_LOG;
       
    86         Cancel();
       
    87         iSema.Close();
       
    88         iStop.Close();
       
    89         }        
       
    90  
       
    91     // ---------------------------------------------------------------------------
       
    92     // SetThreshold
       
    93     // Destroys the synch object so EGL busy loop will get new values 
       
    94     // ---------------------------------------------------------------------------
       
    95     //
       
    96     void SetThreshold(TInt aThreshold)
       
    97         {
       
    98         FUNC_LOG;
       
    99         if (iActiveThreshold != aThreshold)
       
   100             {
       
   101             iActiveThreshold = aThreshold;
       
   102             ResetThresholds();
       
   103             }
       
   104         }
       
   105 
       
   106     // ---------------------------------------------------------------------------
       
   107     // ResetThresholds
       
   108     // See SetThreshold. Releases synch object 
       
   109     // ---------------------------------------------------------------------------
       
   110     //
       
   111     void ResetThresholds()
       
   112         {
       
   113         FUNC_LOG;
       
   114         if (iMarkerState == KErrNone)
       
   115             {
       
   116             iMarkerState = KErrDied;
       
   117             eglDestroySync_fptr(iDpy, iMarker);
       
   118             }  
       
   119         }
       
   120             
       
   121     // ---------------------------------------------------------------------------
       
   122     // StartRequestEvents
       
   123     // Busy loop that is blocked by egl wait. exit on Cancel. 
       
   124     // Runs on separate thread.
       
   125     // ---------------------------------------------------------------------------
       
   126     //
       
   127     void StartRequestEvents()
       
   128         {
       
   129         FUNC_LOG;
       
   130         iDpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
       
   131         EGLint major, minor;
       
   132         eglInitialize(iDpy, &major, &minor);
       
   133         
       
   134         eglCreateSync_fptr = (eglCreateSync)eglGetProcAddress("eglCreateSyncKHR");
       
   135         eglDestroySync_fptr = (eglDestroySync)eglGetProcAddress("eglDestroySyncKHR");
       
   136         eglClientWaitSync_fptr = (eglClientWaitSync)eglGetProcAddress("eglClientWaitSyncKHR");
       
   137         if (!eglCreateSync_fptr || !eglDestroySync_fptr || !eglClientWaitSync_fptr )
       
   138             {
       
   139             /* Free allocated memory */
       
   140             eglTerminate(iDpy);
       
   141             return;
       
   142             }
       
   143             
       
   144         while(!iCancelled)
       
   145             {
       
   146             iStop.Wait();
       
   147             iStop.Signal();
       
   148             TUint usedThreshold = Min(iActiveThreshold,32*1024*1024) ;
       
   149             TUint action = iAction;
       
   150             const EGLint sync_attribs[] =
       
   151                 {
       
   152                 EGL_SYNC_CONDITION_KHR,              action,
       
   153                 EGL_PROF_MEMORY_USAGE_THRESHOLD_NOK, 32*1024*1024-usedThreshold,
       
   154                 EGL_NONE
       
   155                 };
       
   156 
       
   157             /* Create a resource profiling sync */
       
   158             iMarker = eglCreateSync_fptr(iDpy,
       
   159                                          EGL_SYNC_RESOURCE_PROFILING_NOK,
       
   160                                          sync_attribs);
       
   161             iMarkerState = KErrNone;
       
   162 
       
   163             /* Wait until graphics memory usage exceeds the given threshold */
       
   164             eglClientWaitSync_fptr(iDpy, iMarker, 0, EGL_FOREVER_KHR);
       
   165             
       
   166             if (iMarkerState != KErrDied)
       
   167                 {
       
   168                 eglDestroySync_fptr(iDpy, iMarker);
       
   169                 Trigger(action/*, usedThreshold*/);
       
   170                 }                
       
   171             }            
       
   172 
       
   173         /* Free allocated memory */
       
   174         eglTerminate(iDpy);
       
   175         iMarkerState = KErrNotFound;
       
   176         }
       
   177  
       
   178     // ---------------------------------------------------------------------------
       
   179     // RequestNotifications
       
   180     // Setting listener for changes, no queue at the moment
       
   181     // ---------------------------------------------------------------------------
       
   182     //
       
   183     void RequestNotifications(TBool aWasPaused = EFalse)
       
   184         {
       
   185         FUNC_LOG;
       
   186         iSema.Wait();
       
   187         iStatus = KRequestPending;
       
   188         SetActive();
       
   189         iSema.Signal();
       
   190         if (!aWasPaused)
       
   191             {
       
   192             Continue();
       
   193             }            
       
   194         }
       
   195     
       
   196     // ---------------------------------------------------------------------------
       
   197     // Trigger
       
   198     // Letting mainthread to know that threshold was crossed
       
   199     // ---------------------------------------------------------------------------
       
   200     //
       
   201     void Trigger(TInt aReason)
       
   202         {
       
   203         FUNC_LOG;
       
   204         iSema.Wait();    
       
   205         if (IsActive() && iStatus == KRequestPending)
       
   206             {
       
   207             Stop();
       
   208             RThread t;
       
   209             TInt err = t.Open(iThread);
       
   210             if (err)
       
   211                 {
       
   212                 RDebug::Print(_L("CGoomThresholdCrossed::Trigger() RThread::Open() error: %d"), err );
       
   213                 User::Invariant();
       
   214                 }
       
   215             TRequestStatus* status = &iStatus;
       
   216             t.RequestComplete(status, aReason);
       
   217             t.Close();
       
   218             }
       
   219         iSema.Signal();
       
   220         }
       
   221         
       
   222     // ---------------------------------------------------------------------------
       
   223     // RunL()
       
   224     // Thread safe way to hanlde crossed threshold in main thread
       
   225     // ---------------------------------------------------------------------------
       
   226     //
       
   227     void RunL()
       
   228         {
       
   229         FUNC_LOG;
       
   230         switch (iStatus.Int())
       
   231             {
       
   232         case KErrNone:
       
   233             break;
       
   234         case KErrCancel:
       
   235             return;
       
   236         default:
       
   237             break;
       
   238             }
       
   239 		
       
   240 	TInt thresholdType = iStatus.Int();
       
   241 		
       
   242         TRAP_IGNORE(iMonitor.FreeMemThresholdCrossedL(thresholdType, iAction));
       
   243         
       
   244         RequestNotifications(iPaused);
       
   245         }
       
   246     
       
   247     // ---------------------------------------------------------------------------
       
   248     // Cancel
       
   249     // Cancels the busy loop even the Object was not active
       
   250     // ---------------------------------------------------------------------------
       
   251     //
       
   252     void Cancel()
       
   253         {
       
   254         FUNC_LOG;
       
   255         iCancelled = ETrue;
       
   256         ResetThresholds();
       
   257         CActive::Cancel();
       
   258         }
       
   259         
       
   260     // ---------------------------------------------------------------------------
       
   261     // DoCancel
       
   262     // Cancels the active object
       
   263     // ---------------------------------------------------------------------------
       
   264     //
       
   265     void DoCancel()
       
   266         {
       
   267         FUNC_LOG;
       
   268         Trigger(KErrCancel);
       
   269         }
       
   270     
       
   271     EGLSync iMarker;
       
   272     TInt iMarkerState;
       
   273     TUint iActiveThreshold;
       
   274     TUint iAction;
       
   275     TBool iCancelled;
       
   276     RCriticalSection iSema;
       
   277     TThreadId iThread;
       
   278     eglCreateSync  eglCreateSync_fptr;
       
   279     eglDestroySync eglDestroySync_fptr;
       
   280     eglClientWaitSync eglClientWaitSync_fptr ; 
       
   281     CMemoryMonitor& iMonitor;
       
   282     TBuf<16> iThreadName;
       
   283     EGLDisplay iDpy;
       
   284     TBool iPaused;
       
   285     RCriticalSection iStop;
       
   286     };
       
   287 
       
   288 // ---------------------------------------------------------------------------
       
   289 // Entry point into the new thread
       
   290 // ---------------------------------------------------------------------------
       
   291 //   
       
   292 GLDEF_C TInt EGLSynchObjThreadStartFunction(TAny* aBridge)
       
   293     {
       
   294     CTrapCleanup* trapCleanup = CTrapCleanup::New();
       
   295     if (!trapCleanup)
       
   296         {
       
   297         return KErrNoMemory;
       
   298         }
       
   299         
       
   300     CGoomThresholdCrossed* ao = static_cast<CGoomThresholdCrossed*>(aBridge);
       
   301     TInt err = User::RenameThread(ao->ThreadName());
       
   302     RThread().SetPriority(EPriorityAbsoluteHigh);
       
   303     ao->StartRequestEvents();
       
   304 
       
   305     delete trapCleanup;
       
   306     return err;
       
   307     }
       
   308 
       
   309 CGoomThresholdCrossed* CreateThresholdCrossedThreadL(CMemoryMonitor& aMonitor, TUint aAction, TInt aThreshold)
       
   310     {
       
   311     FUNC_LOG;
       
   312     CGoomThresholdCrossed* ao = new (ELeave) CGoomThresholdCrossed(aMonitor, aAction, aThreshold);
       
   313     CleanupStack::PushL(ao);
       
   314     RThread syncThread;
       
   315 
       
   316     User::LeaveIfError(syncThread.Create(
       
   317             ao->ThreadName(),
       
   318             EGLSynchObjThreadStartFunction,
       
   319             16384, // magic
       
   320             0, // uses same heap
       
   321             (TAny*)ao, 
       
   322             EOwnerThread));
       
   323 
       
   324     syncThread.Resume();
       
   325     syncThread.Close();
       
   326     CleanupStack::Pop();
       
   327     return ao;
       
   328     }
       
   329