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

📄 mqueue.cxx

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 CXX
📖 第 1 页 / 共 3 页
字号:
        mqtab[i].msgsize = attr->mq_msgsize;
        mqtab[i].unlinkme = false;
#ifdef CYGFUN_POSIX_MQUEUE_NOTIFY
        mqtab[i].sigev = NULL;
#endif
        strncpy( mqtab[i].name, name, PATH_MAX );

        // initialize first mqtab[i].users
        mqtab[i].users->next = NULL;
        // set the mode for later, but also note that O_NONBLOCK can
        // be set in oflags *or* the attr the user passed
        mqtab[i].users->flags = oflag | (attr->mq_flags & O_NONBLOCK);

        // set back pointer so that message queue handle can find actual queue
        mqtab[i].users->tabent = &mqtab[i]; 
        
        mqtab[i].users->notifieruser = false;

#ifdef CYGIMP_POSIX_MQUEUE_VALIDATE_DESCRIPTOR
        mqtab[i].users->magic = MQ_VALID_MAGIC; // now valid
#endif
        
        retval=(mqd_t)mqtab[i].users;

        goto exit_unlock;
    } // if (NULL == qtabent)

    // so we're not creating, and we have a valid qtabent

    // But this qtabent may be being unlinked. If so, we are permitted
    // to return an error, so we will. (see under mq_unlink() in POSIX)
    // Which error though? EINVAL seems best, but POSIX doesn't say :-/

    if (true == qtabent->unlinkme) {
        errno = EINVAL;
        retval = (mqd_t)-1;
        goto exit_unlock;
    }
    
    // now we have a usable qtabent

    struct mquser *user;
    user = (struct mquser *) malloc( sizeof(struct mquser) );
    if ( NULL == user ) {
            errno = ENOSPC;
            retval = (mqd_t)-1;
            goto exit_unlock;
    }

    // prepend to qtab user list
    user->next = qtabent->users;
    qtabent->users = user;

    // set back pointer so that message queue handle can find actual queue
    user->tabent = qtabent;

    user->flags = oflag;

#ifdef CYGIMP_POSIX_MQUEUE_VALIDATE_DESCRIPTOR
    user->magic = MQ_VALID_MAGIC; // now valid
#endif

    retval=(mqd_t)user;

 exit_unlock:
    interr = pthread_mutex_unlock( &mqtab_mut );
    // should never fail
    CYG_ASSERT( interr == 0, "internal lock failed!" );
    CYG_REPORT_RETVAL( retval );
    return retval;
} // mq_open()

//------------------------------------------------------------------------

// NOTE: It is the *user*'s responsibility to ensure that nothing is
// blocked in mq_send() or mq_receive() when closing the queue with
// that descriptor. The standard does not specify the behaviour, so that's
// what I am assuming

externC int
mq_close( mqd_t mqdes )
{
    CYG_REPORT_FUNCTYPE( "returning %d" );
    CYG_REPORT_FUNCARG1XV( mqdes );
    
    struct mquser *user = (struct mquser *)mqdes;

#ifdef CYGIMP_POSIX_MQUEUE_VALIDATE_DESCRIPTOR
    if ( user->magic != MQ_VALID_MAGIC ) {
        errno  = EBADF;
        CYG_REPORT_RETVAL( -1 );
        return -1;
    }
#endif
    
    int interr;

    interr = pthread_mutex_lock( &mqtab_mut );
    // should never fail
    CYG_ASSERT( interr == 0, "internal lock failed!" );

    struct mqtabent *tabent = user->tabent;
    struct mquser *usertmp;
    
    // perhaps should return EBADF instead of assert?
    CYG_ASSERT( tabent->users != NULL, "Null message queue user list" );

#ifdef CYGFUN_POSIX_MQUEUE_NOTIFY
    // deregister notification iff this was the message queue descriptor
    // that was used to register it (POSIX says)
    if ( true == user->notifieruser ) {
        tabent->mq->setnotify( NULL, 0 );
        tabent->sigev = NULL;
        // not worth clearing notifieruser
    }
#endif

    // find in the list for this queue and remove - sucks a bit, but seems
    // best over all - the list shouldn't be too long
    if ( tabent->users == user ) {
        tabent->users = user->next;  // remove
    } else {
        for ( usertmp=tabent->users;
              NULL != usertmp->next;
              usertmp = usertmp->next ) {
            if ( usertmp->next == user )
                break;
        } // for

        // perhaps should return EBADF instead of assert?
        CYG_ASSERT( usertmp->next != NULL, "Couldn't find message queue user" );

        usertmp->next = user->next; // remove
    } // else
    
#ifdef CYGIMP_POSIX_MQUEUE_VALIDATE_DESCRIPTOR
    user->magic = 0; // invalidate
#endif

    // free it up
    free( user );

    if ( (true == tabent->unlinkme) && (NULL == tabent->users) ) {
        do_mq_unlink( tabent );
    } // if

    interr = pthread_mutex_unlock( &mqtab_mut );
    // should never fail
    CYG_ASSERT( interr == 0, "internal lock failed!" );
    CYG_REPORT_RETVAL( 0 );
    return 0;
} // mq_close()


//------------------------------------------------------------------------

externC int
mq_unlink( const char *name )
{
    CYG_REPORT_FUNCTYPE( "returning %d" );
    CYG_REPORT_FUNCARG1( "name=%s", name );

    int retval, interr;
    cyg_ucount32 i;
    struct mqtabent *qtabent=NULL;

    interr = pthread_mutex_lock( &mqtab_mut );
    // should never fail
    CYG_ASSERT( interr == 0, "internal lock failed!" );

    // find the entry first
    // FIXME: Should check for length and return ENAMETOOLONG
    for ( i=0; i < CYGNUM_POSIX_MQUEUE_OPEN_MAX; i++ ) {
        if ( 0 == strncmp(name, mqtab[i].name, PATH_MAX) ) {
            qtabent = &mqtab[i];
            break;
        } // if
    } // for

    if ( NULL == qtabent ) { // not found
        errno = ENOENT;
        retval = -1;
        goto exit_unlock;
    }

    if ( NULL != qtabent->users ) {   // still in use
        qtabent->unlinkme = true;     // so mark it as pending deletion
    } else {
        do_mq_unlink( qtabent );
    } // else

    retval = 0;

 exit_unlock:
    interr = pthread_mutex_unlock( &mqtab_mut );
    // should never fail
    CYG_ASSERT( interr == 0, "internal lock failed!" );
    CYG_REPORT_RETVAL( retval );
    return retval;
} // mq_unlink()

//------------------------------------------------------------------------

externC int
mq_send( mqd_t mqdes, const char *msg_ptr, size_t msg_len,
         unsigned int msg_prio )
{
    CYG_REPORT_FUNCTYPE( "returning %d" );
    CYG_REPORT_FUNCARG4( "mqdes=%08x, msg_ptr=%08x, msg_len=%u, msg_prio=%u",
                         mqdes, msg_ptr, msg_len, msg_prio );
    CYG_CHECK_DATA_PTRC( msg_ptr );
    
    struct mquser *user = (struct mquser *)mqdes;
    struct mqtabent *tabent = user->tabent;

#ifdef CYGIMP_POSIX_MQUEUE_VALIDATE_DESCRIPTOR
    if ( user->magic != MQ_VALID_MAGIC ) {
        errno  = EBADF;
        CYG_REPORT_RETVAL( -1 );
        return -1;
    }
#endif
    
    if ( msg_len > (size_t)tabent->msgsize ) {
        errno = EMSGSIZE;
        CYG_REPORT_RETVAL( -1 );
        return -1;
    }

    if ( msg_prio > MQ_PRIO_MAX ) {
        errno = EINVAL;
        CYG_REPORT_RETVAL( -1 );
        return -1;
    }

    if ( (O_WRONLY != (user->flags & O_WRONLY)) && 
         (O_RDWR != (user->flags & O_RDWR)) ) {
        errno = EBADF;
        CYG_REPORT_RETVAL( -1 );
        return -1;
    }

    // go for it
    Cyg_Mqueue::qerr_t err;
    err = tabent->mq->put( msg_ptr, msg_len, msg_prio,
                           ((user->flags & O_NONBLOCK) != O_NONBLOCK) );
    switch (err) {

    case Cyg_Mqueue::INTR:
        errno = EINTR;
        CYG_REPORT_RETVAL( -1 );
        return -1;

    case Cyg_Mqueue::WOULDBLOCK:
        CYG_ASSERT( (user->flags & O_NONBLOCK) == O_NONBLOCK,
                    "Message queue assumed non-blocking when blocking requested"
            );
        errno = EAGAIN;
        CYG_REPORT_RETVAL( -1 );
        return -1;
        
    case Cyg_Mqueue::OK:
        CYG_REPORT_RETVAL( 0 );
        return 0;

    default:
        CYG_FAIL( "unhandled message queue return code" );
        return -1; // keep compiler happy
    } // switch
} // mq_send()

//------------------------------------------------------------------------


externC ssize_t
mq_receive( mqd_t mqdes, char *msg_ptr, size_t msg_len,
            unsigned int *msg_prio )
{
    CYG_REPORT_FUNCTYPE( "returning %ld" );
    CYG_REPORT_FUNCARG4( "mqdes=%08x, msg_ptr=%08x, msg_len=%u, msg_prio=%08x",
                         mqdes, msg_ptr, msg_len, msg_prio );
    CYG_CHECK_DATA_PTRC( msg_ptr );
    CYG_CHECK_DATA_PTRC( msg_ptr+msg_len-1 );
    if ( NULL != msg_prio )
        CYG_CHECK_DATA_PTRC( msg_prio );
    
    
    struct mquser *user = (struct mquser *)mqdes;
    struct mqtabent *tabent = user->tabent;

#ifdef CYGIMP_POSIX_MQUEUE_VALIDATE_DESCRIPTOR
    if ( user->magic != MQ_VALID_MAGIC ) {
        errno  = EBADF;
        CYG_REPORT_RETVAL( -1 );
        return (ssize_t)-1;
    }
#endif
    
    if ( (O_RDONLY != (user->flags & O_RDONLY)) && 
         (O_RDWR != (user->flags & O_RDWR)) ) {
        errno = EBADF;
        CYG_REPORT_RETVAL( -1 );
        return (ssize_t)-1;
    }

    if ( msg_len < (size_t)tabent->msgsize ) {
        errno = EMSGSIZE;
        CYG_REPORT_RETVAL( -1 );
        return (ssize_t)-1;
    }

    // go for it
    Cyg_Mqueue::qerr_t err;
    err = tabent->mq->get( msg_ptr, &msg_len, msg_prio,
                           ((user->flags & O_NONBLOCK) != O_NONBLOCK) );
    switch (err) {

    case Cyg_Mqueue::INTR:
        errno = EINTR;
        CYG_REPORT_RETVAL( -1 );
        return (ssize_t)-1;

    case Cyg_Mqueue::WOULDBLOCK:
        CYG_ASSERT( (user->flags & O_NONBLOCK) == O_NONBLOCK,
                    "Message queue assumed non-blocking when blocking requested"
            );
        errno = EAGAIN;
        CYG_REPORT_RETVAL( -1 );
        return (ssize_t)-1;
        
    case Cyg_Mqueue::OK:
        CYG_ASSERT( msg_len <= (size_t)tabent->msgsize,
                    "returned message too long" );
        if ( NULL != msg_prio )
            CYG_ASSERT( *msg_prio <= MQ_PRIO_MAX,
                        "returned message has invalid priority" );

⌨️ 快捷键说明

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