source: svn/newcon3bcm2_21bu/magnum/basemodules/kni/ucos_ii/bkni.c @ 76

Last change on this file since 76 was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 25.9 KB
Line 
1/***************************************************************************
2 *         Copyright (c) 2003-2010, Broadcom Corporation
3 *         All Rights Reserved
4 *         Confidential Property of Broadcom Corporation
5 *
6 *      THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 *      AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8 *      EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile: bkni.c $
11 * $brcm_Revision: Hydra_Software_Devel/2 $
12 * $brcm_Date: 8/19/10 8:10a $
13 *
14 * Module Description: ucos-ii bkni implementation. This module was implemented
15 * to support ucos-ii v2.86. Use with version earlier than specified may lead
16 * to undefined behavior and failure to compile.
17 *
18 * Revision History:
19 *
20 * $brcm_Log: /magnum/basemodules/kni/ucos_ii/bkni.c $
21 *
22 * Hydra_Software_Devel/2   8/19/10 8:10a jfisher
23 * SW7572-49:  Add nesting check.
24 *
25 * Hydra_Software_Devel/1   7/20/10 2:44p jfisher
26 * SW7572-30: Add ucos_ii support.
27 *
28 *
29 ***************************************************************************/
30
31#include "bstd.h"
32#include "bkni.h"
33#include "bkni_multi.h"
34#include "bkni_event_group.h"
35#include "bdbg.h"
36#include "blst_list.h"
37#include "blst_slist.h"
38
39#include "bos.h"
40#include "ucos_ii.h"
41#include "ministd.h"
42BDBG_MODULE(kni);
43
44#define ASSERT_CRITICAL() (void)0
45#define ASSERT_NOT_CRITICAL() (void)0
46#define SET_CRITICAL() (void)0
47#define CLEAR_CRITICAL() (void)0
48extern unsigned char OSLockNesting;
49extern unsigned char OSIntNesting;
50#define CHECK_CRITICAL() ( bos_in_interrupt() || (OSLockNesting > 0) || (OSIntNesting > 0))
51
52/****************************************************************************
53    Data Structures
54****************************************************************************/
55typedef struct BKNI_GroupObj {
56    BLST_D_HEAD(group, BKNI_EventObj) members;
57    OS_EVENT * pLock;
58    BKNI_EventHandle hEvent;
59} BKNI_GroupObj;
60
61typedef struct BKNI_EventObj {
62    BLST_S_ENTRY(BKNI_EventObj) link;
63    BLST_D_ENTRY(BKNI_EventObj) list;
64    OS_EVENT * pOsEvent;
65    BKNI_GroupObj * group;
66} BKNI_EventObj;
67
68typedef struct BKNI_MutexObj {
69    BLST_S_ENTRY(BKNI_MutexObj) link;
70    OS_EVENT * pOsEvent;
71} BKNI_MutexObj;
72
73#define BKNI_MS_TO_TICKS(ms) ((ms + (1000/SW_TICKS_PER_SEC) - 1)/(1000/SW_TICKS_PER_SEC))
74
75
76/* Create a new list head for our MUTEX free pool */
77static BLST_S_HEAD(BKNI_P_MutexFreePool, BKNI_MutexObj) gMutexFreePool = BLST_S_INITIALIZER(gMutexFreePool); 
78/* Create a new list head for our EVENT free pool */
79static BLST_S_HEAD(BKNI_P_EventFreePool, BKNI_EventObj) gEventFreePool = BLST_S_INITIALIZER(gEventFreePool); 
80
81/****************************************************************************
82    Static function prototypes
83****************************************************************************/
84static void BKNI_P_PostSemaphore(OS_EVENT * pEvent);
85static BERR_Code BKNI_P_GetTime(unsigned long *pulMsec);
86/****************************************************************************
87****************************************************************************/
88
89BERR_Code BKNI_Init(void)
90{
91        return BERR_SUCCESS;
92}
93
94void BKNI_Uninit(void)
95{
96}
97
98void *BKNI_Memset(void *mem, int ch, size_t n)
99{
100        return memset(mem, ch, n);
101}
102
103void *BKNI_Memcpy(void *dest, const void *src, size_t n)
104{
105        BDBG_ASSERT(src);
106        BDBG_ASSERT(dest);
107        /* Apparently some people would rather not now they are doing memcpy with 0 length
108        BDBG_ASSERT(n);
109        */
110        return memcpy(dest, src, n);
111}
112
113int BKNI_Memcmp(
114        const void *s1,         /* byte array to be compared */
115        const void *s2,         /* byte array to be compared */
116        size_t n                        /* maximum number of bytes to be compared */
117        )
118{
119        return memcmp(s1, s2, n);
120}
121
122/* Simple brute force implementation */
123void *BKNI_Memchr(const void *mem, int ch, size_t n)
124{
125        while(!n--){
126                if(*(unsigned char*)mem == (unsigned char)ch)
127                        return (void *)mem;
128                mem = ((unsigned char*)mem) + 1;
129        }
130        /* not found */
131        return 0;
132}
133
134void *BKNI_Memmove(
135        void *dest,                     /* destination byte array */
136        const void *src,        /* source byte array */
137        size_t n                        /* number of bytes to copy */
138        )
139{
140        /* our memcpy can copy overlapping memory */
141        return memcpy(dest, src, n);
142}
143#ifndef _BKNI_PRINT_H_
144int BKNI_Printf(
145        const char *fmt, /* format string */
146        ...                                     /* variable arguments */
147        )
148{
149        int ret;
150        va_list args;
151        va_start(args,fmt);
152        ret = vprintf(fmt, args);
153        va_end(args);
154        return ret;
155}
156
157int BKNI_Vprintf(const char *fmt, va_list ap)
158{
159        return vprintf(fmt, ap);
160}
161#endif /* _BKNI_PRINT_H_ */
162
163int BKNI_Snprintf(
164        char *s,                        /* destination string */
165        size_t n,                       /* size of memory that can be used. It should include
166                                                        space for the trailing null byte. */
167        const char *fmt,        /* format string */
168        ...                                     /* variable arguments */
169        )
170{
171        int ret;
172        va_list args;
173        va_start(args,fmt);
174        ret =vsnprintf(s, n, fmt, args);
175        va_end(args);
176        return ret;
177}
178
179int BKNI_Vsnprintf(char *s, size_t n, const char *fmt, va_list ap)
180{
181        return vsnprintf(s, n, fmt, ap);
182}
183
184#define HW_TICKS_US (HW_TICKS_PER_SEC / 1000000)
185
186void BKNI_Delay(unsigned int microsec)
187{
188        unsigned long count_end;
189        unsigned long count_now;
190
191        if (!CHECK_CRITICAL() && (microsec > 5000))
192        {
193                BKNI_Sleep(microsec/5000);
194                microsec %= 5000;
195
196                if (microsec == 0)
197                        return;
198        }
199
200        __asm__("mfc0 %0, $9":"=r"(count_end));
201        count_end += (g_ticks_per_second * microsec) - 10;
202        do{
203                __asm__ volatile ("mfc0 %0, $9":"=r"(count_now));
204        }while(0 == ((count_end - count_now) & 0x80000000));
205}
206
207#if BDBG_DEBUG_BUILD
208void *BKNI_Malloc_tagged(
209        size_t size,
210        const char *file,
211        int line
212        )
213{
214        return malloc_dbg(size,(char*)file,line);
215}
216
217void BKNI_Free_tagged(
218        void *mem,                      /* Pointer to memory allocated by BKNI_Malloc */
219        const char *file,
220        int line
221        )
222{
223        free_dbg(mem, (char*)file, line);
224        return;
225}
226
227void BKNI_DumpMallocs(void)
228{
229        m_report();
230}
231#else
232void *BKNI_Malloc(size_t size)
233{
234        return malloc(size);
235}
236
237void BKNI_Free( void *mem)
238{
239        return free(mem);
240}
241#endif
242
243BERR_Code BKNI_Sleep(
244        unsigned int millisec   /* minimum number of milliseconds to sleep */
245        )
246{
247        bos_sleep(millisec);
248        return BERR_SUCCESS;
249}
250
251/****************************************************************************
252****************************************************************************/
253BERR_Code
254BKNI_CreateEvent(BKNI_EventHandle * event)
255{
256    BKNI_EventObj * pEventObj;
257    bool bAllocNewOsEvent = false;
258        OS_CPU_SR  cpu_sr = 0;
259
260    ASSERT_NOT_CRITICAL();
261
262    *event = NULL;
263
264    /* First, check our free pool */
265    OS_ENTER_CRITICAL();
266    pEventObj = BLST_S_FIRST(&gEventFreePool);
267    if (pEventObj == NULL) {
268        OS_EXIT_CRITICAL();
269        bAllocNewOsEvent = true;
270        pEventObj = (BKNI_EventObj *)BKNI_Malloc(sizeof(BKNI_EventObj));
271    } else {
272        BLST_S_REMOVE_HEAD(&gEventFreePool, link);
273        OS_EXIT_CRITICAL();
274    }
275
276    if (pEventObj == NULL) {
277        return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
278    }
279
280    if (bAllocNewOsEvent == true) {
281        pEventObj->pOsEvent = OSSemCreate(0);
282        if (pEventObj->pOsEvent == NULL) {
283            BKNI_Free(pEventObj);
284            return BERR_TRACE(BERR_OS_ERROR);
285        }
286    } else {
287        /* Initialize the Sem count for this event. We don't have to do this
288           in a critical section because the sem isn't being used right now
289        */
290        pEventObj->pOsEvent->OSEventCnt = 0;
291    }
292
293    pEventObj->group = NULL;
294
295    *event = pEventObj;
296   
297    return BERR_SUCCESS;
298}
299
300/****************************************************************************
301****************************************************************************/
302void
303BKNI_DestroyEvent(BKNI_EventHandle event)
304{
305        OS_CPU_SR  cpu_sr = 0;
306    ASSERT_NOT_CRITICAL();
307
308    if (event) {
309        OS_ENTER_CRITICAL();
310        BLST_S_INSERT_HEAD(&gEventFreePool, (BKNI_EventObj *)event, link);
311        OS_EXIT_CRITICAL();
312    }
313   
314    return;
315}
316
317/****************************************************************************
318****************************************************************************/
319BERR_Code
320BKNI_WaitForEvent(BKNI_EventHandle event, int timeoutMsec)
321{
322    BERR_Code   errCode = BERR_SUCCESS;
323    unsigned char       ucosErr;
324        OS_CPU_SR  cpu_sr = 0;
325   
326    int ticks;
327
328    if (!event || !(event->pOsEvent)) {
329        return BERR_INVALID_PARAMETER;
330    }
331   
332    if (timeoutMsec != 0) {
333        ASSERT_NOT_CRITICAL();
334    }
335
336    /* According to PI documentation, a timeout of 0 tells us to
337       check for an event signal and return immediately. We're not supposed
338       to let it get scheduled because an ISR is allowed to call this
339       ONLY if the timeout is 0.
340    */
341    if (timeoutMsec == 0) {
342        OS_ENTER_CRITICAL();
343        if (event->pOsEvent->OSEventCnt) {
344            event->pOsEvent->OSEventCnt--;
345            errCode = BERR_SUCCESS;
346        } else {
347            errCode = BERR_TIMEOUT;
348        }
349        OS_EXIT_CRITICAL();
350        return errCode;
351    }
352
353    if (timeoutMsec == BKNI_INFINITE) {
354        ticks = 0;
355    } else {
356#if 0 /* Not needed for ucos */
357        if (timeoutMsec < 30) {
358            /* NOTE: The Linux kernel kni interface a 30ms minimum timeout -- why? */
359            timeoutMsec = 30;
360        }
361#endif
362        /* This macro forces us to round up to the next 10ms */
363        ticks = BKNI_MS_TO_TICKS(timeoutMsec);
364                if (ticks <= 0)
365                        ticks = 1;
366    }
367    if (((unsigned int)(event->pOsEvent) & 0xF0000000) != 0x80000000) 
368    {
369        __asm__("sdbbp");
370    }
371
372    OSSemPend(event->pOsEvent, ticks, &ucosErr); 
373
374    switch( ucosErr ) {
375        case OS_NO_ERR:
376            break;
377        case OS_TIMEOUT:
378            errCode = BERR_TIMEOUT;
379            break;
380        default:
381            errCode = BERR_OS_ERROR;
382            break;
383    }
384
385    return errCode;
386}
387
388/****************************************************************************
389    By current definition, BKNI_SetEvent can be called from both task and
390    interrupt context (interrupt means ISR or CriticalSection). Unfortunately,
391    BKNI_SetEvent_isr is permanently mapped to BKNI_SetEvent.
392   
393    Since this is the case, we need to add logic to know whether or not we are
394    inside a critical section so we can process accordingly.
395   
396    NOTE: I do not expect BKNI_SetEvent to be called from real interrupt
397    context (as opposed to our high-priority ISR task) because I have no way
398    of knowing we're actually running in interrupt context. I only know we're
399    in a CriticalSection, which we enter before we call Magnum ISRs.
400****************************************************************************/
401static void
402BKNI_P_SetEvent_isr(BKNI_EventHandle event)
403{
404    INT8U ucosStatus;
405    if (((unsigned int)(event->pOsEvent) & 0xF0000000) != 0x80000000) 
406    {
407        __asm__("sdbbp");
408    }
409
410    if (event && event->pOsEvent) {
411        BKNI_GroupObj *group = event->group;
412
413        /* We're in ISR context (either a real ISR or a CriticalSection), so
414           the OS scheduler is already being held. Don't attempt to lock it again.
415        */
416        /* prevent the event count saturating */
417        ucosStatus = OSSemPost(event->pOsEvent);
418        if (event->pOsEvent->OSEventCnt > 1) {
419            event->pOsEvent->OSEventCnt = 1;
420        }
421
422        if (ucosStatus != OS_NO_ERR) {
423            ucosStatus = BERR_TRACE(ucosStatus);
424        }
425        /* If this event is part of a group, signal the group event */
426        if (group) {
427            BKNI_P_SetEvent_isr(group->hEvent);
428        }
429    }
430}
431
432void
433BKNI_SetEvent(BKNI_EventHandle event)
434{
435    unsigned char ucosError;
436    INT8U ucosStatus;
437
438    /* */
439    if (CHECK_CRITICAL()) {
440        BKNI_P_SetEvent_isr(event);
441        return;
442    }
443   
444    if (event && event->pOsEvent) {
445        BKNI_GroupObj *group = event->group;
446        if (group) {
447            OSSemPend(group->pLock, 0, &ucosError); 
448            if (ucosError != OS_NO_ERR) {
449                ucosError = BERR_TRACE(ucosError);
450            }
451        }
452        /* Hold the the scheduler while we prevent the event count saturating */
453        OSSchedLock();
454        ucosStatus = OSSemPost(event->pOsEvent);
455        if (event->pOsEvent->OSEventCnt > 1) {
456            event->pOsEvent->OSEventCnt = 1;
457        }
458        OSSchedUnlock();
459        /* event may now be stale.... */
460        if (ucosStatus != OS_NO_ERR) {
461            ucosStatus = BERR_TRACE(ucosStatus);
462        }
463        if (group) {
464            BKNI_SetEvent(group->hEvent);
465            BKNI_P_PostSemaphore(group->pLock);
466        }
467    }
468}
469
470/****************************************************************************
471****************************************************************************/
472void
473BKNI_ResetEvent(BKNI_EventHandle event)
474{
475    BDBG_ASSERT((((int) event) % 4) == 0);
476    BDBG_ASSERT((((int) event->pOsEvent) % 4) == 0);
477    if (event && event->pOsEvent) {
478        event->pOsEvent->OSEventCnt = 0;
479    }
480}
481/*
482  We implement BKNI_Fail by executing jtag or software breakpoint
483  instruction, causing system to drop in to the debugger.
484 */
485#define BREAK_TYPE_SOFT 1
486#define BREAK_TYPE_JTAG 2
487#define BREAK_TYPE BREAK_TYPE_JTAG
488void BKNI_Fail(void)
489{
490        BKNI_Sleep(1000);
491#if BREAK_TYPE == BREAK_TYPE_SOFT
492        __asm__("break");
493#else
494        /* __asm__("sdbbp") will put the cpu in debug mode that will freeze watchdog timer */
495#ifdef CONFIG_WATCHDOG
496        BKNI_EnterCriticalSection();
497        while (1);
498#else
499        __asm__("sdbbp");
500#endif
501#endif
502}
503
504struct critical_stance_t {
505        OS_CPU_SR cpu_sr;
506        unsigned int ref_count;
507};
508
509struct critical_stance_t cs = {OS_ENABLE, 0};
510
511void BKNI_EnterCriticalSection(void)
512{
513        OS_CPU_SR  cpu_sr = 0;
514        OSSchedLock();
515        OS_ENTER_CRITICAL();
516        cs.cpu_sr = cpu_sr;
517        cs.ref_count++;
518}
519
520void BKNI_LeaveCriticalSection(void)
521{
522        OS_CPU_SR  cpu_sr = cs.cpu_sr;
523        cs.ref_count--;
524        OS_EXIT_CRITICAL();
525        OSSchedUnlock();
526}
527
528void BKNI_AssertIsrContext(const char *filename, unsigned lineno)
529{
530        if((cs.ref_count == 0) && !bos_in_interrupt()){
531                BKNI_Fail();
532        }
533}
534
535/****************************************************************************
536    Don't use BDBG_ messages in BKNI_CreateMutex -- we get called during
537    KNI & DBG init.
538****************************************************************************/
539BERR_Code
540BKNI_CreateMutex(BKNI_MutexHandle *mutex)
541{
542    BKNI_MutexObj * pMutexObj;
543    bool bAllocNewOsEvent = false;
544        OS_CPU_SR  cpu_sr = 0;
545
546    ASSERT_NOT_CRITICAL();
547
548    *mutex = NULL;
549
550    /* First, check our free pool */
551    OS_ENTER_CRITICAL();
552    pMutexObj = BLST_S_FIRST(&gMutexFreePool);
553    if (pMutexObj == NULL) {
554        OS_EXIT_CRITICAL();
555        bAllocNewOsEvent = true;
556        pMutexObj = (BKNI_MutexObj *)BKNI_Malloc(sizeof(BKNI_MutexObj));
557    } else {
558        BLST_S_REMOVE_HEAD(&gMutexFreePool, link);
559        OS_EXIT_CRITICAL();
560    }
561
562    if (pMutexObj == NULL) {
563        return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
564    }
565
566    if (bAllocNewOsEvent == true) {
567        pMutexObj->pOsEvent = OSSemCreate(1);
568        if (pMutexObj->pOsEvent == NULL) {
569            BKNI_Free(pMutexObj);
570            return BERR_TRACE(BERR_OS_ERROR); 
571        }
572    } else {
573        /* Initialize the Sem count for this mutex. We don't have to do this
574           in a critical section because the sem isn't being used right now
575        */
576        pMutexObj->pOsEvent->OSEventCnt = 1;
577    }
578
579    *mutex = (BKNI_MutexHandle)pMutexObj;
580
581    return BERR_SUCCESS;
582}
583
584/****************************************************************************
585****************************************************************************/
586void
587BKNI_DestroyMutex(BKNI_MutexHandle mutex)
588{
589        OS_CPU_SR  cpu_sr = 0;
590    ASSERT_NOT_CRITICAL();
591
592    /* uCos doesn't have a way to destroy the semaphore. Add it to our free pool */
593    if (mutex) {
594        OS_ENTER_CRITICAL();
595        BLST_S_INSERT_HEAD(&gMutexFreePool, (BKNI_MutexObj *)mutex, link);
596        OS_EXIT_CRITICAL();
597        mutex = NULL;
598    }
599
600    return;
601}
602
603/****************************************************************************
604****************************************************************************/
605BERR_Code
606BKNI_TryAcquireMutex(BKNI_MutexHandle mutex)
607{
608    BERR_Code errCode = BERR_SUCCESS;
609        OS_CPU_SR  cpu_sr = 0;
610
611    ASSERT_NOT_CRITICAL();
612
613    if (!mutex || !(mutex->pOsEvent)) {
614        return BERR_INVALID_PARAMETER;
615    }
616
617    /* See if we can acquire this mutex. If so, grab it and go.
618       If not, return a timeout error. Don't block.
619    */
620    OS_ENTER_CRITICAL();
621    if (mutex->pOsEvent->OSEventCnt) {
622        /* We know it's available -- grab it */
623        mutex->pOsEvent->OSEventCnt--;
624        errCode = BERR_SUCCESS;
625    } else {
626        errCode = BERR_TIMEOUT;
627    }
628    OS_EXIT_CRITICAL();
629
630    return errCode;
631}
632
633#if SUPPORT_DST_PLATFORM
634/****************************************************************************
635****************************************************************************/
636BERR_Code
637BKNI_AcquireMutexTimeout(BKNI_MutexHandle mutex, unsigned short timeout)
638{
639        unsigned char           ucosErr;
640        BERR_Code       errCode = BERR_SUCCESS;
641
642        ASSERT_NOT_CRITICAL();
643
644        if (!mutex || !(mutex->pOsEvent)) {
645                return BERR_INVALID_PARAMETER;
646        }
647
648        /* Wait forever on this mutex */
649        OSSemPend(mutex->pOsEvent, timeout, &ucosErr); 
650
651        switch( ucosErr ) {
652                case OS_NO_ERR:
653                        break;
654                case OS_TIMEOUT:
655                        errCode = BERR_TIMEOUT;
656                        break;
657                default:
658                        errCode = BERR_OS_ERROR;
659                        break;
660        }
661       
662        return errCode;
663}
664
665
666#endif
667
668/****************************************************************************
669****************************************************************************/
670BERR_Code
671BKNI_AcquireMutex(BKNI_MutexHandle mutex)
672{
673    unsigned char       ucosErr;
674    BERR_Code   errCode = BERR_SUCCESS;
675
676    ASSERT_NOT_CRITICAL();
677
678    if (!mutex || !(mutex->pOsEvent)) {
679        return BERR_INVALID_PARAMETER;
680    }
681
682    /* Wait forever on this mutex */
683    OSSemPend(mutex->pOsEvent, 0, &ucosErr); 
684
685    switch( ucosErr ) {
686        case OS_NO_ERR:
687            break;
688        case OS_TIMEOUT:
689            errCode = BERR_TIMEOUT;
690            break;
691        default:
692            errCode = BERR_OS_ERROR;
693            break;
694    }
695   
696    return errCode;
697}
698
699/****************************************************************************
700****************************************************************************/
701void
702BKNI_ReleaseMutex(BKNI_MutexHandle mutex)
703{
704    ASSERT_NOT_CRITICAL();
705
706    if (mutex && mutex->pOsEvent) {
707        BKNI_P_PostSemaphore(mutex->pOsEvent);
708    }
709}
710
711/****************************************************************************
712    Event Group Functions
713****************************************************************************/
714BERR_Code
715BKNI_CreateEventGroup(BKNI_EventGroupHandle *pGroup)
716{
717    BKNI_EventGroupHandle group;
718    BERR_Code result = BERR_SUCCESS;
719
720    group = (BKNI_EventGroupHandle)BKNI_Malloc(sizeof(*group));
721    if (!group) {
722        result = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
723        goto err_no_memory;
724    }
725    BLST_D_INIT(&group->members);
726   
727    group->pLock = OSSemCreate(1);
728    if (group->pLock == NULL) {
729        result = BERR_TRACE(BERR_OS_ERROR);
730        goto err_mutex;
731    }
732    result = BKNI_CreateEvent(&(group->hEvent));
733    if (result != BERR_SUCCESS) {
734        result = BERR_TRACE(result);
735        goto err_event;
736    }
737
738    *pGroup = group;
739
740    return BERR_SUCCESS;
741
742err_event:
743    /* uCOS does not have a method to destroy a semaphore */
744    BDBG_ERR(("%s: uCOS Event Leak - no method to destroy semaphore", __FUNCTION__));
745err_mutex:
746    BKNI_Free((void *)group);
747err_no_memory:
748    return result;
749}
750
751/****************************************************************************
752****************************************************************************/
753void
754BKNI_DestroyEventGroup(BKNI_EventGroupHandle group)
755{
756    unsigned char ucosError;
757    BKNI_EventHandle event;
758
759    OSSemPend(group->pLock, 0, &ucosError); 
760    if (ucosError != OS_NO_ERR) {
761        ucosError = BERR_TRACE(ucosError);
762        BDBG_ASSERT(false);
763    }
764    while( NULL != (event=BLST_D_FIRST(&group->members)) ) {
765        event->group = NULL;
766        BLST_D_REMOVE_HEAD(&group->members, list);
767    }
768    BKNI_P_PostSemaphore(group->pLock);
769    BDBG_ERR(("%s: uCOS Event Leak - no method to destroy semaphore", __FUNCTION__));
770    BKNI_DestroyEvent(group->hEvent);
771    BKNI_Free((void *)group);
772
773    return;
774}
775
776/****************************************************************************
777****************************************************************************/
778BERR_Code
779BKNI_AddEventGroup(BKNI_EventGroupHandle group, BKNI_EventHandle event)
780{
781    unsigned char ucosError;
782    BERR_Code result = BERR_SUCCESS;
783        OS_CPU_SR  cpu_sr = 0;
784
785    /* IMPORTANT: group lock shall be acquired before event lock */
786    OSSemPend(group->pLock, 0, &ucosError); 
787    if (ucosError != OS_NO_ERR) {
788        ucosError = BERR_TRACE(ucosError);
789        BDBG_ASSERT(false);
790    }
791    if (event->group != NULL) {
792        BDBG_ERR(("Event %#x already connected to group %#x", (unsigned)event, (unsigned)group));
793        result = BERR_TRACE(BERR_OS_ERROR);
794    } else {
795        bool bIsSet;
796        BLST_D_INSERT_HEAD(&group->members, event, list);
797        event->group = group;
798        OS_ENTER_CRITICAL();
799        bIsSet = event->pOsEvent->OSEventCnt > 0;
800        OS_EXIT_CRITICAL();
801        if (bIsSet) { /* kinda racey */
802            BKNI_SetEvent(group->hEvent);
803        }
804    }
805    BKNI_P_PostSemaphore(group->pLock);
806
807    return result;
808}
809
810/****************************************************************************
811****************************************************************************/
812BERR_Code
813BKNI_RemoveEventGroup(BKNI_EventGroupHandle group, BKNI_EventHandle event)
814{
815    unsigned char ucosError;
816    BERR_Code result = BERR_SUCCESS;
817
818    OSSemPend(group->pLock, 0, &ucosError); 
819    if (ucosError != OS_NO_ERR) {
820        ucosError = BERR_TRACE(ucosError);
821        BDBG_ASSERT(false);
822    }
823    if (event->group != group) {
824        BDBG_ERR(("Event %#x doesn't belong to group %#x", event, group));
825        result = BERR_TRACE(BERR_OS_ERROR);
826    } else {
827        BLST_D_REMOVE(&group->members, event, list);
828        event->group = NULL;
829    }
830    BKNI_P_PostSemaphore(group->pLock);
831
832    return result;
833}
834
835/****************************************************************************
836****************************************************************************/
837static unsigned
838group_get_events(BKNI_EventGroupHandle group, BKNI_EventHandle *events, unsigned max_events)
839{
840    unsigned char ucosError;
841    BKNI_EventHandle ev;
842    unsigned event;
843        OS_CPU_SR  cpu_sr = 0;
844
845    OSSemPend(group->pLock, 0, &ucosError); 
846    if (ucosError != OS_NO_ERR) {
847        ucosError = BERR_TRACE(ucosError);
848        BDBG_ASSERT(false);
849    }
850    for(event=0, ev=BLST_D_FIRST(&group->members); ev && event<max_events ; ev=BLST_D_NEXT(ev, list)) {
851        bool bIsSet;
852        OS_ENTER_CRITICAL();
853        if ((bIsSet = (ev->pOsEvent->OSEventCnt > 0)) == true) {
854            ev->pOsEvent->OSEventCnt = 0;
855        }
856        OS_EXIT_CRITICAL();
857        if (bIsSet) {
858            events[event] = ev;
859            event++;
860        }
861    }
862    BKNI_P_PostSemaphore(group->pLock);
863
864    return event;
865}
866
867/****************************************************************************
868****************************************************************************/
869BERR_Code
870BKNI_WaitForGroup(BKNI_EventGroupHandle group, int timeoutMsec, BKNI_EventHandle *events, unsigned max_events, unsigned *nevents)
871{
872    BERR_Code result;
873    unsigned long target, now;
874    bool forever = false;
875
876    ASSERT_NOT_CRITICAL();
877
878    if (max_events < 1) {
879        return BERR_TRACE(BERR_INVALID_PARAMETER);
880    }
881
882    if (timeoutMsec == BKNI_INFINITE) {
883        forever = true;
884    } else if (timeoutMsec == 0) {
885        BKNI_WaitForEvent(group->hEvent, 0); /* just clear event */
886        *nevents = group_get_events(group, events, max_events);
887        return *nevents ? BERR_SUCCESS : BERR_TIMEOUT;
888    } else {
889        BKNI_P_GetTime(&target);
890        target += timeoutMsec;
891    }
892
893    for(;;) {
894        /* Make sure we clear the group's event status by calling WaitForEvent.
895           Other OS ports check their event list immediately, but they don't
896           use an Event for the group itself.
897        */
898        result = BKNI_WaitForEvent(group->hEvent, forever ? BKNI_INFINITE : timeoutMsec);
899        if (result == BERR_SUCCESS) {
900            *nevents = group_get_events(group, events, max_events);
901            if (*nevents) {
902                return BERR_SUCCESS;
903            }
904        } else if (result == BERR_TIMEOUT) {
905            *nevents = 0;
906            return BERR_TIMEOUT;
907        } else {
908            return BERR_TRACE(BERR_OS_ERROR);
909        }
910        /* false wakeup */
911        if (!forever) {
912            result = BKNI_P_GetTime(&now);
913            if (result != BERR_SUCCESS) {
914                return BERR_TRACE(BERR_OS_ERROR);
915            }
916            if ((int)(now - target) >= 0) {
917                *nevents = 0;
918                return BERR_TIMEOUT;
919            }
920            timeoutMsec = target - now;
921        }
922    }
923}
924
925/****************************************************************************
926    Provide an internal method for releasing a "mutex" (really a uCOS
927    semaphore). Internal functions can't use the external BKNI interface
928    now that we've added additional checks for validity.
929   
930    Since we're using a semaphore, make sure the count never gets higher
931    than 1. If it does, it means we released the mutex more times than it
932    was acquired
933****************************************************************************/
934static void
935BKNI_P_PostSemaphore(OS_EVENT * pEvent)
936{
937    uint32_t mutexCount;
938        OS_CPU_SR  cpu_sr = 0;
939
940    /* Since we're using a semaphore, make sure the count never
941       gets higher than 1. If it does, it means we released the
942       mutex more times than it was acquired
943    */
944    OS_ENTER_CRITICAL();
945    mutexCount = pEvent->OSEventCnt;
946    OS_EXIT_CRITICAL();
947    if (mutexCount > 0) {
948        /* Mutex already posted. Don't do it again */
949        mutexCount = BERR_TRACE(mutexCount);
950    } else {
951        OSSemPost(pEvent);
952    }
953}
954
955
956/****************************************************************************
957****************************************************************************/
958static BERR_Code
959BKNI_P_GetTime(unsigned long *pulMsec)
960{
961    unsigned long  ticks;
962    ticks = (unsigned long)bos_getticks();
963    *pulMsec  = (unsigned long)TICKS_TO_MS(ticks);
964    return BERR_SUCCESS;
965}
966
Note: See TracBrowser for help on using the repository browser.