xref: /utopia/UTPA2-700.0.x/modules/hsl/api/hsl/frhsl_ringbuffer.c (revision 53ee8cc121a030b8d368113ac3e966b4705770ef)
1 //<MStar Software>
2 //******************************************************************************
3 // MStar Software
4 // Copyright (c) 2010 - 2012 MStar Semiconductor, Inc. All rights reserved.
5 // All software, firmware and related documentation herein ("MStar Software") are
6 // intellectual property of MStar Semiconductor, Inc. ("MStar") and protected by
7 // law, including, but not limited to, copyright law and international treaties.
8 // Any use, modification, reproduction, retransmission, or republication of all
9 // or part of MStar Software is expressly prohibited, unless prior written
10 // permission has been granted by MStar.
11 //
12 // By accessing, browsing and/or using MStar Software, you acknowledge that you
13 // have read, understood, and agree, to be bound by below terms ("Terms") and to
14 // comply with all applicable laws and regulations:
15 //
16 // 1. MStar shall retain any and all right, ownership and interest to MStar
17 //    Software and any modification/derivatives thereof.
18 //    No right, ownership, or interest to MStar Software and any
19 //    modification/derivatives thereof is transferred to you under Terms.
20 //
21 // 2. You understand that MStar Software might include, incorporate or be
22 //    supplied together with third party`s software and the use of MStar
23 //    Software may require additional licenses from third parties.
24 //    Therefore, you hereby agree it is your sole responsibility to separately
25 //    obtain any and all third party right and license necessary for your use of
26 //    such third party`s software.
27 //
28 // 3. MStar Software and any modification/derivatives thereof shall be deemed as
29 //    MStar`s confidential information and you agree to keep MStar`s
30 //    confidential information in strictest confidence and not disclose to any
31 //    third party.
32 //
33 // 4. MStar Software is provided on an "AS IS" basis without warranties of any
34 //    kind. Any warranties are hereby expressly disclaimed by MStar, including
35 //    without limitation, any warranties of merchantability, non-infringement of
36 //    intellectual property rights, fitness for a particular purpose, error free
37 //    and in conformity with any international standard.  You agree to waive any
38 //    claim against MStar for any loss, damage, cost or expense that you may
39 //    incur related to your use of MStar Software.
40 //    In no event shall MStar be liable for any direct, indirect, incidental or
41 //    consequential damages, including without limitation, lost of profit or
42 //    revenues, lost or damage of data, and unauthorized system use.
43 //    You agree that this Section 4 shall still apply without being affected
44 //    even if MStar Software has been modified by MStar in accordance with your
45 //    request or instruction for your use, except otherwise agreed by both
46 //    parties in writing.
47 //
48 // 5. If requested, MStar may from time to time provide technical supports or
49 //    services in relation with MStar Software to you for your use of
50 //    MStar Software in conjunction with your or your customer`s product
51 //    ("Services").
52 //    You understand and agree that, except otherwise agreed by both parties in
53 //    writing, Services are provided on an "AS IS" basis and the warranty
54 //    disclaimer set forth in Section 4 above shall apply.
55 //
56 // 6. Nothing contained herein shall be construed as by implication, estoppels
57 //    or otherwise:
58 //    (a) conferring any license or right to use MStar name, trademark, service
59 //        mark, symbol or any other identification;
60 //    (b) obligating MStar or any of its affiliates to furnish any person,
61 //        including without limitation, you and your customers, any assistance
62 //        of any kind whatsoever, or any information; or
63 //    (c) conferring any license or right under any intellectual property right.
64 //
65 // 7. These terms shall be governed by and construed in accordance with the laws
66 //    of Taiwan, R.O.C., excluding its conflict of law rules.
67 //    Any and all dispute arising out hereof or related hereto shall be finally
68 //    settled by arbitration referred to the Chinese Arbitration Association,
69 //    Taipei in accordance with the ROC Arbitration Law and the Arbitration
70 //    Rules of the Association by three (3) arbitrators appointed in accordance
71 //    with the said Rules.
72 //    The place of arbitration shall be in Taipei, Taiwan and the language shall
73 //    be English.
74 //    The arbitration award shall be final and binding to both parties.
75 //
76 //******************************************************************************
77 //<MStar Software>
78 /*******************************************************************************
79     Shared library to log data to a circular buffer and output the data to
80     multiple devices.
81  *******************************************************************************/
82 #if defined (MSOS_TYPE_LINUX)
83 #include <stdio.h>
84 
85 #include <pthread.h>
86 
87 #include <errno.h>
88 #include <assert.h>
89 #include <sys/time.h>
90 #include <sys/types.h>
91 #include <sys/syscall.h>
92 
93 #include "frhsl_datalink.h"
94 #include "frhsl_ringbuffer.h"
95 #include "frhsl_cfg.h"
96 #include "apiHSL.h"
97 #include "frhsl_RAWLOB.h"
98 #include "MsCommon.h"
99 #include "drvWDT.h"
100 
101 // large part of the data are bookmarks (8 * BUFFER_SEGMENTS_COUNT)
102 #define SYS_STATE_BUFSIZE (1024)
103 
104 
105 #define DUMP_LP_LEN 41
106 static MS_U8 s_DumpBufferLP[] =         {0x17,
107         0x13, 0x0F, 0x09, 0x00, 0x00,
108         0x13, 0x0F, 0x09, 0x00, 0x00,
109         0x13, 0x0F, 0x09, 0x00, 0x00,
110         0x13, 0x0F, 0x09, 0x00, 0x00,
111         0x13, 0x0F, 0x09, 0x00, 0x00,
112         0x12, 0x03, 0xFF, 0x00, 0x00, 0x11, 0x02, 0x00, 0x11, 0x3B, 0xD0, 0x10, 0x00, 0x00, 0x17};
113 static MS_U8 s_CriticalDumpBufferLP[] = {0x17,
114         0x13, 0x0F, 0x09, 0x00, 0x00,
115         0x13, 0x0F, 0x09, 0x00, 0x00,
116         0x13, 0x0F, 0x09, 0x00, 0x00,
117         0x13, 0x0F, 0x09, 0x00, 0x00,
118         0x13, 0x0F, 0x09, 0x00, 0x00,
119         0x12, 0x03, 0xFF, 0x00, 0x00, 0x11, 0x02, 0x00, 0x11, 0x59, 0x86, 0x10, 0x00, 0x00, 0x17};
120 
121 ST_LIBRARY_SHORT_INFO gDynamicLibraryInfo[HSL_MAX_LIBRARY_COUNT];
122 MS_U16 gDynamicLibraryCount = 0;
123 ST_THREAD_INFO gThreadInfo[HSL_MAX_THREAD_COUNT];
124 MS_U16 gThreadCount = 0;
125 
126 pthread_t gTestThreads[MAX_SELFTEST_THREAD_CNT];
127 MS_BOOL gRunLoadTest = true;
128 
HslSelfTestThreadFun(void * pArg)129 void *HslSelfTestThreadFun(void* pArg)
130 {
131     struct timeval timeStart, timeNow;
132     int i = 0;
133     ST_HSL_SELFTEST_CMD command;
134     ST_HSL_SELFTEST_CMD* pCommand = &command;
135     memcpy(pCommand, pArg, sizeof(ST_HSL_SELFTEST_CMD));
136 
137     gettimeofday(&timeStart, 0);
138     timeNow = timeStart;
139 
140     while( gRunLoadTest &&
141             ((timeNow.tv_sec-timeStart.tv_sec)*1000000 + (timeNow.tv_usec-timeStart.tv_usec) < (pCommand->mRunTime*1000000)) )
142     {
143         for(i=0; i < pCommand->mCntSimpleLP; i++)
144         {
145             M_FrHslPrintf0 (0x4890, HSL_DBG_SN_ALL_DEBUG, "HSL SelfTest printf 0 arg:");
146         }
147         for(i=0; i < pCommand->mCntPrintf1p; i++)
148         {
149             M_FrHslPrintf1 (0x37D05, HSL_DBG_SN_ALL_DEBUG, "HSL SelfTest printf 1 arg: %X", 0xFF);
150         }
151         for(i=0; i < pCommand->mCntArray16; i++)
152         {
153             MS_U16 sndArray[pCommand->mParamArray16Size];
154             memset(sndArray, 0x16, sizeof(sndArray));
155             M_FrHslArray16 (0xAD99, HSL_DBG_SN_ALL_DEBUG, "HSL SelfTest array16: %X", pCommand->mParamArray16Size, sndArray);
156         }
157         for(i=0; i< pCommand->mCntArray32; i++)
158         {
159             MS_U32 sndArray[pCommand->mParamArray32Size];
160             memset(sndArray, 0x32, sizeof(sndArray));
161             M_FrHslArray32 (0xAB54, HSL_DBG_SN_ALL_DEBUG, "HSL SelfTest array32: %X", pCommand->mParamArray32Size, sndArray, 0);
162         }
163         for(i=0; i < pCommand->mCntTypedef; i++)
164         {
165             ST_TEST_STRUCT testStruct;
166             testStruct.a = 0x1234;
167             testStruct.b = 0x5678;
168             testStruct.c = 0xABCD;
169             M_FrHslTypedef (0xA4A4,  HSL_DBG_SN_ALL_DEBUG, "HSL SelfTest typedef: %d", ST_TEST_STRUCT, &testStruct );
170         }
171         usleep(pCommand->mThreadDelay*1000); // convert the parameter from usec into msec
172         gettimeofday(&timeNow, 0);
173     }
174     return 0;
175 }
176 
177 const MS_U8 syncBuf[] = {HSL_RAWLOB_SYNC_MARKER};
178 
GetSystemTime(void)179 MS_U32 GetSystemTime(void)
180 {
181 	return MDrv_TIMER_GetCounter (E_TIMER_1);
182 }
183 
184 // PENDING WRITE LINKED LIST OPERATIONS
185 
186 /* Should only be called from the listAppendValue */
listFindNextFreeNode(stHslController * _hsl)187 stListNode* listFindNextFreeNode( stHslController *_hsl )
188 {
189     stListNode *retVal = 0;
190     if( _hsl != 0)
191     {
192         int i = 0;
193         if( _hsl->pendingWriteHead == 0 )
194         {
195             retVal = &(_hsl->pendingWriteList[0]);
196         }
197         else
198         {
199             for( i=0; (i<PENDING_WRITE_LIST_LEN) && (_hsl->pendingWriteList[i].u32bufferIndex || _hsl->pendingWriteList[i].u32timestamp); i++ ){};
200             retVal = &(_hsl->pendingWriteList[i]);
201         }
202     }
203     return retVal;
204 }
205 
listAppendValue(stHslController * _hsl,MS_U32 newValue)206 stListNode* listAppendValue(stHslController *_hsl, MS_U32 newValue)
207 {
208     stListNode *currentNode = 0;
209     stListNode *lastNode = 0;
210     if(_hsl!=0)
211     {
212         pthread_mutex_lock( &(_hsl->pendingWriteMutex) );
213         //assert(_hsl->pendingWriteLength < PENDING_WRITE_LIST_LEN );
214         currentNode = listFindNextFreeNode(_hsl);
215         assert( currentNode != 0 );
216         currentNode->u32bufferIndex = newValue;
217         if(_hsl->pendingWriteHead == 0 )
218         {
219             _hsl->pendingWriteHead = currentNode;
220             currentNode->prev = 0;
221         }
222         else
223         {
224         // find the tail
225             lastNode = _hsl->pendingWriteHead;
226             while(lastNode->next)
227             {
228                 lastNode = lastNode->next;
229             }
230             lastNode->next = currentNode;
231             currentNode->prev = lastNode;
232         }
233         currentNode->next = 0;
234         _hsl->pendingWriteLength++;
235         pthread_mutex_unlock( &(_hsl->pendingWriteMutex) );
236     }
237     return currentNode;
238 }
239 
listRemoveNode(stHslController * _hsl,stListNode * node)240 void listRemoveNode(stHslController *_hsl, stListNode *node)
241 {
242     if(_hsl!=0)
243     {
244         pthread_mutex_lock( &(_hsl->pendingWriteMutex) );
245         //assert( _hsl->pendingWriteHead != 0 );
246 
247         if(node == _hsl->pendingWriteHead)
248         {
249             _hsl->pendingWriteHead = node->next;
250         }
251 
252         if(node->prev)
253         {
254         	node->prev->next = node->next;
255         }
256         if(node->next)
257         {
258         	node->next->prev = node->prev;
259         }
260         node->u32bufferIndex = 0;
261         node->u32timestamp = 0;
262         node->prev = 0;
263         node->next = 0;
264         _hsl->pendingWriteLength--;
265         pthread_mutex_unlock( &(_hsl->pendingWriteMutex) );
266     }
267 }
268 
listGetFirstValue(stHslController * _hsl)269 MS_U32 listGetFirstValue( stHslController *_hsl )
270 {
271     MS_U32 retVal = 0;
272     if(_hsl!=0)
273     {
274         retVal = 0;
275         pthread_mutex_lock( &(_hsl->pendingWriteMutex) );
276         if( _hsl->pendingWriteHead == 0 )
277         {
278             retVal = 0;
279         }
280         else
281         {
282             retVal = _hsl->pendingWriteHead->u32bufferIndex;
283         }
284         pthread_mutex_unlock( &(_hsl->pendingWriteMutex) );
285     }
286     return retVal;
287 }
288 
listIsEmpty(stHslController * _hsl)289 MS_BOOL listIsEmpty(stHslController *_hsl)
290 {
291     MS_BOOL retVal = true;
292     if(_hsl!=0)
293     {
294     pthread_mutex_lock( &(_hsl->pendingWriteMutex) );
295     retVal = (_hsl->pendingWriteHead == 0);
296     pthread_mutex_unlock( &(_hsl->pendingWriteMutex) );
297     }
298     return retVal;
299 }
300 
301 ////////////////////////////////////////////////////////////////////////////////
302 //    GENERAL MESSAGE PROCESSING FUNCTIONS
303 ////////////////////////////////////////////////////////////////////////////////
304 
305 /*******************************************************************************
306     Function:
307         sendBytesToStream
308     Description:
309         Output bytes of data from a message in the buffer, only the bytes less than outputLen will be output
310     INPUT:
311         MS_U8*: output buffer
312         MS_U32: total bytes need to output
313     OUTPUT:
314         Data to a device - currently UART.
315     RETURNS:
316         MS_BOOL: the whole bytes in message was written out or not
317  *******************************************************************************/
bufferSendBytes(p_HslController _hsl,const MS_U8 * const pu8MessageBuffer,const MS_U32 u32totalBytes)318 MS_BOOL bufferSendBytes(p_HslController _hsl, const MS_U8* const pu8MessageBuffer, const MS_U32 u32totalBytes)
319 {
320     PUTCS(pu8MessageBuffer, u32totalBytes, FR_HSL_FILE_DESCRIPTOR, _hsl);
321     return FALSE;
322 }
323 
324 /*******************************************************************************
325     Function:
326             bufferWriteThread
327     Description:
328             output Data to UART
329  *******************************************************************************/
bufferWriteThread(void * data)330 void* bufferWriteThread(void* data)
331 {
332     //TODO!: Write a new simplified ring buffer output procedure
333     struct timeval now;
334     struct timespec timeout;
335     MS_U32 txSize;
336     MS_U32 txPos;
337     MS_U8  txBuffer[TX_BUFFER_SIZE];
338     MS_U32 txBufPos;
339     MS_U32 dumpReadPos;
340     MS_U32 dumpInfoPos=0;
341     MS_U8* dumpInfoBuf=NULL;
342     MS_BOOL resetBufEnd = FALSE;
343 
344     p_HslController _hsl = (p_HslController)data;
345 
346     pthread_mutex_lock(&(_hsl->outputCondMutex));
347     while( !(_hsl->thread_finalize) )
348     {
349 
350         gettimeofday(&now, 0);
351         timeout.tv_sec = now.tv_sec + 1;
352         timeout.tv_nsec = now.tv_usec;
353 
354         /* Checks to the pthread_cond_timedwait return immediately with an exception of the ETIMEDOUT
355          * Any other check will lose the blocking behaviour and will result in a tight loop executing
356          * the default case (add timerwraps) with high frequency and consuming lots of system's resources.
357          * Please see 'man pthread_cond_timedwait' for details.
358          */
359 
360         if( (_hsl->pSystemState->bufFlags != BUFFER_FLAG_NONE) ||
361                 (ETIMEDOUT != pthread_cond_timedwait( &(_hsl->outputCond), &(_hsl->outputCondMutex), &timeout )) )
362         {
363             if( _hsl->pSystemState->bufFlags & BUFFER_FLAG_EMERGENCY_DUMP )
364             {
365                 pthread_cond_wait(&(_hsl->outputCond), &(_hsl->outputCondMutex));
366             }
367 
368             if( _hsl->pSystemState->bufFlags & BUFFER_FLAG_TX )
369             {
370                /* Additional info about the usage of bufReadPos below:   what coverity misses is that:
371                 -   Every write access to this variable is protected by holding both of the: bufferMutex and outputCondMutex
372                 -   Every read is protected by holding at least one of them.
373                 This provides enough locking to ensure that the value is always consistent between threads yet provides enough
374                 freedom for multiple threads to operate concurrently if they only require reading. */
375                 txPos = _hsl->pSystemState->bufReadPos;
376                 if(_hsl->pSystemState->dumpFlag != BUFFER_FLAG_NONE)
377                 {
378                     switch(_hsl->pSystemState->dumpFlag)
379                     {
380                     case BUFFER_FLAG_DUMP:
381                         dumpInfoPos = DUMP_LP_LEN;
382                         dumpInfoBuf = s_DumpBufferLP;
383                         break;
384                     case BUFFER_FLAG_EMERGENCY_DUMP:
385                         dumpInfoPos = DUMP_LP_LEN;
386                         dumpInfoBuf = s_CriticalDumpBufferLP;
387                         break;
388                     default:
389                         dumpInfoPos = 0;
390                         dumpInfoBuf = NULL;
391                         break;
392                     }
393                 }
394                 while( _hsl->pSystemState->bufBytesToSend > 0 )
395                 {
396                     txBufPos = 0;
397                     while((txBufPos < TX_BUFFER_SIZE-1) && (_hsl->pSystemState->bufBytesToSend > 0))
398                     {
399                         // is it time to send a sync marker?
400                         if( _hsl->pSystemState->syncMarker == 0 )
401                         {
402                             txBuffer[txBufPos] = HSL_RAWLOB_SYNC_MARKER;
403                             txBufPos++;
404                             --(_hsl->pSystemState->bufBytesToSend);
405                             _hsl->pSystemState->syncMarker = HSL_RAWLOB_SYNC_MARKER_INTERVAL;
406                         }
407 
408                         // does the remaining data fill the space to the nearest sync marker?
409                         if( _hsl->pSystemState->bufBytesToSend >= _hsl->pSystemState->syncMarker )
410                         {
411                             txSize = _hsl->pSystemState->syncMarker;
412                         }
413                         else
414                         {
415                             txSize = _hsl->pSystemState->bufBytesToSend;
416                         }
417 
418 
419                         if(txSize > 0)
420                         {
421                             // need to inject a data dump information logpoint?
422                             if(dumpInfoPos > 0)
423                             {
424                                 if(txSize > dumpInfoPos)
425                                 {
426                                     txSize = dumpInfoPos;
427                                 }
428 
429                                 dumpReadPos = DUMP_LP_LEN-dumpInfoPos;
430 
431                                 if( dumpReadPos + txSize <= DUMP_LP_LEN )
432                                 {
433                                     memcpy(txBuffer+txBufPos, dumpInfoBuf+dumpReadPos, txSize);
434                                 }
435 
436                                 dumpInfoPos -= txSize;
437 
438                             }
439                             else
440                             {
441                                 if( (txPos + txSize) >= _hsl->pSystemState->bufUsedEnd )
442                                 {
443                                     txSize = _hsl->pSystemState->bufUsedEnd - txPos;
444                                 }
445 
446                                 if( txBufPos + txSize >= TX_BUFFER_SIZE )
447                                 {
448                                     txSize = TX_BUFFER_SIZE - txBufPos;
449                                 }
450 
451                                 // data TX
452                                 memcpy(txBuffer+txBufPos, (MS_U8*)txPos, txSize);
453 
454                                 txPos += txSize;
455                                 /* IMPORTANT !!!
456                                  * The txPos (and effectively the bufReadPos) can only wrap around if the bufReadLimit has
457                                  * wrapped around previously. This is to avoid a corner case when the read limit sits right at the end
458                                  * of the buffer and after catching up with it, the read pos is updated to the beginning of the buffer
459                                  * resulting in the complete OLD buffer contents to be sent again.
460                                  */
461                                 if( (txPos >= _hsl->pSystemState->bufUsedEnd) && (_hsl->pSystemState->bufReadLimit < _hsl->pSystemState->bufReadPos) )
462                                 {
463                                     // mark the buffer's end for restoration once we've read past the previous virtual one
464                                     resetBufEnd = TRUE;
465                                     txPos = _hsl->pSystemState->bufStart;
466                                 }
467                             }
468                             // update tx markers
469                             _hsl->pSystemState->syncMarker = (_hsl->pSystemState->syncMarker - txSize);
470                             _hsl->pSystemState->bufBytesToSend -= txSize;
471                             txBufPos += txSize;
472                         }
473                     }
474                     bufferSendBytes(_hsl, txBuffer, txBufPos);
475                 }
476 
477                 // data successfully sent, update read position.
478                 pthread_mutex_lock(&(_hsl->bufferMutex));
479                 _hsl->pSystemState->bufReadPos = txPos;
480                 _hsl->pSystemState->bufFlags &= ~BUFFER_FLAG_TX;
481                 _hsl->pSystemState->dumpFlag = BUFFER_FLAG_NONE;
482                 if( resetBufEnd )
483                 {
484                     _hsl->pSystemState->bufUsedEnd = _hsl->pSystemState->bufEnd;
485                     resetBufEnd = FALSE;
486                 }
487                 pthread_mutex_unlock(&(_hsl->bufferMutex));
488             }
489             if( _hsl->pSystemState->bufFlags & BUFFER_FLAG_DUMP )
490             {
491                 // dump data
492                 pthread_mutex_lock(&(_hsl->bufferMutex));
493                 _hsl->pSystemState->dumpFlag = BUFFER_FLAG_DUMP;
494                 bufferDumpOldestDataSegment(_hsl);
495                 _hsl->pSystemState->bufFlags &= ~BUFFER_FLAG_DUMP;
496                 pthread_mutex_unlock(&(_hsl->bufferMutex));
497             }
498         }
499         else
500         {
501             // no data to be allocated but it will add some timer wraps
502             pthread_mutex_unlock(&(_hsl->outputCondMutex));
503             if( bufferAllocateWrite(_hsl, 0,0) )
504             {
505                 // coverity thinks that the return value should be checked....
506                 continue;
507             }
508             pthread_mutex_lock(&(_hsl->outputCondMutex));
509         }
510     }
511     pthread_mutex_unlock(&(_hsl->outputCondMutex));
512     return NULL;
513 }
514 
515 
516 ////////////////////////////////////////////////////////////////////////////////
517 //    THREAD FUNCTIONS
518 ////////////////////////////////////////////////////////////////////////////////
519 
520 /*******************************************************************************
521     Function:
522     Description:
523     INPUT:
524     OUTPUT:
525  *******************************************************************************/
deleteThread(hslThread aThread)526 MS_BOOL deleteThread(hslThread aThread)
527 {
528     MS_U32 rc=false;
529 
530     if (0 == pthread_detach(aThread.threadId))
531     {
532         rc = true;
533     }
534 
535     return rc;
536 }
537 
538 /*******************************************************************************
539     Function:
540     Description:
541     INPUT:
542     OUTPUT:
543  *******************************************************************************/
initThread(hslThread * aThread)544 MS_BOOL initThread(hslThread* aThread)
545 {
546     MS_BOOL rc = false;
547 
548     if (0 == pthread_create( &(aThread->threadId), NULL, aThread->funcPtr, aThread->funcParam))
549     {
550         rc = true;
551     }
552 
553     return rc;
554 }
555 
556 ////////////////////////////////////////////////////////////////////////////////
557 //    MUTEX FUNCTIONS
558 ////////////////////////////////////////////////////////////////////////////////
559 
560 /*******************************************************************************
561     Function:
562         initMutex
563     Description:
564     INPUT:
565     OUTPUT:
566  *******************************************************************************/
initMutex(pthread_mutex_t * pMutex)567 MS_BOOL initMutex(pthread_mutex_t* pMutex)
568 {
569     MS_BOOL rc = false;
570 
571     if (0 == pthread_mutex_init(pMutex, NULL))
572     {
573         rc = true;
574     }
575 
576     return rc;
577 }
578 
579 /*******************************************************************************
580     Function:
581     Description:
582     INPUT:
583     OUTPUT:
584  *******************************************************************************/
deleteMutex(pthread_mutex_t * pMutex)585 MS_BOOL deleteMutex(pthread_mutex_t* pMutex)
586 {
587     MS_BOOL rc = false;
588 
589     if (0 == pthread_mutex_destroy(pMutex))
590     {
591         rc = true;
592     }
593 
594     return rc;
595 }
596 
597 ////////////////////////////////////////////////////////////////////////////////
598 //    CONDITION FUNCTIONS
599 ////////////////////////////////////////////////////////////////////////////////
600 
601 /*******************************************************************************
602     Function:
603         initCondition
604     Description:
605         Initilises a condition variable.
606     INPUT:
607         pCond - pointer to a condition varaible.
608     OUTPUT:
609         None.
610     RETURNS:
611         rc - indicates success or failure of initialisation
612  *******************************************************************************/
initCondition(pthread_cond_t * pCond)613 MS_BOOL initCondition(pthread_cond_t* pCond)
614 {
615     MS_BOOL rc = false;
616 
617     if (0 == pthread_cond_init(pCond, NULL))
618     {
619         rc = true;
620     }
621 
622     return rc;
623 }
624 
625 /*******************************************************************************
626     Function:
627         deleteCondition
628     Description:
629         Deletes a condition variable.
630     INPUT:
631         pCond - pointer to a condition varaible.
632     OUTPUT:
633         None.
634     RETURNS:
635         rc - indicates success or failure of initialisation
636  *******************************************************************************/
deleteCondition(pthread_cond_t * pCond)637 MS_BOOL deleteCondition(pthread_cond_t* pCond)
638 {
639     MS_BOOL rc = false;
640 
641     if (0 == pthread_cond_destroy(pCond))
642     {
643         rc = true;
644     }
645 
646     return rc;
647 }
648 
649 ////////////////////////////////////////////////////////////////////////////////
650 //    INIT FUNCTIONS
651 ////////////////////////////////////////////////////////////////////////////////
652 
653 /*******************************************************************************
654     Function:
655         initBuffer
656     Description:
657         Initialises the data structure for the ring buffer and partitions the
658         memory to contain the system state and the ring buffer data.
659     INPUT:
660         size - size of the memory available.
661         physAddr - starting address of the memory in RAM (needs to be remapped for
662         this process).
663     OUTPUT:
664         None.
665  *******************************************************************************/
initBufferMemory(stHslController * const _hsl,const MS_U32 size,const MS_PHYADDR physAddr)666 MS_BOOL initBufferMemory(stHslController* const _hsl, const MS_U32 size, const MS_PHYADDR physAddr)
667 {
668     MS_U32 virtualAddress;
669     int i;
670     if ( size != 0 )
671     {
672         pthread_mutex_lock(&(_hsl->outputCondMutex));
673         pthread_mutex_lock(&(_hsl->bufferMutex));
674 
675         if(physAddr != 0)
676         {
677             // save intial params. and buffer ptrs and sizes to system state structure
678             // required to store system state in ringbuffer so need to allocate 2K.
679             // from buffer of 512K.
680 
681             // convert physical address to one mapped into process memory space.
682             virtualAddress = MsOS_MPool_PA2VA(physAddr);
683         }
684         else
685         {
686             virtualAddress = (MS_U32)malloc(size);
687             assert(virtualAddress!=0);
688         }
689 
690         // initialise memory
691         memset( (MS_U8*)virtualAddress, 0, size);
692 
693         // locate system state structure at beginning of allocated memory
694         _hsl->pSystemState = (stSystemState*)(virtualAddress);
695 
696         if( physAddr != 0 )
697         {
698             _hsl->pSystemState->dynamicAlloc = 0;
699         }
700         else
701         {
702             _hsl->pSystemState->dynamicAlloc = 1;
703         }
704         // store pre-determined system state buffer size
705         _hsl->pSystemState->ssize = SYS_STATE_BUFSIZE;
706 
707         // initialise rest of system state structure
708         _hsl->pSystemState->sbufStart = virtualAddress;
709         _hsl->pSystemState->sbufEnd = virtualAddress + SYS_STATE_BUFSIZE - 1;
710 
711         // initialise the ringbuffer pointers
712         _hsl->pSystemState->bufSize = size - SYS_STATE_BUFSIZE;
713         _hsl->pSystemState->bufStart = virtualAddress + SYS_STATE_BUFSIZE;
714         _hsl->pSystemState->bufEnd = virtualAddress + size - 1;
715         _hsl->pSystemState->bufUsedEnd = _hsl->pSystemState->bufEnd;
716         _hsl->pSystemState->bufWritePos = _hsl->pSystemState->bufStart + 1; // leave one byte for the initial timer wrap
717         _hsl->pSystemState->bufReadPos = _hsl->pSystemState->bufStart;
718         _hsl->pSystemState->bufReadLimit = _hsl->pSystemState->bufWritePos;
719 
720         _hsl->pSystemState->syncMarker = 0; // must be zero since the first byte should be sync byte
721 
722         // the following values should remain constant throughout the execution
723         // calculated once on initialization
724         _hsl->pSystemState->bufMinFreeBytes = _hsl->pSystemState->bufSize * BUFFER_FREE_SPACE_PERCENTAGE / 100;
725         _hsl->pSystemState->bufSegmentSize = _hsl->pSystemState->bufSize / BUFFER_SEGMENTS_COUNT + 1;
726 
727 
728         // initialize bookmarks
729         _hsl->pSystemState->nextBookmark = 0;
730         _hsl->pSystemState->bufBookmarks[0].address = _hsl->pSystemState->bufStart;
731         _hsl->pSystemState->bufBookmarks[0].timerWrapDelta = 0;
732 
733         // initialize flags
734         _hsl->pSystemState->bufFlags = BUFFER_FLAG_NONE;
735         _hsl->pSystemState->flushOnConnect = 0; // don't flush just after the reset
736         _hsl->pSystemState->dumpFlag = BUFFER_FLAG_NONE; // no dump at the beginning
737 
738         // initialize timing
739         _hsl->pSystemState->hslLastTwTime = GetSystemTime();
740         *((MS_U8*)(_hsl->pSystemState->bufStart)) = HSL_RAWLOB_MSG_TYPE_TW_CHAN0;
741 
742         _hsl->thread_finalize = false;
743 
744         for(i=0; i<PENDING_WRITE_LIST_LEN; i++)
745         {
746             _hsl->pendingWriteList[i].u32bufferIndex = 0;
747             _hsl->pendingWriteList[i].u32timestamp = 0;
748         }
749         pthread_mutex_unlock(&(_hsl->bufferMutex));
750         pthread_mutex_unlock(&(_hsl->outputCondMutex));
751 
752         return true;
753     }
754     else
755     {
756         return false;
757     }
758 }
759 
deleteBufferMemory(stHslController * const _hsl)760 MS_BOOL deleteBufferMemory(stHslController* const _hsl)
761 {
762     if(_hsl->pSystemState->dynamicAlloc)
763     {
764         free((void*)(_hsl->pSystemState));
765     }
766     return true;
767 }
768 ////////////////////////////////////////////////////////////////////////////////
769 //    EXTERNALLY EXPOSED FUNCTIONS
770 ////////////////////////////////////////////////////////////////////////////////
771 
772 /*******************************************************************************
773     Function:
774         finalizeRingBuffer
775     Description:
776         flush output and kill any remaining threads
777     INPUT:
778         None.
779     OUTPUT:
780         None.
781  *******************************************************************************/
bufferFinalize(stHslController * const _hsl)782 MS_BOOL bufferFinalize(stHslController* const _hsl)
783 {
784     MS_BOOL rc = false;
785 
786     //    free(pDropInfo);
787 
788     // tell output thread to stop output
789     _hsl->thread_finalize = true;
790 
791     // delete condition variable
792     if(deleteThread(_hsl->logThreads[0]))
793     {
794         if(deleteCondition(&(_hsl->outputCond)))
795         {
796             if(deleteMutex(&(_hsl->outputCondMutex)))
797             {
798                 if(deleteMutex(&(_hsl->inputMutex)))
799                 {
800                     if(deleteMutex(&(_hsl->bufferMutex)))
801                     {
802                         rc = deleteBufferMemory(_hsl);
803                     }
804                 }
805             }
806         }
807     }
808     return rc;
809 }
810 
bufferCalculateFreeSpace(stHslController * const _hsl)811 MS_U32 bufferCalculateFreeSpace(stHslController* const _hsl)
812 {
813     MS_U32 retVal = 0;
814     if( _hsl->pSystemState->bufWritePos >= _hsl->pSystemState->bufReadPos )
815     {
816         retVal = _hsl->pSystemState->bufReadPos - _hsl->pSystemState->bufStart + _hsl->pSystemState->bufUsedEnd - _hsl->pSystemState->bufWritePos;
817     }
818     else
819     {
820         retVal = _hsl->pSystemState->bufReadPos - _hsl->pSystemState->bufWritePos;
821     }
822     return retVal;
823 }
824 
825 /*******************************************************************************
826     Function:
827         bufferInitialize
828     Description:
829         Initialises the library - allocates the memory for the buffer, initialises
830         the mutex and the output thread.
831     INPUT:
832         physAddr    - start addres in memory of buffer.
833         size    - size in bytes of buffer.
834     OUTPUT:
835         None.
836  *******************************************************************************/
bufferInitialize(stHslController * const _hsl,const MS_PHYADDR physAddr,const MS_U32 size)837 MS_BOOL bufferInitialize(stHslController* const _hsl, const MS_PHYADDR physAddr, const MS_U32 size)
838 {
839     MS_BOOL rc = false;
840 
841     if (initBufferMemory(_hsl, size, physAddr))
842     {
843         if (initMutex(&(_hsl->bufferMutex)))
844         {
845             if (initMutex(&(_hsl->inputMutex)))
846             {
847                 if (initMutex(&(_hsl->outputCondMutex)))
848                 {
849                     if (initCondition(&(_hsl->outputCond)))
850                     {
851                         rc = initThread(&(_hsl->logThreads[0]));
852                     }
853                 }
854             }
855         }
856     }
857 
858     return rc;
859 }
860 
861 /*******************************************************************************
862         Function:
863                 bufferDumpOldestDataSegment
864         Description:
865                 Removes the oldest data from the buffer in order to prepare space
866                 for new data
867         INPUT:
868                 None.
869         OUTPUT:
870                 None.
871  *******************************************************************************/
bufferDumpOldestDataSegment(stHslController * const _hsl)872 MS_BOOL bufferDumpOldestDataSegment(stHslController* const _hsl)
873 {
874     // copy the data between current read marker and the nearest bookmark
875     // to the dump buffer and add a warning logpoint at the end.
876     // after that move the read marker N bookmarks forward.
877 
878     //find the nearest bookmark
879     int i = (_hsl->pSystemState->bufReadPos - _hsl->pSystemState->bufStart) / _hsl->pSystemState->bufSegmentSize;
880     if(i>0)
881     {
882         i--;
883     }
884     _hsl->pSystemState->flushOnConnect = 1;
885     while( _hsl->pSystemState->bufBookmarks[i].address <= _hsl->pSystemState->bufReadPos)
886     {
887         ++i;
888     }
889 
890     // move the read pointer forward.
891     i = ( i + BUFFER_DUMP_SEGMENTS) % BUFFER_SEGMENTS_COUNT;
892 
893     if( _hsl->pSystemState->bufBookmarks[i].address < _hsl->pSystemState->bufUsedEnd )
894     {
895         _hsl->pSystemState->bufReadPos = _hsl->pSystemState->bufBookmarks[i].address;
896     }
897     else
898     {
899         // need to wrap around the end of the buffer
900         _hsl->pSystemState->bufReadPos = _hsl->pSystemState->bufStart;
901     }
902 
903     // Add a log point to inform the user about lost data
904     // The log point will be injected at current READ position
905     return TRUE;
906 }
907 
908 /*******************************************************************************
909     Function:
910         getStartAddress
911     Description:
912         Populates a data structure showing next available writing positions.
913     INPUT:
914         dataSize    - size in bytes of data to be written to buffer.
915         s_dataInfo    - data structure containing pointers to write positions, size
916             of data to be written and flag indicating a wrap condition.
917     OUTPUT:
918         None.
919  *******************************************************************************/
bufferAllocateWrite(stHslController * const _hsl,const MS_U32 dataSize,stListNode ** const s_dataInfo)920 MS_BOOL bufferAllocateWrite(stHslController* const _hsl, const MS_U32 dataSize, stListNode** const s_dataInfo)
921 {
922     MS_BOOL rc = false;
923     MS_U32 currentTime;
924     MS_U32 twDelta;
925     MS_U32 u32freeSpace;
926     MS_U32 u32tmpReadPtr;
927 
928     pthread_mutex_lock(&(_hsl->inputMutex));
929     pthread_mutex_lock(&(_hsl->bufferMutex));
930     //    pthread_mutex_lock(&dumpMutex);
931     // memory buffer exists ?
932     if ( !_hsl->thread_finalize )
933     {
934         // first things first - read the timestamp
935         currentTime = GetSystemTime();
936 
937         // update the read limits first
938         if( _hsl->pSystemState->bufReadLimit != _hsl->pSystemState->bufWritePos )
939         {
940             u32tmpReadPtr = listGetFirstValue(_hsl);
941             if( u32tmpReadPtr == 0 ) // this means no writes are pending
942             {
943                 _hsl->pSystemState->bufReadLimit = _hsl->pSystemState->bufWritePos;
944             }
945             else
946             {
947                 _hsl->pSystemState->bufReadLimit = u32tmpReadPtr;
948             }
949         }
950 
951         // calculate the number of missing timer wraps and save the timestamp
952         if( currentTime < _hsl->pSystemState->hslLastTwTime )
953         {
954             // the system clock has wrapped around
955             twDelta = 0x10000 - (_hsl->pSystemState->hslLastTwTime >> 16) + (currentTime >> 16);
956         }
957         else
958         {
959             twDelta = (currentTime >> 16) - (_hsl->pSystemState->hslLastTwTime >> 16);
960         }
961         /* WARNING: as it happens, sometimes the read from the hardware clock is incorrect
962          * which may result in large values of twDelta leading to the buffer being unable
963          * to accomodate so much data in one write.
964          * In a normal operation the value of twDelta should not exceed about 200.
965          * The following assert allows for a large slip in time readings but will still
966          * detect a major failure.
967          *
968          * It has been also observed that on some targets the hardware clock is not configured
969          * and started correctly. As a result all time readings are the same and as time
970          * measurement is an essential feature of hsl it will assert when a disfunctional clock
971          * is detected.
972          */
973         assert(_hsl->pSystemState->hslLastTwTime != currentTime);
974         assert(twDelta < ASSERT_RT_CLOCK_FAIL_TW);
975 
976         _hsl->pSystemState->hslLastTwTime = currentTime;
977 
978         if( _hsl->pSystemState->bufWritePos >= _hsl->pSystemState->bufReadPos )
979         {
980             // now see if we need to wrap around - when writing we always use the physical end of the buffer
981             if( (_hsl->pSystemState->bufEnd - _hsl->pSystemState->bufWritePos) < (twDelta + dataSize) )
982             {
983                 _hsl->pSystemState->bufUsedEnd = _hsl->pSystemState->bufWritePos;
984                 _hsl->pSystemState->bufWritePos = _hsl->pSystemState->bufStart;
985 
986                 // set the last bookmark: it should always be aligned with the end of readable data
987                 _hsl->pSystemState->bufBookmarks[BUFFER_SEGMENTS_COUNT-1].address = _hsl->pSystemState->bufUsedEnd;
988                 _hsl->pSystemState->nextBookmark = 0;
989             }
990         }
991 
992         // if the free space drops below a threshold set a flag and notify the "garbage collector"
993         // an additional mutex required to enable releasing blocking output thread and wait here
994         u32freeSpace = bufferCalculateFreeSpace(_hsl);
995         while( u32freeSpace < twDelta + dataSize )
996         {
997             _hsl->pSystemState->bufFlags |= BUFFER_FLAG_EMERGENCY_DUMP;
998             pthread_mutex_unlock(&(_hsl->bufferMutex));
999             pthread_mutex_lock(&(_hsl->outputCondMutex));
1000             pthread_mutex_lock(&(_hsl->bufferMutex));
1001             if(u32freeSpace < twDelta + dataSize) // must check again due to small probability of a complete buffer flush
1002             {
1003                 _hsl->pSystemState->dumpFlag = BUFFER_FLAG_EMERGENCY_DUMP;
1004                 bufferDumpOldestDataSegment(_hsl);
1005             }
1006             _hsl->pSystemState->bufFlags &= ~BUFFER_FLAG_EMERGENCY_DUMP;
1007             u32freeSpace = bufferCalculateFreeSpace(_hsl);
1008             pthread_cond_signal(&(_hsl->outputCond));
1009             pthread_mutex_unlock(&(_hsl->outputCondMutex));
1010         }
1011         if( u32freeSpace < _hsl->pSystemState->bufMinFreeBytes )
1012         {
1013             _hsl->pSystemState->bufFlags |= BUFFER_FLAG_DUMP;
1014             pthread_cond_signal( &(_hsl->outputCond) );
1015         }
1016         // write the missing timer wraps
1017         memset( (MS_U8*)(_hsl->pSystemState->bufWritePos), HSL_RAWLOB_MSG_TYPE_TW_CHAN0, twDelta );
1018         _hsl->pSystemState->bufWritePos += twDelta;
1019 
1020         // if we have a valid pointer to data info save the pending write data
1021         if( s_dataInfo )
1022         {
1023             // save the position of the pending write
1024             *s_dataInfo = listAppendValue(_hsl, _hsl->pSystemState->bufWritePos);
1025             (*s_dataInfo)->u32timestamp = currentTime;
1026         }
1027         else
1028         {
1029         	_hsl->pSystemState->bufReadLimit = _hsl->pSystemState->bufWritePos + dataSize;
1030         }
1031         _hsl->pSystemState->bufWritePos += dataSize;
1032 
1033         // did we pass a bookmark threshold? if yes save the position
1034         if(  _hsl->pSystemState->bufWritePos >= _hsl->pSystemState->bufStart + (_hsl->pSystemState->bufSegmentSize * (_hsl->pSystemState->nextBookmark+1)) )
1035         {
1036             _hsl->pSystemState->bufBookmarks[_hsl->pSystemState->nextBookmark].address = _hsl->pSystemState->bufWritePos;
1037             ++(_hsl->pSystemState->nextBookmark);
1038         }
1039 
1040         rc = true;
1041     }
1042 
1043     //    pthread_mutex_unlock(&dumpMutex);
1044     pthread_mutex_unlock(&(_hsl->bufferMutex));
1045     pthread_mutex_unlock(&(_hsl->inputMutex));
1046 
1047     return rc;
1048 }
1049 
bufferAcknowledgeWrite(stHslController * const _hsl,stListNode * const s_dataInfo)1050 void bufferAcknowledgeWrite( stHslController* const _hsl, stListNode* const s_dataInfo )
1051 {
1052     // no need to lock, the read limit will be updated on next allocate call
1053     listRemoveNode(_hsl, s_dataInfo);
1054 }
1055 
1056 /*******************************************************************************
1057     Function:
1058         sendToCmdQue
1059     Description:
1060         send the command to ringbuffer's command queue.
1061     INPUT:
1062         pCmd    - command queue header.
1063     OUTPUT:
1064         True/False.
1065  *******************************************************************************/
bufferProcessCommand(stHslController * const _hsl,CmdInfo * const pCmd)1066 MS_BOOL bufferProcessCommand(stHslController* const _hsl, CmdInfo* const pCmd)
1067 {
1068     switch( pCmd->u16Cmd)
1069     {
1070     case HSL_CMD_RB_TOTAL_SIZE:
1071     {
1072         pCmd->u32Len = _hsl->pSystemState->bufSize;
1073         pCmd->u32Len += _hsl->pSystemState->bufSize / HSL_RAWLOB_SYNC_MARKER_INTERVAL;
1074         /* NEED TO ADD 1KB TO THE REPORTED TOTAL BUFFER SIZE DUE TO AN ERROR IN HSLS
1075          * CAUSING A FALSE DETECTION ON A FIFO OVERFLOW
1076          */
1077         pCmd->u32Len += 1024;
1078     }
1079     break;
1080 
1081     case HSL_CMD_RB_EXIST_DATA_SIZE:
1082     {
1083         pthread_mutex_lock( &(_hsl->bufferMutex) );
1084         if( _hsl->pSystemState->bufReadLimit >= _hsl->pSystemState->bufReadPos )
1085         {
1086             pCmd->u32Len = _hsl->pSystemState->bufReadLimit - _hsl->pSystemState->bufReadPos;
1087         }
1088         else
1089         {
1090             pCmd->u32Len = (_hsl->pSystemState->bufUsedEnd - _hsl->pSystemState->bufReadPos) + (_hsl->pSystemState->bufReadLimit - _hsl->pSystemState->bufStart);
1091         }
1092         if(_hsl->pSystemState->dumpFlag != BUFFER_FLAG_NONE)
1093         {
1094             pCmd->u32Len += DUMP_LP_LEN;
1095         }
1096         pCmd->u32Len += (HSL_RAWLOB_SYNC_MARKER_INTERVAL - _hsl->pSystemState->syncMarker + pCmd->u32Len) / HSL_RAWLOB_SYNC_MARKER_INTERVAL;
1097         //pCmd->u32Len += pSystemState->syncMarker / (pCmd->u32Len % HSL_RAWLOB_SYNC_MARKER_INTERVAL);
1098         pthread_mutex_unlock( &(_hsl->bufferMutex) );
1099     }
1100     break;
1101 
1102     case HSL_CMD_SEND_DATA:
1103     {
1104         // mutex required to prevent inserting data in the middle of an HSL stream
1105         pthread_mutex_lock(&(_hsl->outputCondMutex));
1106 
1107         PUTCS(pCmd->pu8Buf, pCmd->u32Len, FR_HSL_FILE_DESCRIPTOR, _hsl);
1108         FFLUSH(FR_HSL_FILE_DESCRIPTOR);
1109 
1110         pthread_mutex_unlock(&(_hsl->outputCondMutex));
1111     }
1112     break;
1113 
1114     case HSL_CMD_RESET:
1115     {
1116         pthread_mutex_lock(&(_hsl->outputCondMutex));
1117 
1118         // Reset Sync Marker since the first byte needs to be a Sync Marker
1119         _hsl->pSystemState->bufBytesToSend = 0;
1120         _hsl->pSystemState->syncMarker = 0;
1121 
1122         if(_hsl->pSystemState->flushOnConnect > 0)
1123         {
1124             pthread_mutex_lock(&(_hsl->bufferMutex)); // TODO: review if there are no possible deadlocks
1125             _hsl->pSystemState->bufUsedEnd = _hsl->pSystemState->bufEnd;
1126             _hsl->pSystemState->bufWritePos = _hsl->pSystemState->bufStart + 1; // leave one byte for the initial timer wrap
1127             _hsl->pSystemState->bufReadPos = _hsl->pSystemState->bufStart;
1128             _hsl->pSystemState->bufReadLimit = _hsl->pSystemState->bufWritePos;
1129 
1130             _hsl->pSystemState->syncMarker = 0; // must be zero since the first byte should be sync byte
1131             // initialize bookmarks
1132 
1133             _hsl->pSystemState->nextBookmark = 0;
1134             _hsl->pSystemState->bufBookmarks[0].address = _hsl->pSystemState->bufStart;
1135             _hsl->pSystemState->bufBookmarks[0].timerWrapDelta = 0;
1136 
1137             // initialize flags
1138             _hsl->pSystemState->bufFlags = BUFFER_FLAG_NONE;
1139             _hsl->pSystemState->dumpFlag = BUFFER_FLAG_NONE;
1140 
1141             // initialize timing
1142             _hsl->pSystemState->hslLastTwTime = GetSystemTime();
1143             *((MS_U8*)(_hsl->pSystemState->bufStart)) = HSL_RAWLOB_MSG_TYPE_TW_CHAN0;
1144             _hsl->pSystemState->flushOnConnect = 1;
1145 
1146             pthread_mutex_unlock(&(_hsl->bufferMutex));
1147         }
1148         else
1149         {
1150             _hsl->pSystemState->flushOnConnect = 1;
1151         }
1152         pthread_mutex_unlock(&(_hsl->outputCondMutex));
1153 
1154         // Dump base addresses of known loaded dynamic libraries
1155         int i = 0;
1156         for(i=0; i<gDynamicLibraryCount; i++)
1157         {
1158             gDynamicLibraryInfo[i].rec_no = i+1;
1159             gDynamicLibraryInfo[i].rec_total = gDynamicLibraryCount;
1160             M_FrHslTypedef (0x80AB, HSL_DBG_SN_PROFILING, "Dynamic library base address: %d", ST_LIBRARY_SHORT_INFO, &gDynamicLibraryInfo[i]);
1161         }
1162         for(i=0; i<gThreadCount; i++)
1163         {
1164             M_FrHslTypedef (0x8DA6, HSL_DBG_SN_PROFILING, "Thread name: %d", ST_THREAD_INFO, &gThreadInfo[i]);
1165         }
1166     }
1167     break;
1168 
1169     case HSL_CMD_GET_HSL_DATA:
1170     {
1171         pthread_mutex_lock(&(_hsl->outputCondMutex));
1172         pthread_mutex_lock(&(_hsl->bufferMutex));
1173         _hsl->pSystemState->bufFlags |= BUFFER_FLAG_TX;
1174         _hsl->pSystemState->bufBytesToSend = pCmd->u32Len;
1175         pthread_cond_signal(&(_hsl->outputCond));
1176         pthread_mutex_unlock(&(_hsl->bufferMutex));
1177         pthread_mutex_unlock(&(_hsl->outputCondMutex));
1178     }
1179     break;
1180 
1181     default:
1182     {
1183         return FALSE;
1184     }
1185     break;
1186     }
1187     return TRUE;
1188 }
1189 
1190 #endif
1191 
1192