Major commit for preparing 1.1.1 release
[spandex:spandex.git] / sct / symbian / common / src / symbian_sicommon.cpp
1 /*\r
2  * Spandex benchmark and test framework.\r
3  *\r
4  * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).\r
5  *\r
6  * Contact: Kari J. Kangas <kari.j.kangas@nokia.com>\r
7  *\r
8  *   This framework is free software; you can redistribute it and/or modify it\r
9  * under the terms of the GNU Lesser General Public License as published by the\r
10  * Free Software Foundation, version 2.1 of the License.\r
11  *\r
12  *   This framework is distributed in the hope that it will be useful, but\r
13  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License\r
15  * for more details.\r
16  *\r
17  *   You should have received a copy of the GNU Lesser General Public License\r
18  * along with this framework; if not, see <http://www.gnu.org/licenses/>.\r
19  *\r
20  */\r
21 \r
22 /* Symbian includes */\r
23 #include <e32def.h>\r
24 #include <e32std.h>\r
25 #include <w32std.h>\r
26 #include <e32debug.h>\r
27 #include <hal.h>\r
28 \r
29 /* Stdlib includes*/\r
30 #include <math.h>\r
31 #include <string.h>\r
32 #include <stdio.h>\r
33 #include <stdarg.h>\r
34 \r
35 /* Includes from Spandex core */\r
36 #include "sct_sicommon.h"\r
37 #include "sct_utils.h"\r
38 #include "sct_module.h"\r
39 #include "sct_systemmodule.h"\r
40 \r
41 #include "CSpandexCommon.h"\r
42 #include "CPlatform.h"\r
43 \r
44 #if defined( INCLUDE_SYMBIANBITGDI_MODULE )\r
45 # include "sct_symbianbitgdimodule.h"\r
46 #endif  /* defined( INCLUDE_SYMBIANBITGDI_MODULE ) */ \r
47 \r
48 #if defined( INCLUDE_SYMBIANSVG_MODULE )\r
49 # include "sct_symbiansvgmodule.h"\r
50 #endif  /* defined( INCLUDE_SYMBIANSVG_MODULE ) */\r
51 \r
52 #if defined( INCLUDE_EGL_MODULE )\r
53 /* For sctEglGetProcAddress */\r
54 #include "sct_eglmodule.h"\r
55 #endif  /* defined( INCLUDE_EGL_MODULE ) */\r
56 \r
57 #define EMULATOR_TIMER_MULTIPLIER       1000\r
58 #define DEBUG_PRINT_OUTPUT_BUFFER_SIZE  1024\r
59 \r
60 /* ---------------------------------------------------------------------- */\r
61 /*!\r
62  *\r
63  *\r
64  */\r
65 void* siCommonGetContext( void )\r
66 {\r
67     return CPlatform::SpandexCommon();\r
68 }\r
69 \r
70 /* ---------------------------------------------------------------------- */\r
71 /*!\r
72  *\r
73  *\r
74  */\r
75 const char* siCommonQueryAttribute( void* aContext, SCTSystemAttribute aName )\r
76 {\r
77         CSpandexCommon* spandex = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
78         \r
79     SCT_ASSERT( spandex == siCommonGetContext() );\r
80     SCT_ASSERT_ALWAYS( spandex != NULL );\r
81 \r
82         switch( aName )\r
83         {\r
84         case SCT_SYSINFO_DEVICE_TYPE:\r
85                 return spandex->DeviceInfo().deviceName;\r
86 \r
87         case SCT_SYSINFO_CPU:\r
88                 return spandex->DeviceInfo().cpu;\r
89                 \r
90     case SCT_SYSINFO_OS:\r
91                 return spandex->DeviceInfo().OS;\r
92 \r
93         case SCT_SYSINFO_RAM_TOTAL:\r
94                 return spandex->DeviceInfo().totalMemory;\r
95 \r
96         case SCT_SYSINFO_RAM_FREE:\r
97                 return spandex->DeviceInfo().freeMemory;\r
98                 \r
99         default:\r
100         SCT_ASSERT_ALWAYS( 0 );\r
101                 return NULL;\r
102         }\r
103 }\r
104 \r
105 /* ---------------------------------------------------------------------- */\r
106 /*!\r
107  *\r
108  *\r
109  *\r
110  */\r
111 unsigned long siCommonGetTimerFrequency( void* /*aContext*/ )\r
112 {       \r
113 #if defined( EKA2 )\r
114     return 1000;\r
115 #else   /* defined( EKA2 ) */\r
116         TInt timerPeriod; //in microseconds\r
117         TInt timerFreq;\r
118 \r
119         HAL::Get( HALData::ESystemTickPeriod, timerPeriod );\r
120 \r
121         timerFreq = 1000000 / timerPeriod; // in Hz\r
122 \r
123 /* Make Symbian timer in emulator to appear more accurate than what it really is */\r
124 # if defined( __WINS__ )\r
125     timerFreq *= EMULATOR_TIMER_MULTIPLIER;\r
126 # endif /* defined( __WINS__ ) */\r
127 \r
128         return timerFreq;\r
129 #endif  /* defined( EKA2 ) */\r
130 }\r
131 \r
132 /* ---------------------------------------------------------------------- */\r
133 /*!\r
134  *\r
135  *\r
136  *\r
137  */\r
138 unsigned long siCommonGetTimerTick( void* /*aContext*/ )\r
139 {\r
140 #if defined( EKA2 )\r
141     return User::NTickCount();\r
142 #else   /* defined( EKA2 ) */\r
143 # if defined( __WINS__ )\r
144         return ( unsigned long )( User::TickCount() * EMULATOR_TIMER_MULTIPLIER );\r
145 # else  /* defined( __WINS__ ) */\r
146         return ( unsigned long )( User::TickCount() );\r
147 # endif /* defined( __WINS__ ) */\r
148 #endif  /* defined( EKA2 ) */\r
149 }\r
150 \r
151 /* ---------------------------------------------------------------------- */\r
152 /*!\r
153  *\r
154  *\r
155  *\r
156  */\r
157 void siCommonDebugPrintf( void* aContext, const char* fmt, ... )\r
158 {\r
159         CSpandexCommon* spandex = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
160     char            buf[ DEBUG_PRINT_OUTPUT_BUFFER_SIZE ];\r
161     va_list         ap;\r
162 \r
163     SCT_ASSERT( spandex == siCommonGetContext() );\r
164     SCT_ASSERT_ALWAYS( spandex != NULL );\r
165     SCT_ASSERT_ALWAYS( fmt != NULL );   \r
166     \r
167     /* TODO FIXME: following code has potential buffer overflow, in which case\r
168      * make the debug print messages shorter. Too bad symbian does not seem to\r
169      * support vnsprintf. */\r
170         va_start( ap, fmt );\r
171         vsprintf( buf, fmt, ap );\r
172         va_end( ap );\r
173 \r
174     RDebug::Printf( buf );\r
175 }\r
176 \r
177 /* ---------------------------------------------------------------------- */\r
178 /*!\r
179  *\r
180  *\r
181  *\r
182  */\r
183 void siCommonErrorMessage( void* aContext, const char* aErrorMessage )\r
184 {\r
185         CSpandexCommon* spandex     = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
186     FILE*           outputFile  = NULL;\r
187     \r
188     SCT_ASSERT( spandex == siCommonGetContext() );\r
189     SCT_ASSERT_ALWAYS( spandex != NULL );\r
190            \r
191     outputFile = spandex->OutputFile();\r
192         if( outputFile )\r
193         {\r
194                 fputs( "SPANDEX ERROR: ", outputFile );\r
195                 fputs( aErrorMessage, outputFile );\r
196         fputs( "\n", outputFile );\r
197                 fflush( outputFile );\r
198         }\r
199 \r
200     CPlatform::DisplayError( "Spandex error", aErrorMessage );\r
201 }\r
202 \r
203 /* ---------------------------------------------------------------------- */\r
204 /*!\r
205  *\r
206  *\r
207  *\r
208  */\r
209 void siCommonWarningMessage( void* aContext, const char* aWarningMessage )\r
210 {\r
211         CSpandexCommon* spandex     = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
212     FILE*           outputFile  = NULL;\r
213     \r
214     SCT_ASSERT( spandex == siCommonGetContext() );\r
215     SCT_ASSERT_ALWAYS( spandex != NULL );\r
216            \r
217     outputFile = spandex->OutputFile();\r
218         if( outputFile )\r
219         {\r
220                 fputs( "#SPANDEX WARNING: ", outputFile );\r
221                 fputs( aWarningMessage, outputFile );\r
222         fputs( "\n", outputFile );\r
223                 fflush( outputFile );\r
224         }\r
225 }\r
226 \r
227 /* ---------------------------------------------------------------------- */\r
228 /*!\r
229  *\r
230  *\r
231  *\r
232  */\r
233 SCTLog* siCommonGetErrorLog( void* /*context*/ )\r
234 {\r
235     return CPlatform::GetLog();\r
236 }\r
237 \r
238 /* ---------------------------------------------------------------------- */\r
239 /*!\r
240  *\r
241  *\r
242  *\r
243  */\r
244 void siCommonSetErrorLog( void* /*context*/, SCTLog* log )\r
245 {\r
246     CPlatform::SetLog( log );\r
247 }\r
248 \r
249 /* ---------------------------------------------------------------------- */\r
250 /*!\r
251  *\r
252  *\r
253  *\r
254  */\r
255 void siCommonProgressMessage( void* /*aContext*/, int aTotalBenchmark, int aCurrentBenchmark, int aCurrentRepeat, const char* aBenchmarkName )\r
256 {\r
257         CPlatform::ReportProgress( aTotalBenchmark, aCurrentBenchmark, aCurrentRepeat, aBenchmarkName );\r
258 }\r
259 \r
260 /* ---------------------------------------------------------------------- */\r
261 /*!\r
262  *\r
263  * \r
264  *\r
265  */\r
266 void siCommonAssert( void* aContext, void* aExp, void* aFile, unsigned int aLine )\r
267 {\r
268         CSpandexCommon* spandex     = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
269     FILE*           outputFile  = NULL;\r
270 \r
271     /* Assert strings are potentially very long so do formatted print only to a\r
272      * file and avoid potential for buffer overflow due to missing snprintf. */\r
273         if( spandex != NULL )\r
274         {\r
275             outputFile = spandex->OutputFile();\r
276                 if( outputFile )\r
277                 {\r
278             siCommonFlushOutput( aContext );\r
279             fprintf( outputFile,\r
280                      "\nSpandex assert failed.\nExpresion: ( %s )\nFile: %s\nLine: %d\n",\r
281                      ( char* )( aExp ), ( char* )( aFile ), ( int )( aLine ) ); \r
282             fflush( outputFile );\r
283             fclose( outputFile );\r
284         }\r
285         }\r
286 \r
287     CPlatform::DisplayError( "Spandex assert", "See the output file for details" );\r
288     User::Panic( _L( "Spandex assert" ), 0 );\r
289 }\r
290 \r
291 /* ---------------------------------------------------------------------- */\r
292 /*!\r
293  * \r
294  *\r
295  */\r
296 void* siCommonMemoryAlloc( void* /*aContext*/, unsigned int aSize )\r
297 {\r
298         return User::Alloc( aSize );\r
299 }\r
300 \r
301 /* ---------------------------------------------------------------------- */\r
302 /*!\r
303  * \r
304  *\r
305  */\r
306 void* siCommonMemoryRealloc( void* /*aContext*/, void* aData, unsigned int aSize )\r
307 {\r
308         return User::ReAlloc( aData, aSize );\r
309 }\r
310 \r
311 /* ---------------------------------------------------------------------- */\r
312 /*!\r
313  *\r
314  *\r
315  */\r
316 void siCommonMemoryFree( void* /*aContext*/, void* aMemblock )\r
317 {\r
318         User::Free( aMemblock );\r
319 }\r
320 \r
321 /* ---------------------------------------------------------------------- */\r
322 /*!\r
323  *\r
324  *\r
325  *\r
326  */\r
327 char siCommonReadChar( void* aContext )\r
328 {\r
329         char            ch;\r
330         CSpandexCommon* spandex = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
331 \r
332     SCT_ASSERT_ALWAYS( spandex != NULL );\r
333 \r
334         return ( fread( &ch, sizeof( char ), 1, spandex->InputFile() ) == 1 ) ? ch : SCT_END_OF_INPUT;\r
335 }\r
336 \r
337 /* ---------------------------------------------------------------------- */\r
338 /*!\r
339  *\r
340  * \r
341  *\r
342  */\r
343 int siCommonWriteChar( void* aContext, char aCh )\r
344 {\r
345         CSpandexCommon* spandex = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
346 \r
347     SCT_ASSERT( spandex == siCommonGetContext() );\r
348     SCT_ASSERT_ALWAYS( spandex != NULL );\r
349 \r
350     spandex->outputBuffer[ spandex->outputSize++ ] = aCh;\r
351     if( spandex->outputSize >= EOutputBufferSize )\r
352     {\r
353         return siCommonFlushOutput( aContext );\r
354     }\r
355     else\r
356     {\r
357         return 1;\r
358     }\r
359 }\r
360 \r
361 /* ---------------------------------------------------------------------- */\r
362 /*!\r
363  *\r
364  * \r
365  *\r
366  */\r
367 int siCommonFlushOutput( void* aContext )\r
368 {\r
369         CSpandexCommon* spandex = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
370     int             n;\r
371     \r
372     SCT_ASSERT( spandex == siCommonGetContext() );\r
373     SCT_ASSERT_ALWAYS( spandex != NULL );\r
374     SCT_ASSERT_ALWAYS( spandex->OutputFile() != NULL );\r
375 \r
376     if( spandex->outputSize == 0 )\r
377     {\r
378         fflush( spandex->OutputFile() );        \r
379         return 1;\r
380     }\r
381     \r
382     n = fwrite( spandex->outputBuffer, spandex->outputSize, 1, spandex->OutputFile() );\r
383 \r
384     spandex->outputSize = 0;\r
385     fflush( spandex->OutputFile() );\r
386 \r
387     return ( n == 1 );\r
388 }\r
389 \r
390 /* ---------------------------------------------------------------------- */\r
391 /*!\r
392  *\r
393  *\r
394  *\r
395  */\r
396 SCTModuleList* siCommonGetModules( void* /*context*/ )\r
397 {\r
398     SCTModuleList*  modules;\r
399     SCTModule*      module;\r
400 \r
401     modules = sctGetCoreModules();   \r
402     if( modules == NULL )\r
403     {\r
404         return NULL;\r
405     }\r
406 \r
407 #if defined( INCLUDE_SYMBIANBITGDI_MODULE )\r
408     module = sctCreateSymbianBitGDIModule();\r
409     if( module == NULL || sctAddModuleToList( modules, module ) == SCT_FALSE )\r
410     {\r
411         sctDestroyModuleList( modules );\r
412         return NULL;\r
413     }\r
414 #else  /* defined( INCLUDE_SYMBIANBITGDI_MODULE ) */\r
415     SCT_USE_VARIABLE( module );\r
416 #endif  /* defined( INCLUDE_SYMBIANBITGDI_MODULE ) */\r
417 \r
418 #if defined( INCLUDE_SYMBIANSVG_MODULE )\r
419     module = sctCreateSymbianSVGModule();\r
420     if( module == NULL || sctAddModuleToList( modules, module ) == SCT_FALSE )\r
421     {\r
422         sctDestroyModuleList( modules );\r
423         return NULL;\r
424     }\r
425 #endif  /* defined( INCLUDE_SYMBIANSVG_MODULE ) */\r
426     \r
427     return modules;\r
428 }\r
429 \r
430 /* ---------------------------------------------------------------------- */\r
431 /*!\r
432  *\r
433  *\r
434  *\r
435  */\r
436 void siCommonSleep( void* /*context*/, int micros )\r
437 {\r
438     //User::After( micros / 1000 );\r
439     User::AfterHighRes( micros );\r
440 }\r
441 \r
442 /* ---------------------------------------------------------------------- */\r
443 /*!\r
444  *\r
445  *\r
446  *\r
447  */\r
448 void siCommonYield( void* /*context*/ )\r
449 {\r
450     User::ResetInactivityTime();\r
451 }\r
452 \r
453 /* ---------------------------------------------------------------------- */\r
454 /*!\r
455  *\r
456  *\r
457  *\r
458  */\r
459 void siCommonGetTime( void* /*context*/, char* buffer, int length )\r
460 {\r
461     time_t      ltime;\r
462     struct tm*  today;\r
463 \r
464     SCT_ASSERT_ALWAYS( length >= 1 );\r
465 \r
466     time( &ltime );\r
467     today = localtime( &ltime );\r
468     if( strftime( buffer, length, "%Y-%m-%d %H:%M:%S", today ) == 0 )\r
469     {\r
470         buffer[ 0 ] = '\0';\r
471     }\r
472 }\r
473 \r
474 /* ---------------------------------------------------------------------- */\r
475 /*!\r
476  *\r
477  *\r
478  */\r
479 void* siCommonGetSingleton( void* aContext )\r
480 {\r
481     CSpandexCommon* spandex = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
482 \r
483     SCT_ASSERT_ALWAYS( spandex != NULL );\r
484 \r
485     return spandex->GetSingleton();\r
486 }\r
487 \r
488 /* ---------------------------------------------------------------------- */\r
489 /*!\r
490  *\r
491  *\r
492  */\r
493 void siCommonSetSingleton( void* aContext, void* ptr )\r
494 {\r
495     CSpandexCommon* spandex     = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
496 \r
497     SCT_ASSERT_ALWAYS( spandex != NULL );\r
498 \r
499     return spandex->SetSingleton( ptr );\r
500 }\r
501 \r
502 /* ---------------------------------------------------------------------- */\r
503 /*!\r
504  *\r
505  *\r
506  */\r
507 SCTExtensionProc siCommonGetProcAddress( void* context, const char* procname )\r
508 {\r
509     SCT_USE_VARIABLE( context );\r
510 \r
511 #if defined( INCLUDE_EGL_MODULE )\r
512     return ( SCTExtensionProc )( sctEglGetProcAddress( procname ) );\r
513 #else   /* defined( INCLUDE_EGL_MODULE ) */\r
514     SCT_USE_VARIABLE( procname );\r
515     return NULL;\r
516 #endif  /* defined( INCLUDE_EGL_MODULE ) */\r
517 }\r
518 \r
519 /*!\r
520  *\r
521  *\r
522  */\r
523 void* siCommonCreateThread( void* aContext, SCTBenchmarkWorkerThreadFunc aFunc, SCTBenchmarkWorkerThreadContext* aThreadContext )\r
524 {\r
525     CSpandexCommon* spandex     = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
526     RThread*        thread;\r
527     HBufC*          threadName;\r
528     TInt            r;\r
529 \r
530 #if defined( SCT_DEBUG )\r
531     siCommonDebugPrintf( NULL, "SPANDEX: siCommonCreateThread start" );\r
532 #endif  /* defined( SCT_DEBUG ) */\r
533     \r
534     SCT_ASSERT_ALWAYS( spandex != NULL );    \r
535     SCT_ASSERT_ALWAYS( aFunc != NULL );\r
536     SCT_ASSERT_ALWAYS( aThreadContext != NULL );\r
537 \r
538     thread = new RThread;\r
539     if( thread == NULL )\r
540     {\r
541 #if defined( SCT_DEBUG )\r
542         siCommonDebugPrintf( NULL, "SPANDEX: siCommonCreateThread thread allocation failed" );\r
543 #endif  /* defined( SCT_DEBUG ) */       \r
544         return NULL;\r
545     }\r
546 \r
547     threadName = HBufC::New( 64 );\r
548     if( threadName == NULL )\r
549     {\r
550 #if defined( SCT_DEBUG )\r
551         siCommonDebugPrintf( NULL, "SPANDEX: siCommonCreateThread allocation failed" );\r
552 #endif  /* defined( SCT_DEBUG ) */        \r
553         delete thread;\r
554         return NULL;\r
555     }\r
556 \r
557     threadName->Des().Format( _L( "Spandex worker thread %x" ), aThreadContext );\r
558     \r
559     r = thread->Create( *threadName,\r
560                         ( TThreadFunction )( aFunc ),\r
561                         0x14000,\r
562                         &( User::Heap() ),\r
563                         aThreadContext );\r
564 \r
565     delete threadName;\r
566     \r
567     if( r != KErrNone )\r
568     {\r
569 #if defined( SCT_DEBUG )\r
570         siCommonDebugPrintf( NULL, "SPANDEX: siCommonCreateThread create thread failed" );\r
571 #endif  /* defined( SCT_DEBUG ) */\r
572         delete thread;\r
573         return NULL;\r
574     }\r
575 \r
576     thread->Resume();\r
577 \r
578 #if defined( SCT_DEBUG )\r
579     siCommonDebugPrintf( NULL, "SPANDEX: siCommonCreateThread end %x", thread );\r
580 #endif  /* defined( SCT_DEBUG ) */\r
581     \r
582     return thread;\r
583 }\r
584 \r
585 /*!\r
586  *\r
587  */\r
588 void siCommonThreadCleanup( void* aContext )\r
589 {\r
590     SCT_USE_VARIABLE( aContext );\r
591     \r
592     /* Fix symbian. */\r
593     CloseSTDLIB();\r
594 }\r
595 \r
596 /*!\r
597  *\r
598  *\r
599  */\r
600 void siCommonJoinThread( void* aContext, void* aThread )\r
601 {\r
602     CSpandexCommon* spandex = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
603     RThread*        thread;\r
604     TRequestStatus  status;\r
605 \r
606 #if defined( SCT_DEBUG )\r
607     siCommonDebugPrintf( NULL, "SPANDEX: siCommonJoinThread start %x", aThread );\r
608 #endif  /* defined( SCT_DEBUG ) */\r
609     \r
610     SCT_ASSERT_ALWAYS( spandex != NULL );        \r
611     SCT_ASSERT_ALWAYS( aThread != NULL );\r
612 \r
613     thread = ( RThread* )( aThread );\r
614     \r
615     thread->Logon( status );\r
616     User::WaitForRequest( status );\r
617 \r
618     thread->Close();\r
619 \r
620 #if defined( SCT_DEBUG )\r
621     siCommonDebugPrintf( NULL, "SPANDEX: siCommonJoinThread end %x", aThread );\r
622 #endif  /* defined( SCT_DEBUG ) */\r
623     \r
624     delete thread;\r
625 }\r
626 \r
627 /*!\r
628  *\r
629  *\r
630  */\r
631 void* siCommonCreateMutex( void* aContext )\r
632 {\r
633     CSpandexCommon* spandex = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
634     RMutex*         mutex;\r
635     TInt            r;\r
636 \r
637 #if defined( SCT_DEBUG )\r
638     siCommonDebugPrintf( NULL, "SPANDEX: siCommonCreateMutex start" );\r
639 #endif  /* defined( SCT_DEBUG ) */\r
640     \r
641     SCT_ASSERT_ALWAYS( spandex != NULL );        \r
642 \r
643     mutex = new RMutex;\r
644     if( mutex == NULL )\r
645     {\r
646 #if defined( SCT_DEBUG )\r
647         siCommonDebugPrintf( NULL, "SPANDEX: siCommonCreateMutex mutex allocation failed" );\r
648 #endif  /* defined( SCT_DEBUG ) */\r
649         return NULL;\r
650     }\r
651 \r
652     r = mutex->CreateLocal();\r
653     \r
654     if( r != KErrNone )\r
655     {\r
656 #if defined( SCT_DEBUG )\r
657         siCommonDebugPrintf( NULL, "SPANDEX: siCommonCreateMutex mutex creation failed" );\r
658 #endif  /* defined( SCT_DEBUG ) */\r
659         delete mutex;\r
660         return NULL;\r
661     }\r
662 \r
663 #if defined( SCT_DEBUG )\r
664     siCommonDebugPrintf( NULL, "SPANDEX: siCommonCreateMutex end %x", mutex );\r
665 #endif  /* defined( SCT_DEBUG ) */\r
666     \r
667     return mutex;\r
668 }\r
669 \r
670 /*!\r
671  *\r
672  *\r
673  */\r
674 void siCommonLockMutex( void* aContext, void* aMutex )\r
675 {\r
676     CSpandexCommon* spandex = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
677     RMutex*         mutex;\r
678 \r
679 #if defined( SCT_DEBUG )\r
680     siCommonDebugPrintf( NULL, "SPANDEX: siCommonLockMutex start %x", aMutex );\r
681 #endif  /* defined( SCT_DEBUG ) */\r
682     \r
683     SCT_ASSERT_ALWAYS( spandex != NULL );            \r
684     SCT_ASSERT_ALWAYS( aMutex != NULL );\r
685 \r
686     mutex = ( RMutex* )( aMutex );\r
687     \r
688     mutex->Wait();\r
689 \r
690 #if defined( SCT_DEBUG )\r
691     siCommonDebugPrintf( NULL, "SPANDEX: siCommonLockMutex end %x", aMutex );\r
692 #endif  /* defined( SCT_DEBUG ) */   \r
693 }\r
694 \r
695 /*!\r
696  *\r
697  *\r
698  */\r
699 void siCommonUnlockMutex( void* aContext, void* aMutex )\r
700 {\r
701     CSpandexCommon* spandex = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
702     RMutex*         mutex;\r
703 \r
704 #if defined( SCT_DEBUG )\r
705     siCommonDebugPrintf( NULL, "SPANDEX: siCommonUnlockMutex start %x", aMutex );\r
706 #endif  /* defined( SCT_DEBUG ) */\r
707     \r
708     SCT_ASSERT_ALWAYS( spandex != NULL );            \r
709     SCT_ASSERT_ALWAYS( aMutex != NULL );\r
710 \r
711     mutex = ( RMutex* )( aMutex );\r
712     \r
713     mutex->Signal();\r
714 \r
715 #if defined( SCT_DEBUG )\r
716     siCommonDebugPrintf( NULL, "SPANDEX: siCommonUnlockMutex end %x", aMutex );\r
717 #endif  /* defined( SCT_DEBUG ) */\r
718     \r
719 }\r
720         \r
721 /*!\r
722  *\r
723  *\r
724  */\r
725 void siCommonDestroyMutex( void* aContext, void* aMutex )\r
726 {\r
727     CSpandexCommon* spandex = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
728     RMutex*         mutex;\r
729 \r
730 #if defined( SCT_DEBUG )\r
731     siCommonDebugPrintf( NULL, "SPANDEX: siCommonDestroyMutex start %x", aMutex );\r
732 #endif  /* defined( SCT_DEBUG ) */\r
733     \r
734     SCT_ASSERT_ALWAYS( spandex != NULL );            \r
735     SCT_ASSERT_ALWAYS( aMutex != NULL );\r
736 \r
737     mutex = ( RMutex* )( aMutex );\r
738 \r
739     mutex->Close();\r
740     delete mutex;\r
741 \r
742 #if defined( SCT_DEBUG )\r
743     siCommonDebugPrintf( NULL, "SPANDEX: siCommonDestroyMutex end %x", aMutex );\r
744 #endif  /* defined( SCT_DEBUG ) */\r
745 }\r
746 \r
747 /*!\r
748  *\r
749  *\r
750  */ \r
751 struct SCTSymbianSignal\r
752 {\r
753     RMutex*         mutex;\r
754     RSemaphore*     semaphore;\r
755     volatile int    enabled;\r
756     volatile int    waiting;\r
757 };\r
758 \r
759 /*!\r
760  *\r
761  *\r
762  */\r
763 void* siCommonCreateSignal( void* aContext )\r
764 {\r
765     CSpandexCommon*     spandex = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
766     SCTSymbianSignal*   signal;\r
767     TInt                r;\r
768 \r
769 #if defined( SCT_DEBUG )\r
770     siCommonDebugPrintf( NULL, "SPANDEX: siCommonCreateSignal start" );\r
771 #endif  /* defined( SCT_DEBUG ) */\r
772     \r
773     SCT_ASSERT_ALWAYS( spandex != NULL );            \r
774     \r
775     signal = ( SCTSymbianSignal* )( siCommonMemoryAlloc( spandex, sizeof( SCTSymbianSignal ) ) );\r
776     if( signal == NULL )\r
777     {\r
778 #if defined( SCT_DEBUG )\r
779         siCommonDebugPrintf( NULL, "SPANDEX: siCommonCreateSignal signal allocation failed" );\r
780 #endif  /* defined( SCT_DEBUG ) */\r
781         return NULL;\r
782     }\r
783 \r
784     memset( signal, 0, sizeof( SCTSymbianSignal ) );\r
785 \r
786     signal->mutex = ( RMutex* )( siCommonCreateMutex( spandex ) );\r
787     if( signal->mutex == NULL )\r
788     {\r
789 #if defined( SCT_DEBUG )\r
790         siCommonDebugPrintf( NULL, "SPANDEX: siCommonCreateSignal mutex allocation failed" );\r
791 #endif  /* defined( SCT_DEBUG ) */        \r
792         siCommonDestroySignal( spandex, signal );\r
793         return NULL;\r
794     }\r
795 \r
796     signal->semaphore = new RSemaphore;\r
797     if( signal->semaphore == NULL )\r
798     {\r
799 #if defined( SCT_DEBUG )\r
800         siCommonDebugPrintf( NULL, "SPANDEX: siCommonCreateSignal semaphore allocation failed" );\r
801 #endif  /* defined( SCT_DEBUG ) */        \r
802         siCommonDestroySignal( spandex, signal );\r
803         return NULL;\r
804     }\r
805 \r
806     r = signal->semaphore->CreateLocal( 0 );\r
807 \r
808     if( r != KErrNone )\r
809     {\r
810 #if defined( SCT_DEBUG )\r
811         siCommonDebugPrintf( NULL, "SPANDEX: siCommonCreateSignal semaphore creation failed" );\r
812 #endif  /* defined( SCT_DEBUG ) */        \r
813         siCommonDestroySignal( spandex, signal );\r
814         return NULL;\r
815     }\r
816     \r
817     signal->enabled = 1;\r
818 \r
819 #if defined( SCT_DEBUG )\r
820     siCommonDebugPrintf( NULL, "SPANDEX: siCommonCreateSignal end %x", signal );\r
821 #endif  /* defined( SCT_DEBUG ) */\r
822     \r
823     return signal;\r
824 }\r
825 \r
826 /*!\r
827  *\r
828  *\r
829  */\r
830 int siCommonWaitForSignal( void* aContext, void* aSignal, long aTimeoutMillis )\r
831 {\r
832     CSpandexCommon*     spandex = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
833     SCTSymbianSignal*   signal;    \r
834     TInt                r;\r
835     int                 enabled;\r
836 \r
837 #if defined( SCT_DEBUG )\r
838     siCommonDebugPrintf( NULL, "SPANDEX: siCommonWaitForSignal start %x", aSignal );\r
839 #endif  /* defined( SCT_DEBUG ) */\r
840     \r
841     SCT_ASSERT_ALWAYS( spandex != NULL );                \r
842     SCT_ASSERT_ALWAYS( aSignal != NULL );\r
843 \r
844     signal = ( SCTSymbianSignal* )( aSignal );\r
845 \r
846     /* First, lock signal mutex. */    \r
847     signal->mutex->Wait();\r
848     \r
849     /* Check if the signal is enabled. */\r
850     if( signal->enabled == 0 )\r
851     {\r
852 #if defined( SCT_DEBUG )\r
853         siCommonDebugPrintf( NULL, "SPANDEX: siCommonWaitForSignal signal %x disabled", aSignal );\r
854 #endif  /* defined( SCT_DEBUG ) */\r
855         signal->mutex->Signal();        \r
856         return -1;\r
857     }\r
858     signal->waiting++;\r
859     \r
860     signal->mutex->Signal();        \r
861     \r
862     /* Wait for the signal event. */\r
863     if( aTimeoutMillis > 0 )\r
864     {\r
865         r = signal->semaphore->Wait( aTimeoutMillis * 1000 );\r
866     }\r
867     else\r
868     {\r
869         signal->semaphore->Wait();\r
870         r = KErrNone;\r
871     }\r
872 \r
873     /* Lock signal mutex again. */\r
874     signal->mutex->Wait();\r
875     \r
876     /* Got signal event, get enabled. */\r
877     enabled = signal->enabled;\r
878     signal->waiting--;\r
879     \r
880     /* Release signal mutex and return wait status. */\r
881     signal->mutex->Signal();   \r
882 \r
883     /* Signal was disabled, or semaphore is about to be destroyed. */\r
884     if( enabled == 0 || r == KErrGeneral )\r
885     {\r
886 #if defined( SCT_DEBUG )\r
887         siCommonDebugPrintf( NULL, "SPANDEX: siCommonWaitForSignal signal %x wait failed", aSignal );\r
888 #endif  /* defined( SCT_DEBUG ) */\r
889         return -1;\r
890     }\r
891 \r
892     /* Wait was ok. */\r
893     if( r == KErrNone )\r
894     {\r
895 #if defined( SCT_DEBUG )\r
896         siCommonDebugPrintf( NULL, "SPANDEX: siCommonWaitForSignal signal %x wait ok", aSignal );\r
897 #endif  /* defined( SCT_DEBUG ) */        \r
898         return 1;\r
899     }\r
900 \r
901 #if defined( SCT_DEBUG )\r
902     siCommonDebugPrintf( NULL, "SPANDEX: siCommonWaitForSignal signal %x wait timeout", aSignal );\r
903 #endif  /* defined( SCT_DEBUG ) */   \r
904     \r
905     /* Timeout must have happened. */\r
906     return 0;\r
907 }\r
908 \r
909 /*!\r
910  *\r
911  *\r
912  */\r
913 void siCommonDisableSignal( void* aContext, void* aSignal )\r
914 {\r
915     CSpandexCommon*     spandex = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
916     SCTSymbianSignal*   signal;\r
917 \r
918 #if defined( SCT_DEBUG )\r
919     siCommonDebugPrintf( NULL, "SPANDEX: siCommonDisableSignal start %x", aSignal );\r
920 #endif  /* defined( SCT_DEBUG ) */\r
921 \r
922     SCT_ASSERT_ALWAYS( spandex != NULL );                \r
923     SCT_ASSERT_ALWAYS( aSignal != NULL );\r
924 \r
925     signal = ( SCTSymbianSignal* )( aSignal );\r
926 \r
927     /* Lock signal mutex */\r
928     signal->mutex->Wait();\r
929 \r
930     /* Set signal as disabled. */\r
931     signal->enabled = 0;\r
932 \r
933     /* Wake up all threads waiting for the signal event. Also set the event\r
934      * for threads just about to start the wait. */\r
935     if( signal->waiting > 0 )\r
936     {\r
937         signal->semaphore->Signal( signal->waiting );\r
938     }\r
939     \r
940     /* Release signal mutex. */\r
941     signal->mutex->Signal();\r
942 \r
943 #if defined( SCT_DEBUG )\r
944     siCommonDebugPrintf( NULL, "SPANDEX: siCommonDisableSignal end %x", aSignal );\r
945 #endif  /* defined( SCT_DEBUG ) */    \r
946\r
947 \r
948 /*!\r
949  *\r
950  *\r
951  */\r
952 void siCommonEnableSignal( void* aContext, void* aSignal )\r
953 {\r
954     CSpandexCommon*     spandex = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
955     SCTSymbianSignal*   signal;\r
956 \r
957 #if defined( SCT_DEBUG )\r
958     siCommonDebugPrintf( NULL, "SPANDEX: siCommonEnableSignal start %x", aSignal );\r
959 #endif  /* defined( SCT_DEBUG ) */\r
960     \r
961     SCT_ASSERT_ALWAYS( spandex != NULL );                \r
962     SCT_ASSERT_ALWAYS( aSignal != NULL );\r
963 \r
964     signal = ( SCTSymbianSignal* )( aSignal );\r
965     \r
966     /* Lock signal mutex */\r
967     signal->mutex->Wait();\r
968 \r
969     SCT_ASSERT_ALWAYS( signal->waiting == 0 );\r
970     \r
971     /* Enable signal, and reset the event. */\r
972     signal->enabled = 1;\r
973     \r
974     /* Release signal mutex. */\r
975     signal->mutex->Signal();\r
976 \r
977 #if defined( SCT_DEBUG )\r
978     siCommonDebugPrintf( NULL, "SPANDEX: siCommonEnableSignal end %x", aSignal );\r
979 #endif  /* defined( SCT_DEBUG ) */    \r
980\r
981 \r
982 /*!\r
983  *\r
984  *\r
985  */\r
986 void siCommonTriggerSignal( void* aContext, void* aSignal )\r
987 {\r
988     CSpandexCommon*     spandex = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
989     SCTSymbianSignal*   signal;\r
990 \r
991 #if defined( SCT_DEBUG )\r
992     siCommonDebugPrintf( NULL, "SPANDEX: siCommonTriggerSignal start %x", aSignal );\r
993 #endif  /* defined( SCT_DEBUG ) */\r
994     \r
995     SCT_ASSERT_ALWAYS( spandex != NULL );                \r
996     SCT_ASSERT_ALWAYS( aSignal != NULL );\r
997 \r
998     signal = ( SCTSymbianSignal* )( aSignal );\r
999 \r
1000     /* Lock signal mutex */\r
1001     signal->mutex->Wait();\r
1002     \r
1003     if( signal->enabled != 0 )\r
1004     {\r
1005         signal->semaphore->Signal();\r
1006     }\r
1007 \r
1008     /* Release signal mutex. */\r
1009     signal->mutex->Signal();\r
1010 \r
1011 #if defined( SCT_DEBUG )\r
1012     siCommonDebugPrintf( NULL, "SPANDEX: siCommonTriggerSignal end %x", aSignal );\r
1013 #endif  /* defined( SCT_DEBUG ) */    \r
1014 }\r
1015 \r
1016 /*!\r
1017  *\r
1018  *\r
1019  */\r
1020 void siCommonDestroySignal( void* aContext, void* aSignal )\r
1021 {\r
1022     CSpandexCommon*     spandex = ( CSpandexCommon* )( aContext ? aContext : siCommonGetContext() );\r
1023     SCTSymbianSignal*   signal;\r
1024 \r
1025 #if defined( SCT_DEBUG )\r
1026     siCommonDebugPrintf( NULL, "SPANDEX: siCommonDestroySignal start %x", aSignal );\r
1027 #endif  /* defined( SCT_DEBUG ) */\r
1028     \r
1029     SCT_ASSERT_ALWAYS( spandex != NULL );                \r
1030     SCT_ASSERT_ALWAYS( aSignal != NULL );\r
1031 \r
1032     signal = ( SCTSymbianSignal* )( aSignal );\r
1033     \r
1034     if( signal->semaphore != NULL )\r
1035     {\r
1036         signal->semaphore->Close();\r
1037         delete signal->semaphore;\r
1038         signal->semaphore = NULL;\r
1039     }\r
1040 \r
1041     if( signal->mutex != NULL )\r
1042     {\r
1043         signal->mutex->Close();\r
1044         delete signal->mutex;\r
1045         signal->mutex = NULL;\r
1046     }\r
1047 \r
1048     siCommonMemoryFree( NULL, signal );\r
1049 \r
1050 #if defined( SCT_DEBUG )\r
1051     siCommonDebugPrintf( NULL, "SPANDEX: siCommonDestroySignal end %x", aSignal );\r
1052 #endif  /* defined( SCT_DEBUG ) */    \r
1053 }\r