📄 mqueue.inl
字号:
#ifndef CYGONCE_KERNEL_MQUEUE_INL#define CYGONCE_KERNEL_MQUEUE_INL/*========================================================================//// mqueue.inl//// Message queues implementation////========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): jlarmour// Contributors: // Date: 2000-05-09// Purpose: This file provides the implementation for eCos message// queues// Description: This differs from the message boxes also supported// by eCos primarily because the requirements of message// queues are driven by POSIX semantics. POSIX semantics are// more dynamic and therefore heavyweight than Mboxes,// including prioritization, and variable sized queues and// message lengths// Usage: Do not include this file directly - instead// #include <cyg/kernel/mqueue.hxx>////####DESCRIPTIONEND####////======================================================================*//* CONFIGURATION */#include <pkgconf/system.h>#include <pkgconf/kernel.h> // Configuration header/* INCLUDES */#include <stddef.h> // size_t, NULL#include <cyg/infra/cyg_type.h> // Types#include <cyg/kernel/mqueue.hxx> // Header for this file, just in case#include <cyg/infra/cyg_ass.h> // Assertion support#include <cyg/infra/cyg_trac.h> // Tracing support#include <cyg/kernel/sched.hxx> // scheduler#include <cyg/kernel/sched.inl> // scheduler inlines#include <cyg/kernel/sema.hxx> // Cyg_Counting_Semaphore#ifdef CYGPKG_ISOINFRA# include <string.h> // memcpy#elseexternC void * memcpy( void *, const void *, size_t );#endif// NOTE:// An alternative implementation based on mutexes and condition variables// rather than semaphores/scheduler locking was considered. But it was// not thought quite as good because it isn't driver safe. You would// also have to manage explicitly what counting semaphores do for you// intrinsically. Also with the mutex approach, the message queue would// be locked the whole time a new entry was being filled in, or copied out//// It also makes the non-blocking case properly non-blocking rather than// still being able to block while waiting for a mutex protecting// the message queue internal structures/* INLINE FUNCTIONS */#ifndef CYGPRI_KERNEL_SYNCH_MQUEUE_INLINE# define CYGPRI_KERNEL_SYNCH_MQUEUE_INLINE inline#endif//------------------------------------------------------------------------CYGPRI_KERNEL_SYNCH_MQUEUE_INLINE cyg_boolCyg_Mqueue::check_this( cyg_assert_class_zeal zeal ) const{ if (zeal != cyg_none) { CYG_CHECK_DATA_PTRC(this); // extreme paranoia#ifdef CYGDBG_USE_ASSERTS if ( qlen <= 0 || msgsize <= 0 ) return false;#endif if ( queuespacesize < sizeof(struct qentry)+1 ) return false; CYG_CHECK_DATA_PTRC(queuespace); CYG_CHECK_FUNC_PTRC(free_fn); // prevent pre-emption through this. Not so bad since // this is only a diagnostic function Cyg_Scheduler::lock(); if (NULL != q) CYG_CHECK_DATA_PTRC(q); if (NULL != freelist) CYG_CHECK_DATA_PTRC(freelist); if (NULL != callback) CYG_CHECK_FUNC_PTRC(callback); // check each queue entry long msgs=0, busymsgs=0; unsigned int oldprio=0; struct qentry *qtmp; if ( NULL != q ) oldprio = q->priority; for ( qtmp=q; NULL != qtmp; qtmp=qtmp->next ) { if ( NULL != qtmp->next ) CYG_CHECK_DATA_PTRC( qtmp->next ); // queue should be priority ordered if ( qtmp->priority > oldprio ) goto fail; oldprio = qtmp->priority; #ifdef CYGDBG_USE_ASSERTS // valid length if ( !qtmp->busy ) if ( qtmp->buflen > msgsize ) goto fail;#endif if ( qtmp->busy ) busymsgs++; else msgs++; } // for long freemsgs=0; // check that number of used and unused messages == q length for ( qtmp=freelist; NULL != qtmp; qtmp=qtmp->next ) { if ( NULL != qtmp->next ) CYG_CHECK_DATA_PTRC( qtmp->next ); if ( qtmp->busy ) busymsgs++; else freemsgs++; }#ifdef CYGDBG_USE_ASSERTS // and sum of all messages should be the total q length if ( qlen != (msgs+freemsgs+busymsgs) ) goto fail;#endif Cyg_Scheduler::unlock(); } return true; // object OK fail: Cyg_Scheduler::unlock(); return false; // object fubar'd}//------------------------------------------------------------------------CYGPRI_KERNEL_SYNCH_MQUEUE_INLINECyg_Mqueue::Cyg_Mqueue( long maxmsgs, long maxmsgsize, qalloc_fn_t qalloc, qfree_fn_t qfree, qerr_t *err ) : putsem(maxmsgs), getsem(0){ CYG_REPORT_FUNCTION(); CYG_REPORT_FUNCARG5( "maxmsgs=%ld, maxmsgsize=%ld, qalloc=%08x, " "qfree=%08x, &err=%08x", maxmsgs, maxmsgsize, qalloc, qfree, err); CYG_PRECONDITIONC( (maxmsgs > 0) && (maxmsgsize > 0) ); CYG_CHECK_DATA_PTRC( err ); CYG_CHECK_FUNC_PTRC( qalloc ); CYG_CHECK_FUNC_PTRC( qfree ); // mem to allocate for entire queue size. Also wants to be rounded // up so that the structs are aligned. const long addralign = sizeof(void *) - 1; long entrysize = (sizeof(struct qentry) + maxmsgsize + addralign) & ~addralign; queuespacesize = entrysize * maxmsgs; queuespace = qalloc( queuespacesize ); if (NULL == queuespace) { *err=NOMEM; CYG_REPORT_RETURN(); return; } // link up freelist long i; struct qentry *qtmp; for ( i=0, qtmp=(struct qentry *)queuespace; i<maxmsgs-1; i++, qtmp=qtmp->next ) { qtmp->busy = false; qtmp->next = (struct qentry *)((char *)qtmp + entrysize); } // for freelist = (struct qentry *)queuespace; // set the last entry in the chain to the start to make the list circular qtmp->next = NULL; qtmp->busy = false; callback = NULL; q = NULL; free_fn = qfree;#ifdef CYGDBG_USE_ASSERTS qlen = maxmsgs; msgsize = maxmsgsize;#endif *err = OK; // object should be valid now CYG_ASSERT_THISC(); CYG_REPORT_RETURN();}//------------------------------------------------------------------------CYGPRI_KERNEL_SYNCH_MQUEUE_INLINECyg_Mqueue::~Cyg_Mqueue(){ CYG_REPORT_FUNCTION(); if ( NULL != queuespace ) { // object should be valid if queuespace was successfully allocated CYG_ASSERT_THISC(); free_fn( queuespace, queuespacesize ); }#ifdef CYGDBG_USE_ASSERTS qlen = msgsize = 0; // deliberately make it fail check_this() if used#endif CYG_REPORT_RETURN();}//------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -