⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 event.c

📁 linux环境支持psos的操作系统。非常适合进行移植的朋友。
💻 C
字号:
/***************************************************************************** * event.c - defines the wrapper functions and data structures needed *           to implement a Wind River pSOS+ (R) task event flag API  *           in a POSIX Threads environment.
 ****************************************************************************/#include <errno.h>#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <signal.h>#include <sys/time.h>#include "p2pthread.h"#undef DIAG_PRINTFS#define EV_NOWAIT    0x01#define EV_ANY       0x02#define ERR_TIMEOUT  0x01#define ERR_NODENO   0x04#define ERR_OBJDEL   0x05#define ERR_OBJTFULL 0x08#define ERR_OBJNF    0x09#define ERR_NOEVS    0x3C/*******************************************************************************  External function and data references*****************************************************************************/extern void   sched_lock( void );extern void   sched_unlock( void );extern p2pthread_cb_t *   my_tcb( void );extern p2pthread_cb_t *   tcb_for( ULONG taskid );/******************************************************************************* ev_send - sets the specified flag bits in a p2pthread task event group*****************************************************************************/ULONG   ev_send( ULONG taskid, ULONG new_events ){#ifdef DIAG_PRINTFS     p2pthread_cb_t *our_tcb;#endif    p2pthread_cb_t *tcb;    ULONG old_flags;    ULONG error;    error = ERR_NO_ERROR;    if ( (tcb = tcb_for( taskid )) != (p2pthread_cb_t *)NULL )    {        /*        **  'Lock the p2pthread scheduler' to defer any context switch to a        **  higher priority task until after this call has completed its work.        */        sched_lock();        /*        **  Lock mutex for event post        */        pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock,                              (void *)&(tcb->event_lock));        pthread_mutex_lock( &(tcb->event_lock) );        /*        **  Get the state of the flag bits prior to the send operation        */        old_flags = tcb->events_pending;#ifdef DIAG_PRINTFS         printf( "\r\nevent flags @ tcb %p new %lx pending %lx captured %lx",                tcb, new_events, tcb->events_pending, tcb->events_captured );#endif        /*        **  If requested to set any flags which were not already set,        */         if ( (old_flags & new_events) != new_events )        {            /*            **  Set the flag bits specified by the caller            */            tcb->events_pending = old_flags | new_events;#ifdef DIAG_PRINTFS         printf( "\r\nsignalling new event flags %lx @ tcb %p",                new_events, tcb );#endif            /*            **  Signal the condition variable for the event            */            pthread_cond_broadcast( &(tcb->event_change) );        }        /*        **  Unlock the event mutex.         */        pthread_mutex_unlock( &(tcb->event_lock) );        pthread_cleanup_pop( 0 );        /*        **  'Unlock the p2pthread scheduler' to enable a possible context switch        **  to a task made runnable by this call.        */        sched_unlock();#ifdef DIAG_PRINTFS         our_tcb = my_tcb();        printf( "\r\ntask @ %p sent event flags %lx @ tcb %p",                our_tcb, new_events, tcb );#endif    }    else    {        error = ERR_OBJDEL;    }    return( error );}/******************************************************************************* events_match_mask - compares the specified set of event flags against**                     the specified event combination and returns a boolean**                     TRUE/FALSE result.*****************************************************************************/static int    events_match_mask( p2pthread_cb_t *tcb, ULONG rule ){    int match;    ULONG still_pending;    /*    **  Save a mask of events already captured when the new pending events    **  arrived. Note: we induct events_captured member here because of we 
    **  have to test the condition of (rule & EV_ALL).    */    still_pending = tcb->events_captured;    /*    **  Capture any newly-arrived pending events which are wanted.    **  These events will be accumulated until the match rule is satisfied.    */    tcb->events_captured |= (tcb->events_pending & tcb->event_mask);    /*    **  Clear any events just captured from the pending list.  Any events    **  which had previously been captured and had occurred again are left    **  pending.    */    tcb->events_pending &= ((~tcb->event_mask) | still_pending);    /*    **  Now see if the match rule has been satisfied by captured events.    */

    /*
	**  Note: i have modified this line to suit for rule == 
	**  EV_ANY | EV_NOWAIT or EV_ANY |EV_WAIT condition.
	**  The origin statement here is "if ( rule == EV_ANY )"
	*/
	if ( rule & EV_ANY )    // if ( rule == EV_ANY )    {        /* ANY rule... any event matching a bit in mask awakens task */        if ( (tcb->events_captured & tcb->event_mask) != 0L )            match = TRUE;
		else 
		    match = FALSE;#ifdef DIAG_PRINTFS         printf( "\r\nmatch any event @ tcb %p mask %lx pending %lx captured %lx",                tcb, tcb->event_mask, tcb->events_pending,                tcb->events_captured );#endif    }    else
    {        /* ALL rule... all bits in mask must be matched by events */        if ( (tcb->events_captured & tcb->event_mask) == tcb->event_mask )            match = TRUE;
		else 
		    match = FALSE;
#ifdef DIAG_PRINTFS         printf( "\r\nmatch all events @ tcb %p mask %lx pending %lx captured %lx",                tcb, tcb->event_mask, tcb->events_pending,                tcb->events_captured );#endif    }    return( match );}/******************************************************************************* ev_receive - blocks the calling task until a matching combination of events**            occurs in the specified p2pthread event flag group.*****************************************************************************/ULONG   ev_receive( ULONG mask, ULONG opt, ULONG max_wait, ULONG *captured ){    p2pthread_cb_t *tcb;    struct timeval now;    struct timespec timeout;    int retcode;    long sec, usec;    ULONG error;    error = ERR_NO_ERROR;    /*    **  Get tcb for task    */    tcb = my_tcb();    /*    **  Save event mask in TCB, Note: there is no locking here 
    **  since only in my own pthread i change this member.    */
    tcb->event_mask = mask;#ifdef DIAG_PRINTFS     printf( "\r\ntask @ %p pend on event flags %lx", tcb, mask );#endif    /*    ** Lock mutex for event pend.    */    pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock,                          (void *)&(tcb->event_lock));    pthread_mutex_lock( &(tcb->event_lock) );    retcode = 0;    if ( opt & EV_NOWAIT )    {        /*        **  Caller specified no wait on events...        **  Check the condition variable with an immediate timeout.        */            gettimeofday( &now, (struct timezone *)NULL );            timeout.tv_sec = now.tv_sec;            timeout.tv_nsec = now.tv_usec * 1000;            while ( !(events_match_mask( tcb, opt )) &&                    (retcode != ETIMEDOUT) )            {                retcode = pthread_cond_timedwait( &(tcb->event_change),                                              &(tcb->event_lock), &timeout );            }    }    else    {        /*        **  Caller expects to wait on events, with or without a timeout.        */        if ( max_wait == 0L )        {            /*            **  Infinite wait was specified... wait without timeout,            **  The loop is required since the task may be awakened             **  by signals for events which do not match, or for            **  signals other than from a send to the event flags.            */            while ( !(events_match_mask( tcb, opt )) )            {                pthread_cond_wait( &(tcb->event_change),                                   &(tcb->event_lock) );            }        }        else        {            /*            **  Calculate timeout delay in seconds and microseconds            */            sec = 0;            usec = max_wait * P2PT_TICK * 1000;                gettimeofday( &now, (struct timezone *)NULL );            usec += now.tv_usec;            if ( usec > 1000000 )            {                sec = usec / 1000000;                usec = usec % 1000000;            }            timeout.tv_sec = now.tv_sec + sec;            timeout.tv_nsec = usec * 1000;            /*            **  Wait for an event match for the current task or for the            **  timeout to expire.  The loop is required since the task may            **  be awakened by signals for events which do not match, or            **  for signals other than from a send to the event flags (some 
            **  other signals also may cause pthread_cond_timedwait() to 
            **  premature return, see p2linux.pdf).            */            while ( !(events_match_mask( tcb, opt )) &&                    (retcode != ETIMEDOUT) )            {                retcode = pthread_cond_timedwait( &(tcb->event_change),                                                  &(tcb->event_lock),                                                  &timeout );            }        }    }    /*    **  Return a list of captured events to the caller.    */    if ( captured != (ULONG *)NULL )        *captured = tcb->events_captured;    /*    **  See if we timed out or if we got an event match    */    if ( retcode == ETIMEDOUT )    {        /*        **  Timed out without an event match        */        if ( opt & EV_NOWAIT )            error = ERR_NOEVS;        else            error = ERR_TIMEOUT;#ifdef DIAG_PRINTFS         printf( "...timed out" );#endif    }    else    {        /*        **  An event match occurred... Clear the accumulated captured events.        */#ifdef DIAG_PRINTFS         printf( "\r\ntask @ %p captured events %lx", tcb,                tcb->events_captured );#endif        tcb->events_captured = (ULONG)NULL;    }    /*    **  Unlock the mutex for the condition variable and clean up.    */    pthread_mutex_unlock( &(tcb->event_lock) );    pthread_cleanup_pop( 0 );    return( error );}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -