source: svn/zas_dstar/hal/os/src/module/lld_evnt.c @ 66

Last change on this file since 66 was 66, checked in by megakiss, 11 years ago

키패드 기능 연결

전원키 누르고 리모콘 누르면 학습
CH+ 간격 1초 증가 MAX:15
CH- 간격 1초 감소 MIN :1

File size: 20.5 KB
Line 
1/****************************************************************************
2 * Copyright (c) 2006 DST Technologies Inc.  All Rights Reserved.   
3 *
4 * Module:  EVENTS
5 *
6 * Description: This is a decent implementation of events under Linux.
7 *
8 * Notes:   This implementation poses some limitations, some of which can
9 *          be changed by adjusting some defines:
10 *        - Max number of events, shared and local, in the system is
11 *          defined by MAX_NOF_EVENTS
12 *        - Max number of processes that can share the same event at
13 *          any given time is defined by MAX_NOF_PROCS
14 *        - When a event is deleted, all tasks within the calling process
15 *          that may be pending on the event will be unlocked with an
16 *          error code.
17 *
18 ***************************************************************************/
19
20/*============================
21 * Includes
22 *===========================*/
23#include "lld_os.h"
24#include "dsthallocal.h"
25#include "lld_local.h"
26#include "os.h"
27
28/*============================
29 * Defines
30 *===========================*/
31#define UNUSED_EVENT            0xffffffff
32#define SIGNALED                1
33#define NOT_SIGNALED            0
34#define INVALID_PID             0xffffffff  /* Invalid process ID   */
35#define Event(i)                (EventsPtr->_Events[i])
36#define EventPtr(i)             (&(EventsPtr->_Events[i]))
37
38/*============================
39 * Structures
40 *===========================*/
41typedef struct 
42{
43    DS_U32  Status;                     /* = UNUSED_EVENT if not used       */
44    DS_U32  Name;                       /* 0 for local events               */
45    DS_U32  OwnerPid[MAX_NOF_PROCS];    /* Owner process IDs. Contains      */
46                                        /* INVALID_PID for non used entries */
47    WAIT_Q  WaitQ;                      /* Queue of processes waiting on    */
48                                        /* the event                        */
49}EVNT_STR;
50
51typedef struct
52{
53    EVNT_STR _Events[MAX_NOF_EVENTS];
54}EVENTS;
55
56/*============================
57 * Shared variables
58 *===========================*/
59static EVENTS *EventsPtr = NULL;        /* Pointer to events area */
60
61/*============================
62 * Prototypes
63 *===========================*/
64static DS_U32 EventCreate (DS_U32 EventName, DS_BOOL Signaled, DS_U32 *EvntId);
65static DS_U32 EventWait   (DS_U32 EvntId, DS_U32 Timeout, DS_U32 *TimeLeft,
66                           DS_U32 AutoReset);
67static DS_U32 EventSet    (DS_U32 EvntId);
68static DS_U32 EventReset  (DS_U32 EvntId);
69static DS_U32 EventDelete (DS_U32 EvntId);
70static DS_U32 EventInfo   (DS_U32 EvntId, DS_U32 *Size, void *Dest);
71static EVNT_STR *GetEvPtr (DS_U32 EvntId, DS_U32 *ProcIndex);
72
73/*^^***************************************************************************
74 * void EventInit (void)
75 *
76 * Description: Initialize kernel events for first use
77 *
78 * Entry :  None
79 *
80 * Return:  None
81 *
82 * Notes :
83 *
84 **************************************************************************^^*/
85void EventInit (void)
86{
87    DS_U32 i;
88    EVNT_STR *EvPtr;
89
90    /*=======================================
91     * Allocate shared mem for events
92     *======================================*/
93    if (EventsPtr == NULL)
94    {
95        EventsPtr = lld_os_malloc (sizeof(EVENTS));
96
97        /*=======================================
98         * Initialize events array
99         *======================================*/
100        for (i=0; i<MAX_NOF_EVENTS; i++)
101        {
102            EvPtr = EventPtr(i);
103            EvPtr->Status = UNUSED_EVENT;
104        }
105    }
106}
107
108/*^^***************************************************************************
109 * void EventCleanup (void)
110 *
111 * Description: Cleanup for module shutdown
112 *
113 * Entry :  None
114 *
115 * Return:  None
116 *
117 * Notes :
118 *
119 **************************************************************************^^*/
120void EventCleanup (void)
121{
122    if (EventsPtr != NULL)
123    {
124        lld_os_free (EventsPtr);
125    }
126}
127
128/*^^***************************************************************************
129 * void EventProcessExit (void)
130 *
131 * Description: Cleanup for all events when a process exits normally
132 *              or upnormally.
133 *
134 * Entry :  None
135 *
136 * Return:  None
137 *
138 * Notes : 
139 *
140 **************************************************************************^^*/
141void EventProcessExit (void)
142{
143    DS_U32  i, j, k, ProcId;
144    EVNT_STR *EvPtr;
145
146    ProcId = mCurrentPid;
147
148    /*================================
149     * For all events in the system
150     *===============================*/
151    for (i=0; i<MAX_NOF_EVENTS; i++)
152    {
153        EvPtr = EventPtr(i);
154        /*===============================
155         * If event exist
156         *==============================*/
157        if (EvPtr->Status != UNUSED_EVENT)
158        {
159            k = 0;                                  /* Ev reference count */
160            /*===============================
161             * Find ev reference count
162             *==============================*/
163            for (j=0; j<MAX_NOF_PROCS; j++)
164            {
165                /*=======================================
166                 * If the terminating proc owns the ev
167                 * remove it from the list
168                 *======================================*/
169                if (EvPtr->OwnerPid[j] == ProcId)
170                {
171                    EvPtr->OwnerPid[j] = INVALID_PID;
172                }
173                if (EvPtr->OwnerPid[j] != INVALID_PID)
174                {
175                    k++;                    /* Other process owns the event */
176                }
177            }
178            /*============================================
179             * If no other processes reference the ev
180             *===========================================*/
181            if (k == 0)
182            {
183                EvPtr->Status = UNUSED_EVENT;
184            }
185        }
186    }
187}
188
189/*^^***************************************************************************
190 * DS_U32 EventOperation (OBJ_OPER *EvPrm)
191 *
192 * Description: Perform event operation defined in EvPrm
193 *
194 * Entry :  EvPrm = Pointer to OBJ_OPER struc holding the requested operation.
195 *
196 * Return:  0 or -ERESTARTSYS
197 *          EvPrm.RetCode hold return values (varies by the opcode)
198 *          EvPrm.Prm2 will also be set as follows:
199 *            Create: EvPrm.Prm2 = Event ID. = 0 if any error.
200 *            Wait:   EvPrm.Prm2 = Adjusted timeout if ret due to signal
201 *            Info:   EvPrm.Prm2 = Info size
202 *
203 * Notes :
204 *
205 **************************************************************************^^*/
206DS_U32 EventOperation (OBJ_OPER *EvPrm)
207{
208    switch (EvPrm->Opcode)
209    {
210        case OBJ_OPCODE_CREATE:
211            EvPrm->RetCode = EventCreate (EvPrm->Prm1, EvPrm->Prm2, 
212                                          &(EvPrm->Prm2));
213            break;
214        case OBJ_OPCODE_DELETE:
215            EvPrm->RetCode = EventDelete (EvPrm->Prm1);
216            break;
217        case OBJ_OPCODE_WAIT:
218            EvPrm->RetCode = EventWait (EvPrm->Prm1, EvPrm->Prm2, 
219                                        &(EvPrm->Prm2), EvPrm->RetCode);
220            if (EvPrm->RetCode == OBJ_SIGNAL_RCV)
221            {
222                return (ERR_RESTART_SYS);
223            }
224            break;
225        case OBJ_OPCODE_SET:
226            EvPrm->RetCode = EventSet (EvPrm->Prm1);
227            break;
228        case OBJ_OPCODE_RESET:
229            EvPrm->RetCode = EventReset (EvPrm->Prm1);
230            break;
231        case OBJ_OPCODE_INFO:
232            EvPrm->RetCode = EventInfo (EvPrm->Prm1, &(EvPrm->Prm2), 
233                                        (void *)(EvPrm->Prm2));
234            break;
235        default:
236            EvPrm->RetCode = OBJ_INVALID_OP;
237            break;
238    }
239    return (0);
240}
241
242/*^^***************************************************************************
243 * static DS_U32 EventCreate (DS_U32 EventName, DS_BOOL Signaled, DS_U32 *EvntId)
244 *
245 * Description: Creates an event object with the specified status
246 *
247 * Entry :  EventName  = Unique number identifying the event.
248 *                       Set to NULL to create unnamed event (can not be
249 *                       used for inter-process synchronization)
250 *          Status     = Initial status (Set=_TRUE_, Reset=_FALSE_)
251 *          EvntId     = Pointer to receive event ID
252 *
253 * Return:  Entry EvntId holds event ID. =0 if any error. Return codes are:
254 *          OBJ_OK              Operation completed
255 *          OBJ_INVALID_ID      Invalid ev id or process does not own ev
256 *          OBJ_MAX_PROCS       Max number of procs reached
257 *          OBJ_MAX_OBJS        Max number of events reached
258 *
259 * Notes :  If the same process creates a shared event multiple times,
260 *          it's pid will appear in the event's OwnerPid list only once.
261 *          In this case, only one delete is required by the calling process
262 *          to delete the event.
263 *
264 **************************************************************************^^*/
265static DS_U32 EventCreate (DS_U32 EventName, DS_BOOL Signaled, DS_U32 *EvntId)
266{
267    DS_U32 i, j;
268    EVNT_STR *EvPtr = NULL;
269
270    *EvntId = 0;
271    if (EventsPtr == NULL)
272    {
273        return (OBJ_INVALID_ID);
274    }
275
276    /*================================
277     * If shared event
278     *===============================*/
279    if (EventName != 0)
280    {
281        /*===========================================
282         * Find if shared ev exist (same name)
283         *==========================================*/
284        for (i=0; i<MAX_NOF_EVENTS; i++)
285        {
286            EvPtr = EventPtr(i);
287            if ((EvPtr->Status != UNUSED_EVENT) && (EvPtr->Name == EventName))
288            {
289                /*===============================================
290                 * Find if current process already owns the ev
291                 *==============================================*/
292                for (j=0; j<MAX_NOF_PROCS; j++)
293                {
294                    if (EvPtr->OwnerPid[j] == mCurrentPid)
295                    {
296                        *EvntId = (i+1);
297                        return (OBJ_OK);
298                    }
299                }
300                /*===============================================
301                 * No, add process to owners list
302                 *==============================================*/
303                for (j=0; j<MAX_NOF_PROCS; j++)
304                {
305                    if (EvPtr->OwnerPid[j] == INVALID_PID)
306                    {
307                        EvPtr->OwnerPid[j] = mCurrentPid;
308                        *EvntId = (i+1);
309                        return (OBJ_OK);
310                    }
311                }
312                return (OBJ_MAX_PROCS);
313            }
314        }
315    }
316
317    /*======================================================
318     * If ev does not exist or local ev, create new one
319     *=====================================================*/
320    for (i=0; i<MAX_NOF_EVENTS; i++)
321    {
322        EvPtr = EventPtr(i);
323        if (EvPtr->Status == UNUSED_EVENT)
324        {
325            if (Signaled)
326            {
327                EvPtr->Status = SIGNALED;
328            }
329            else
330            {
331                EvPtr->Status = NOT_SIGNALED;
332            }
333            EvPtr->Name = EventName;
334            for (j=0; j<MAX_NOF_PROCS; j++)
335            {
336                EvPtr->OwnerPid[j] = INVALID_PID;
337            }
338            EvPtr->OwnerPid[0] = mCurrentPid;
339            lld_init_wait_q (&(EvPtr->WaitQ));
340            *EvntId = (i+1);
341            return (OBJ_OK);
342        }
343    }
344    return (OBJ_MAX_OBJS);
345}
346
347/*^^***************************************************************************
348 * static DS_U32 EventWait (DS_U32 EvntId, DS_U32 Timeout, DS_U32 *TimeLeft,
349 *                          DS_U32 AutoReset)
350 *
351 * Description: Locks a event (decrement count) with a timeout
352 *
353 * Entry :  EvntId    = Returned by EventCreate
354 *          Timeout   = In 1/100 of a second increments.
355 *                      = 0 to return immidiately if the resource not available
356 *                      = 0xffffffff to wait forever on the resource
357 *          TimeLeft  = Pointer to DS_U32 to receive remaining timeout if the
358 *                      wait operation interrupted by a signal (if return value
359 *                      is OBJ_SIGNAL_RCV)
360 *          AutoReset = _TRUE_ to reset the event after receiving it
361 *
362 * Return:  OBJ_OK              Operation completed
363 *          OBJ_INVALID_ID      Invalid ev id or process does not own ev
364 *          OBJ_TIMEOUT         Timedout
365 *          OBJ_SIGNAL_RCV      Signal received
366 *
367 * Notes :  - If ev status = SIGNALED and AutoReset = _FALSE_, the function will
368 *            return immediately with OBJ_OK
369 *          - If ev status = SIGNALED and AutoReset = _TRUE_, Status will be set
370 *            to NOT_SIGNALED and the function will return with OBJ_OK
371 *          - If ev status = NOT_SIGNALED and timeout = 0, will return TIMEOUT
372 *          - If ev status = NOT_SIGNALED and timeout > 0, other processes will
373 *            be scheduled until either timeout is elapsed (return TIMEOUT),
374 *            the calling process detects that ev state > 0 (return OK) or the
375 *            process receives a signal (return SIGNAL_RCV)
376 *
377 *          **** VERY IMPORTANT ***
378 *          This locking mechanism does not support priority inversion since
379 *          linux does not support (_TRUE_) task priorities.
380 *
381 **************************************************************************^^*/
382static DS_U32 EventWait (DS_U32 EvntId, DS_U32 Timeout, DS_U32 *TimeLeft,
383                         DS_U32 AutoReset)
384{
385    DS_U32 i, Idx;
386    EVNT_STR *EvPtr;
387
388    while (_TRUE_)
389    {
390        /*===========================================
391         * Make sure ev still exist (not deleted)
392         *==========================================*/
393        EvPtr = GetEvPtr(EvntId, &Idx);
394        if (EvPtr == NULL)
395        {
396            return (OBJ_INVALID_ID);
397        }
398
399        /*==========================
400         * If event is signaled
401         *=========================*/
402        if (EvPtr->Status == SIGNALED)
403        {
404            if (AutoReset)
405            {
406                EvPtr->Status = NOT_SIGNALED;
407            }
408            return (OBJ_OK);
409        }
410
411        /*==================================
412         * If not signaled and timeout = 0
413         *=================================*/
414        if (Timeout == 0)
415        {
416            return (OBJ_TIMEOUT);
417        }
418
419        /*==============================================================
420         * If not signaled and timeout, wait signaled or timeout
421         *=============================================================*/
422        if (Timeout == OS_WAIT_FOREVER)
423        {
424            lld_wait_on_q (&(EvPtr->WaitQ));
425            i = Timeout;                        /* Any non zero value */
426        }
427        else
428        {
429            i = lld_timeout_wait_on_q (&(EvPtr->WaitQ), Timeout);
430        }
431        if (i == 0)
432        {
433            return (OBJ_TIMEOUT);
434        }
435        if (lld_os_signal_detected())
436        {
437            *TimeLeft = i;
438            return (OBJ_SIGNAL_RCV);
439        }
440        if (Timeout != OS_WAIT_FOREVER)
441        {
442            Timeout = i;
443        }
444    }
445}
446
447/*^^***************************************************************************
448 * static DS_U32 EventSet (DS_U32 EvntId)
449 *
450 * Description: Set event state to signaled
451 *
452 * Entry :  EvntId   = Returned by EventCreate
453 *
454 * Return:  OBJ_OK          Operation completed
455 *          OBJ_INVALID_ID  Invalid ev id or process does not own ev
456 *
457 * Notes:   
458 *
459 **************************************************************************^^*/
460static DS_U32 EventSet (DS_U32 EvntId)
461{
462    EVNT_STR *EvPtr;
463
464    EvPtr = GetEvPtr(EvntId, NULL);
465    if (EvPtr == NULL)
466    {
467        return (OBJ_INVALID_ID);
468    }
469    if (EvPtr->Status == NOT_SIGNALED)
470    {
471        EvPtr->Status = SIGNALED;
472        lld_wakeup_wait_q (&(EvPtr->WaitQ));
473    }
474    return (OBJ_OK);
475}
476
477/*^^***************************************************************************
478 * static DS_U32 EventReset (DS_U32 EvntId)
479 *
480 * Description: Set event to not signaled state
481 *
482 * Entry :  EvntId   = Returned by EventCreate
483 *
484 * Return:  OBJ_OK          Operation completed
485 *          OBJ_INVALID_ID  Invalid ev id or process does not own ev
486 *
487 * Notes:   
488 *
489 **************************************************************************^^*/
490static DS_U32 EventReset (DS_U32 EvntId)
491{
492    EVNT_STR *EvPtr;
493
494    EvPtr = GetEvPtr(EvntId, NULL);
495    if (EvPtr == NULL)
496    {
497        return (OBJ_INVALID_ID);
498    }
499    EvPtr->Status = NOT_SIGNALED;
500    return (OBJ_OK);
501}
502
503/*^^***************************************************************************
504 * static DS_U32 EventDelete (DS_U32 EvntId)
505 *
506 * Description: Deletes an event.
507 *
508 * Entry :  EvntId   = Returned by EventCreate
509 *
510 * Return:  OBJ_OK              Operation completed
511 *          OBJ_INVALID_ID      Invalid ev id or process does not own ev
512 *
513 * Notes:   The event will be deleted only if its reference count is 0.
514 *          All tasks waiting on the event will be unblocked with error
515 *          return code.
516 *          The only caveat here is:
517 *          If a taskA deletes a event while other task(s) are pending or
518 *          already locked it, and TaskA then creates another event before
519 *          the other tasks gets notified of the deleted event, it is
520 *          possible that the returned EvntId will be the same as the just
521 *          deleted event and hence other pending task(s) will continue to
522 *          run normally.
523 *
524 **************************************************************************^^*/
525static DS_U32 EventDelete (DS_U32 EvntId)
526{
527    DS_U32 i, j;
528    EVNT_STR *EvPtr;
529
530    EvPtr = GetEvPtr(EvntId, &j);
531    if (EvPtr == NULL)
532    {
533        return (OBJ_INVALID_ID);
534    }
535
536    /*======================================
537     * Remove process from owners list
538     *=====================================*/
539    EvPtr->OwnerPid[j] = INVALID_PID;
540
541    /*==================================================
542     * Check if other process still use the event
543     *=================================================*/
544    j = 0;
545    for (i=0; i<MAX_NOF_PROCS; i++)
546    {
547        if (EvPtr->OwnerPid[i] != INVALID_PID)
548        {
549            j = 1;                          /* Other process is using it */
550            break;
551        }
552    }
553
554    /*================================================
555     * If no other process is using the event
556     *===============================================*/
557    if (j == 0)
558    {
559        EvPtr->Status = UNUSED_EVENT;
560    }
561
562    /*======================================
563     * Awake all tasks waiting on the ev
564     *=====================================*/
565    lld_wakeup_wait_q (&(EvPtr->WaitQ));
566    return (OBJ_OK);
567}
568
569/*^^***************************************************************************
570 * static DS_U32 EventInfo (DS_U32 EvntId, DS_U32 *Size, void *Dest)
571 *
572 * Description: Return a copy of kernel structure for a event.
573 *
574 * Entry :  EvntId   = User mode ev ID
575 *          Size    = Pointer to receive size of ev structure
576 *          Dest    = Area to copy ev info to
577 *
578 * Return: 
579 *
580 * Notes:   This fucntion is provided for diagnostic purpose only.
581 *
582 **************************************************************************^^*/
583static DS_U32 EventInfo (DS_U32 EvntId, DS_U32 *Size, void *Dest)
584{
585    EVNT_STR *EvPtr;
586
587    EvntId--;
588    if ((EvntId >= MAX_NOF_EVENTS) || (EventsPtr == NULL))
589    {
590        return (OBJ_INVALID_ID);
591    }
592    EvPtr = EventPtr(EvntId);
593    *Size = sizeof (EVNT_STR);
594    lld_os_copy_to_user(Dest, (DS_S8 *)EvPtr, sizeof(EVNT_STR));
595    return (OBJ_OK);
596}
597
598/*^^***************************************************************************
599 * static EVNT_STR *GetEvPtr (DS_U32 EvntId, DS_U32 *ProcIndex)
600 *
601 * Description: Find event corresponding to a ev ID and process ID
602 *
603 * Entry :  EvntId       = User mode ev ID
604 *          ProcIndex   = Ptr to receive process index in OwnerPid array or
605 *                        NULL if not needed
606 *
607 * Return:  Pointer to event struc or NULL
608 *
609 * Notes:   This call will fail if the event does not exist or if
610 *          the caller process did not create the event.
611 *
612 **************************************************************************^^*/
613static EVNT_STR *GetEvPtr (DS_U32 EvntId, DS_U32 *ProcIndex)
614{
615    EVNT_STR *EvPtr;
616    DS_U32  i, ProcId;
617
618    EvntId--;
619    if ((EvntId >= MAX_NOF_EVENTS) || (EventsPtr == NULL))
620    {
621        return (NULL);
622    }
623    ProcId = mCurrentPid;                  /* Current process ID */
624    EvPtr = EventPtr(EvntId);
625    if (EvPtr->Status == UNUSED_EVENT)
626    {
627        return (NULL);
628    }
629    for (i=0; i<MAX_NOF_PROCS; i++)
630    {
631        if (EvPtr->OwnerPid[i] == ProcId)
632        {
633            if (ProcIndex != NULL)
634            {
635                *ProcIndex = i;
636            }
637            return (EvPtr);
638        }
639    }
640    return (NULL);
641}
Note: See TracBrowser for help on using the repository browser.