Index: compat/posix/current/ChangeLog =================================================================== RCS file: /cvs/ecos/ecos/packages/compat/posix/current/ChangeLog,v retrieving revision 1.31 diff -u -5 -p -r1.31 ChangeLog --- compat/posix/current/ChangeLog 10 Dec 2002 02:28:21 -0000 1.31 +++ compat/posix/current/ChangeLog 21 Jan 2003 19:27:02 -0000 @@ -1,5 +1,31 @@ +2003-01-19 Dmitriy Korovkin + * src/sem.cxx (sem_timedwait): New function. Implementing POSIX + 1003.1d draft definition. + * include/semaphore.h: Ditto + * doc/posix.sgml: Documented. + + * src/mutex.cxx (pthread_mutex_timedlock): New function. Implementing + POSIX 1003.1d draft definition. + * include/mutex.hxx: Ditto + * doc/posix.sgml: Documented. + + +2003-01-13 Jonathan Larmour + + * doc/posix.sgml: Document them. + + * src/mqueue.cxx (mq_timedreceive): Make fully compliant by dealing + with bogus timeouts. + (mq_timedsend): Ditto. + +2003-01-13 Dmitriy Korovkin + + * src/mqueue.cxx (mq_timedsend): New function. Implementing POSIX + 1003.1d draft definition. + (mq_timedreceive): Ditto. + 2002-12-10 Wade Jensen 2002-12-10 Jonathan Larmour * src/mutex.cxx (pthread_cond_timedwait): Initialize clock converters only once ever. Index: compat/posix/current/doc/posix.sgml =================================================================== RCS file: /cvs/ecos/ecos/packages/compat/posix/current/doc/posix.sgml,v retrieving revision 1.2 diff -u -5 -p -r1.2 posix.sgml --- compat/posix/current/doc/posix.sgml 15 Sep 2002 22:09:21 -0000 1.2 +++ compat/posix/current/doc/posix.sgml 21 Jan 2003 19:27:03 -0000 @@ -746,10 +746,17 @@ int pthread_cond_wait(pthr pthread_mutex_t *mutex); int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime); +From POSIX 1003.1d draft: + +int sem_timedwait(sem_t *sem, + const struct timespec *abs_timeout); +int pthread_mutex_lock(pthread_mutex_t *mutex, + const struct timespec *abs_timeout); + @@ -1113,10 +1120,19 @@ ssize_t mq_receive( mqd&lo size_t msg_len, unsigned int *msg_prio ); int mq_setattr( mqd_t mqdes, const struct mq_attr *mqstat, struct mq_attr *omqstat ); int mq_getattr( mqd_t mqdes, struct mq_attr *mqstat ); int mq_notify( mqd_t mqdes, const struct sigevent *notification ); + +From POSIX 1003.1d draft: + +int mq_timedsend( mqd_t mqdes, const char *msg_ptr, + size_t msg_len, unsigned int msg_prio, + const struct timespec *abs_timeout ); +ssize_t mq_timedreceive( mqd_t mqdes, char *msg_ptr, + size_t msg_len, unsigned int *msg_prio, + const struct timespec *abs_timeout ); Index: compat/posix/current/include/mutex.h =================================================================== RCS file: /cvs/ecos/ecos/packages/compat/posix/current/include/mutex.h,v retrieving revision 1.3 diff -u -5 -p -r1.3 mutex.h --- compat/posix/current/include/mutex.h 23 May 2002 22:59:56 -0000 1.3 +++ compat/posix/current/include/mutex.h 21 Jan 2003 19:27:03 -0000 @@ -115,10 +115,19 @@ externC int pthread_mutex_init (pthread_ externC int pthread_mutex_destroy (pthread_mutex_t *mutex); // Lock mutex, waiting for it if necessary. externC int pthread_mutex_lock (pthread_mutex_t *mutex); +#ifdef CYGFUN_KERNEL_THREADS_TIMER +/* POSIX 1003.1d Draft functions - FIXME: should be conditionalized */ +// Lock mutex, waiting for it if necessary for a timeout. +struct timespec; /* forward declaration */ + +externC int pthread_mutex_timedlock (pthread_mutex_t *mutex, + const struct timespec *abs_timeout); +#endif + // Try to lock mutex. externC int pthread_mutex_trylock (pthread_mutex_t *mutex); // Unlock mutex. Index: compat/posix/current/include/semaphore.h =================================================================== RCS file: /cvs/ecos/ecos/packages/compat/posix/current/include/semaphore.h,v retrieving revision 1.3 diff -u -5 -p -r1.3 semaphore.h --- compat/posix/current/include/semaphore.h 23 May 2002 22:59:57 -0000 1.3 +++ compat/posix/current/include/semaphore.h 21 Jan 2003 19:27:03 -0000 @@ -93,10 +93,18 @@ externC int sem_init (sem_t *sem, int p externC int sem_destroy (sem_t *sem); // Decrement value if >0 or wait for a post. externC int sem_wait (sem_t *sem); +#ifdef CYGFUN_KERNEL_THREADS_TIMER +/* POSIX 1003.1d Draft functions - FIXME: should be conditionalized */ +// Decrement value if >0 or wait for a post for a timeout. +struct timespec; /* forward declaration */ + +externC int sem_timedwait (sem_t *sem, const struct timespec *abs_timeout); +#endif + // Decrement value if >0, return -1 if not. externC int sem_trywait (sem_t *sem); // Increment value and wake a waiter if one is present. externC int sem_post (sem_t *sem); Index: compat/posix/current/src/mqueue.cxx =================================================================== RCS file: /cvs/ecos/ecos/packages/compat/posix/current/src/mqueue.cxx,v retrieving revision 1.5 diff -u -5 -p -r1.5 mqueue.cxx --- compat/posix/current/src/mqueue.cxx 23 May 2002 22:59:59 -0000 1.5 +++ compat/posix/current/src/mqueue.cxx 21 Jan 2003 19:27:03 -0000 @@ -82,11 +82,14 @@ #include // C++ new #ifdef CYGFUN_POSIX_MQUEUE_NOTIFY # include # include "pprivate.h" // cyg_sigqueue() #endif - +#ifdef CYGFUN_KERNEL_THREADS_TIMER +# include +# include "pprivate.h" // cyg_timespec_to_ticks() +#endif /* CONSTANTS */ #define MQ_VALID_MAGIC 0x6db256c1 @@ -669,11 +672,188 @@ mq_receive( mqd_t mqdes, char *msg_ptr, return (ssize_t)-1; // keep compiler happy } // switch } // mq_receive() + +//------------------------------------------------------------------------ +#ifdef CYGFUN_KERNEL_THREADS_TIMER +externC int +mq_timedsend( mqd_t mqdes, const char *msg_ptr, size_t msg_len, + unsigned int msg_prio, const struct timespec *abs_timeout) +{ + CYG_REPORT_FUNCTYPE( "returning %d" ); + CYG_REPORT_FUNCARG6( "mqdes=%08x, msg_ptr=%08x, msg_len=%u, msg_prio=%u, + abs_timeout = %lu, %ld", + mqdes, msg_ptr, msg_len, msg_prio, + abs_timeout->tv_sec, abs_timeout->tv_nsec); + 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; + bool nonblocking = ((user->flags & O_NONBLOCK) == O_NONBLOCK); + bool goodtimespec = valid_timespec(abs_timeout); + err = tabent->mq->put( msg_ptr, msg_len, msg_prio, + !nonblocking && goodtimespec, + cyg_timespec_to_ticks(abs_timeout)); + switch (err) { + + case Cyg_Mqueue::INTR: + errno = EINTR; + CYG_REPORT_RETVAL( -1 ); + return -1; + + case Cyg_Mqueue::WOULDBLOCK: + if (!goodtimespec) { + errno = EINVAL; + CYG_REPORT_RETVAL( -1 ); + return -1; + } + 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::TIMEOUT: + errno = ETIMEDOUT; + 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_timedsend() + +//------------------------------------------------------------------------ + + +externC ssize_t +mq_timedreceive( mqd_t mqdes, char *msg_ptr, size_t msg_len, + unsigned int *msg_prio, const struct timespec *abs_timeout) +{ + CYG_REPORT_FUNCTYPE( "returning %ld" ); + CYG_REPORT_FUNCARG6( "mqdes=%08x, msg_ptr=%08x, msg_len=%u, msg_prio=%08x, + abs_timeout = %lu, %ld", + mqdes, msg_ptr, msg_len, msg_prio, + abs_timeout->tv_sec, abs_timeout->tv_nsec ); + 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; + bool nonblocking = ((user->flags & O_NONBLOCK) == O_NONBLOCK); + bool goodtimespec = valid_timespec(abs_timeout); + err = tabent->mq->get( msg_ptr, &msg_len, msg_prio, + !nonblocking && goodtimespec, + cyg_timespec_to_ticks(abs_timeout) ); + switch (err) { + + case Cyg_Mqueue::INTR: + errno = EINTR; + CYG_REPORT_RETVAL( -1 ); + return (ssize_t)-1; + + case Cyg_Mqueue::WOULDBLOCK: + if (!goodtimespec) { + errno = EINVAL; + CYG_REPORT_RETVAL( -1 ); + return -1; + } + 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::TIMEOUT: + errno = ETIMEDOUT; + CYG_REPORT_RETVAL( -1 ); + return -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" ); + CYG_REPORT_RETVAL( msg_len ); + return (ssize_t)msg_len; + + default: + CYG_FAIL( "unhandled message queue return code" ); + return (ssize_t)-1; // keep compiler happy + } // switch + +} // mq_timedreceive() + //------------------------------------------------------------------------ +#endif #ifdef CYGFUN_POSIX_MQUEUE_NOTIFY externC int mq_notify( mqd_t mqdes, const struct sigevent *notification ) Index: compat/posix/current/src/mutex.cxx =================================================================== RCS file: /cvs/ecos/ecos/packages/compat/posix/current/src/mutex.cxx,v retrieving revision 1.4 diff -u -5 -p -r1.4 mutex.cxx --- compat/posix/current/src/mutex.cxx 10 Dec 2002 02:28:21 -0000 1.4 +++ compat/posix/current/src/mutex.cxx 21 Jan 2003 19:27:03 -0000 @@ -64,10 +64,13 @@ #include // mutex definitions #include // clock definitions #include #include // thread inlines +#ifdef CYGFUN_KERNEL_THREADS_TIMER +#include +#endif //----------------------------------------------------------------------------- // new operator to allow us to construct mutex objects inline void *operator new(size_t size, cyg_uint8 *ptr) { return (void *)ptr; }; @@ -321,10 +324,44 @@ externC int pthread_mutex_lock (pthread_ while( !mx->lock() ) continue; PTHREAD_RETURN(0); } + +#ifdef CYGFUN_KERNEL_THREADS_TIMER +//----------------------------------------------------------------------------- +// Lock mutex, waiting for it if necessary for the specified timeout. + +externC int pthread_mutex_timedlock (pthread_mutex_t *mutex, + const struct timespec *abs_timeout) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK( mutex ); + + Cyg_Mutex *mx = (Cyg_Mutex *)mutex; + Cyg_Thread *self = Cyg_Thread::self(); + + if( mx->get_owner() == self ) + PTHREAD_RETURN(EDEADLK); + + if (!valid_timespec(abs_timeout)) + PTHREAD_RETURN(EINVAL); + + // Loop here until we acquire the mutex. Even if we are kicked out + // of the wait by a signal or release we must retry. + while( !mx->lock(cyg_timespec_to_ticks(abs_timeout)) ) + { + if (self->get_wake_reason() == Cyg_Thread::TIMEOUT) + PTHREAD_RETURN(ETIMEDOUT); + + continue; + } + + PTHREAD_RETURN(0); +} +#endif //----------------------------------------------------------------------------- // Try to lock mutex. externC int pthread_mutex_trylock (pthread_mutex_t *mutex) Index: compat/posix/current/src/pprivate.h =================================================================== RCS file: /cvs/ecos/ecos/packages/compat/posix/current/src/pprivate.h,v retrieving revision 1.7 diff -u -5 -p -r1.7 pprivate.h --- compat/posix/current/src/pprivate.h 23 May 2002 22:59:59 -0000 1.7 +++ compat/posix/current/src/pprivate.h 21 Jan 2003 19:27:03 -0000 @@ -236,10 +236,11 @@ externC void cyg_posix_thread_sigdestroy //----------------------------------------------------------------------------- // Functions exported by time.cxx to other parts of the POSIX subsystem. #ifdef CYGPKG_POSIX_CLOCKS + externC void cyg_posix_clock_start(); externC cyg_tick_count cyg_timespec_to_ticks( const struct timespec *tp, cyg_bool roundup = false); @@ -250,10 +251,22 @@ externC void cyg_ticks_to_timespec( cyg_ #ifdef CYGPKG_POSIX_TIMERS externC void cyg_posix_timer_asr( pthread_info *self ); #endif + +static inline cyg_bool valid_timespec( const struct timespec *tp ) +{ + // Fail a NULL pointer + if( tp == NULL ) return false; + + // Fail illegal nanosecond values + if( tp->tv_nsec < 0 || tp->tv_nsec > 1000000000 ) + return false; + + return true; +} //----------------------------------------------------------------------------- // Functions exported by except.cxx #ifdef CYGPKG_POSIX_SIGNALS Index: compat/posix/current/src/sem.cxx =================================================================== RCS file: /cvs/ecos/ecos/packages/compat/posix/current/src/sem.cxx,v retrieving revision 1.5 diff -u -5 -p -r1.5 sem.cxx --- compat/posix/current/src/sem.cxx 23 May 2002 23:00:00 -0000 1.5 +++ compat/posix/current/src/sem.cxx 21 Jan 2003 19:27:03 -0000 @@ -59,10 +59,13 @@ #include // base kernel types #include // tracing macros #include // assertion macros +#ifdef CYGFUN_KERNEL_THREADS_TIMER +#include +#endif #include // our header #include "pprivate.h" // POSIX private header #include // Kernel threads @@ -158,10 +161,44 @@ externC int sem_wait (sem_t *sem) pthread_testcancel(); #endif SEMA_RETURN(retval); } + +#ifdef CYGFUN_KERNEL_THREADS_TIMER +// ------------------------------------------------------------------------- +// Decrement value if >0 or wait for a post for a specified timeout. +externC int sem_timedwait (sem_t *sem, const struct timespec *abs_timeout) +{ + int retval = 0; + + SEMA_ENTRY(); + +#ifdef CYGPKG_POSIX_PTHREAD + // check for cancellation first. + pthread_testcancel(); +#endif + + Cyg_Counting_Semaphore *sema = (Cyg_Counting_Semaphore *)sem; + if (!valid_timespec(abs_timeout)) + retval = EINVAL; + else if( !sema->wait(cyg_timespec_to_ticks(abs_timeout)) ) + { + if((Cyg_Thread::self())->get_wake_reason() == Cyg_Thread::TIMEOUT) + retval = ETIMEDOUT; + else + retval = EINTR; + } + +#ifdef CYGPKG_POSIX_PTHREAD + // check if we were woken because we were being cancelled + pthread_testcancel(); +#endif + + SEMA_RETURN(retval); +} +#endif // ------------------------------------------------------------------------- // Decrement value if >0, return -1 if not. externC int sem_trywait (sem_t *sem) Index: compat/posix/current/src/time.cxx =================================================================== RCS file: /cvs/ecos/ecos/packages/compat/posix/current/src/time.cxx,v retrieving revision 1.7 diff -u -5 -p -r1.7 time.cxx --- compat/posix/current/src/time.cxx 23 May 2002 23:00:00 -0000 1.7 +++ compat/posix/current/src/time.cxx 21 Jan 2003 19:27:04 -0000 @@ -168,22 +168,10 @@ static void init_converters() converters_initialized = true; } } -static cyg_bool valid_timespec( const struct timespec *tp ) -{ - // Fail a NULL pointer - if( tp == NULL ) return false; - - // Fail illegal nanosecond values - if( tp->tv_nsec < 0 || tp->tv_nsec > 1000000000 ) - return false; - - return true; -} - externC cyg_tick_count cyg_timespec_to_ticks( const struct timespec *tp, cyg_bool roundup = false) { init_converters(); Index: isoinfra/current/ChangeLog =================================================================== RCS file: /cvs/ecos/ecos/packages/isoinfra/current/ChangeLog,v retrieving revision 1.19 diff -u -5 -p -r1.19 ChangeLog --- isoinfra/current/ChangeLog 15 Dec 2002 21:17:17 -0000 1.19 +++ isoinfra/current/ChangeLog 21 Jan 2003 19:27:31 -0000 @@ -1,5 +1,10 @@ +2003-01-13 Jonathan Larmour + + * include/mqueue.h: Define POSIX 1003.1d draft mq_timedsend() and + mq_timedreceive() functions. + 2002-12-12 Bart Veer * include/stdlib.h: #include cyg_type.h, now that this header uses NORET attributes Index: isoinfra/current/include/mqueue.h =================================================================== RCS file: /cvs/ecos/ecos/packages/isoinfra/current/include/mqueue.h,v retrieving revision 1.3 diff -u -5 -p -r1.3 mqueue.h --- isoinfra/current/include/mqueue.h 23 May 2002 23:06:41 -0000 1.3 +++ isoinfra/current/include/mqueue.h 21 Jan 2003 19:27:31 -0000 @@ -57,10 +57,11 @@ */ /* CONFIGURATION */ #include /* Configuration header */ +#include /* CYGFUN_KERNEL_THREADS_TIMER */ /* INCLUDES */ #ifdef _POSIX_MESSAGE_PASSING # ifdef CYGBLD_ISO_MQUEUE_HEADER @@ -115,10 +116,26 @@ extern int mq_setattr( mqd_t /* mqdes */, const struct mq_attr * /* mqstat */, struct mq_attr * /* omqstat */ ); extern int mq_getattr( mqd_t /* mqdes */, struct mq_attr * /* mqstat */ ); + +# ifdef CYGFUN_KERNEL_THREADS_TIMER +/* POSIX 1003.1d Draft functions - FIXME: should be conditionalized */ + +struct timespec; /* forward declaration */ + +extern int +mq_timedsend( mqd_t /* mqdes */, const char * /* msg_ptr */, + size_t /* msg_len */, unsigned int /* msg_prio */, + const struct timespec * /* abs_timeout */ ); + +extern ssize_t +mq_timedreceive( mqd_t /* mqdes */, char * /* msg_ptr */, + size_t /* msg_len */, unsigned int * /* msg_prio */, + const struct timespec * /* abs_timeout */ ); +# endif #ifdef __cplusplus } /* extern "C" */ #endif Index: kernel/current/ChangeLog =================================================================== RCS file: /cvs/ecos/ecos/packages/kernel/current/ChangeLog,v retrieving revision 1.86 diff -u -5 -p -r1.86 ChangeLog --- kernel/current/ChangeLog 4 Jan 2003 03:23:15 -0000 1.86 +++ kernel/current/ChangeLog 21 Jan 2003 19:27:34 -0000 @@ -1,5 +1,19 @@ +2003-01-19 Dmitriy Korovkin + + * include/mqueue.inl: Added to get/put functions with timeout check + if timeout occured or wait was interrupted by signal + + * src/sync/mutex.cxx: Added lock with timeout function + * include/mutex.hxx: Ditto + +2003-01-13 Dmitriy Korovkin +2003-01-13 Jonathan Larmour + + * include/mqueue.hxx: Allow get/put to return time out. + * include mqueue.inl: Ditto. + 2003-01-02 Gary Thomas * tests/kcache2.c: New subtest for raw data cache operations. 2002-12-12 Nick Garnett Index: kernel/current/include/mqueue.hxx =================================================================== RCS file: /cvs/ecos/ecos/packages/kernel/current/include/mqueue.hxx,v retrieving revision 1.4 diff -u -5 -p -r1.4 mqueue.hxx --- kernel/current/include/mqueue.hxx 23 May 2002 23:06:48 -0000 1.4 +++ kernel/current/include/mqueue.hxx 21 Jan 2003 19:27:35 -0000 @@ -67,10 +67,11 @@ #include /* size_t */ #include /* Types */ #include /* CYGDBG_DEFINE_CHECK_THIS, CYGDBG_USE_ASSERTS */ +#include /* Kernel package types */ #include /* Cyg_Counting_Semaphore */ /* CLASSES */ class Cyg_Mqueue { @@ -81,10 +82,13 @@ public: typedef enum { OK=0, NOMEM, WOULDBLOCK, +#ifdef CYGFUN_KERNEL_THREADS_TIMER + TIMEOUT, +#endif INTR } qerr_t; protected: struct qentry { @@ -120,19 +124,25 @@ protected: public: Cyg_Mqueue( long maxmsgs, long maxmsgsize, qalloc_fn_t qalloc, qfree_fn_t qfree, qerr_t *err ); ~Cyg_Mqueue(); - // put() copies len bytes of *buf into the queue at priority prio - qerr_t put( const char *buf, size_t len, unsigned int prio, - bool block=true); + qerr_t put( const char *buf, size_t len, unsigned int prio, bool block=true +#ifdef CYGFUN_KERNEL_THREADS_TIMER + ,cyg_tick_count timeout = 0 +#endif + ); // get() returns the oldest highest priority message in the queue in *buf // and sets *prio to the priority (if prio is non-NULL) and *len to the // actual message size - qerr_t get( char *buf, size_t *len, unsigned int *prio, bool block=true ); + qerr_t get( char *buf, size_t *len, unsigned int *prio, bool block=true +#ifdef CYGFUN_KERNEL_THREADS_TIMER + ,cyg_tick_count timeout = 0 +#endif + ); // count() returns the number of messages in the queue long count(); // Supply a callback function to call (with the supplied data argument) Index: kernel/current/include/mqueue.inl =================================================================== RCS file: /cvs/ecos/ecos/packages/kernel/current/include/mqueue.inl,v retrieving revision 1.5 diff -u -5 -p -r1.5 mqueue.inl --- kernel/current/include/mqueue.inl 23 May 2002 23:06:48 -0000 1.5 +++ kernel/current/include/mqueue.inl 21 Jan 2003 19:27:35 -0000 @@ -270,11 +270,15 @@ Cyg_Mqueue::~Cyg_Mqueue() //------------------------------------------------------------------------ // put() copies len bytes of *buf into the queue at priority prio CYGPRI_KERNEL_SYNCH_MQUEUE_INLINE Cyg_Mqueue::qerr_t -Cyg_Mqueue::put( const char *buf, size_t len, unsigned int prio, bool block ) +Cyg_Mqueue::put( const char *buf, size_t len, unsigned int prio, bool block +#ifdef CYGFUN_KERNEL_THREADS_TIMER + , cyg_tick_count timeout +#endif + ) { CYG_REPORT_FUNCTYPE( "err=%d"); CYG_REPORT_FUNCARG4( "buf=%08x, len=%ld, prio=%ud, block=%d", buf, len, prio, block==true ); CYG_CHECK_DATA_PTRC( buf ); @@ -284,10 +288,23 @@ Cyg_Mqueue::put( const char *buf, size_t qerr_t err; struct qentry *qtmp, *qent; // wait till a freelist entry is available if ( true == block ) { +#ifdef CYGFUN_KERNEL_THREADS_TIMER + if ( timeout != 0) { + if ( false == putsem.wait(timeout) ) { + if((Cyg_Thread::self())->get_wake_reason() == + Cyg_Thread::TIMEOUT) + err = TIMEOUT; + else + err = INTR; + goto exit; + } + } + else +#endif if ( false == putsem.wait() ) { err = INTR; goto exit; } } else { @@ -377,11 +394,15 @@ Cyg_Mqueue::put( const char *buf, size_t // get() returns the oldest highest priority message in the queue in *buf // and sets *prio to the priority (if prio is non-NULL) and *len to the // actual message size CYGPRI_KERNEL_SYNCH_MQUEUE_INLINE Cyg_Mqueue::qerr_t -Cyg_Mqueue::get( char *buf, size_t *len, unsigned int *prio, bool block ) +Cyg_Mqueue::get( char *buf, size_t *len, unsigned int *prio, bool block +#ifdef CYGFUN_KERNEL_THREADS_TIMER + , cyg_tick_count timeout +#endif + ) { CYG_REPORT_FUNCTYPE( "err=%d"); CYG_REPORT_FUNCARG4( "buf=%08x, len=%08x, prio=%08x, block=%d", buf, len, prio, block==true ); CYG_CHECK_DATA_PTRC( buf ); @@ -393,10 +414,23 @@ Cyg_Mqueue::get( char *buf, size_t *len, qerr_t err; struct qentry *qent; // wait till a q entry is available if ( true == block ) { +#ifdef CYGFUN_KERNEL_THREADS_TIMER + if ( timeout != 0) { + if ( false == getsem.wait(timeout) ) { + if((Cyg_Thread::self())->get_wake_reason() == + Cyg_Thread::TIMEOUT) + err = TIMEOUT; + else + err = INTR; + goto exit; + } + } + else +#endif if ( false == getsem.wait() ) { err = INTR; goto exit; } } else { Index: kernel/current/include/mutex.hxx =================================================================== RCS file: /cvs/ecos/ecos/packages/kernel/current/include/mutex.hxx,v retrieving revision 1.8 diff -u -5 -p -r1.8 mutex.hxx --- kernel/current/include/mutex.hxx 23 May 2002 23:06:48 -0000 1.8 +++ kernel/current/include/mutex.hxx 21 Jan 2003 19:27:35 -0000 @@ -113,10 +113,14 @@ public: ~Cyg_Mutex(); // Destructor cyg_bool lock(); // lock and/or wait +#ifdef CYGFUN_KERNEL_THREADS_TIMER + cyg_bool lock(cyg_tick_count timeout); // lock and/or wait with timeout +#endif + cyg_bool trylock(); // try to lock and return success void unlock(); // unlock void release(); // release all waiting threads Index: kernel/current/src/sync/mutex.cxx =================================================================== RCS file: /cvs/ecos/ecos/packages/kernel/current/src/sync/mutex.cxx,v retrieving revision 1.14 diff -u -5 -p -r1.14 mutex.cxx --- kernel/current/src/sync/mutex.cxx 23 May 2002 23:06:56 -0000 1.14 +++ kernel/current/src/sync/mutex.cxx 21 Jan 2003 19:27:36 -0000 @@ -323,10 +323,152 @@ Cyg_Mutex::lock(void) return result; } // ------------------------------------------------------------------------- +// Lock and/or wait with timeout +// FIXME: Personally I don't like simply copy/paste function adding +// but I implemented this as it was implemented with semaphores. +// Architecture engineer, please take a look! + +#ifdef CYGFUN_KERNEL_THREADS_TIMER + +cyg_bool +Cyg_Mutex::lock(cyg_tick_count timeout) +{ + CYG_REPORT_FUNCTYPE("returning %d"); + + cyg_bool result = true; + Cyg_Thread *self = Cyg_Thread::self(); + + // Prevent preemption + Cyg_Scheduler::lock(); + + CYG_ASSERTCLASS( this, "Bad this pointer"); + + CYG_INSTRUMENT_MUTEX(LOCK, this, 0); + + // Loop while the mutex is locked, sleeping each time around + // the loop. This copes with the possibility of a higher priority + // thread grabbing the mutex between the wakeup in unlock() and + // this thread actually starting. + +#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL + + IF_PROTOCOL_ACTIVE + self->count_mutex(); + +#endif + +#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING + + IF_PROTOCOL_CEILING + self->set_priority_ceiling(ceiling); + +#endif + + // Set the timer _once_ outside the loop. + self->set_timer( timeout, Cyg_Thread::TIMEOUT ); + + // If the timeout is in the past, the wake reason will have been + // set to something other than NONE already. Set the result false + // to force an immediate return. + + if( self->get_wake_reason() != Cyg_Thread::NONE ) + result = false; + + while( locked && result ) + { + CYG_ASSERT( self != owner, "Locking mutex I already own"); + + self->set_sleep_reason( Cyg_Thread::WAIT ); + + self->sleep(); + + queue.enqueue( self ); + +#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT + + IF_PROTOCOL_INHERIT + owner->inherit_priority(self); + +#endif + + CYG_INSTRUMENT_MUTEX(WAIT, this, 0); + + // Allow other threads to run + Cyg_Scheduler::reschedule(); + + CYG_ASSERTCLASS( this, "Bad this pointer"); + + switch( self->get_wake_reason() ) + { + case Cyg_Thread::TIMEOUT: + result = false; + CYG_INSTRUMENT_MUTEX(TIMEOUT, this, 0); + break; + + case Cyg_Thread::DESTRUCT: + case Cyg_Thread::BREAK: + result = false; + break; + + case Cyg_Thread::EXIT: + self->exit(); + break; + + default: + break; + } + + } + + if( result ) + { + locked = true; + owner = self; + + CYG_INSTRUMENT_MUTEX(LOCKED, this, 0); + } + else + { +#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL + + IF_PROTOCOL_ACTIVE + self->uncount_mutex(); + +#endif +#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT + + IF_PROTOCOL_INHERIT + self->disinherit_priority(); + +#endif +#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING + + IF_PROTOCOL_CEILING + self->clear_priority_ceiling(); + +#endif + } + + // Clear the timeout. It is irrelevant whether the alarm has + // actually gone off or not. + self->clear_timer(); + + // Unlock the scheduler and maybe switch threads + Cyg_Scheduler::unlock(); + + CYG_ASSERTCLASS( this, "Bad this pointer"); + + CYG_REPORT_RETVAL(result); + + return result; +} + +#endif +// ------------------------------------------------------------------------- // Try to lock and return success cyg_bool Cyg_Mutex::trylock(void) {