mq_timed... sem_timedwait, pthread_mutex_timed_lock
Dmitriy Korovkin
dkorovkin@rambler.ru
Tue Jan 21 19:40:00 GMT 2003
Hi,
I'm really sorry about my previous patch. I has many stupied bugs and
typos. Here is the fixed one. At least, I could start ISaGRAF target using
this patch. Would please, review it.
Thanks in advance,
--
Dmitriy
---------- Forwarded message ----------
Date: Sun, 19 Jan 2003 18:26:09 +0300 (MSK)
From: Dmitriy Korovkin <dkorovkin@rambler.ru>
To: ecos-patches@sources.redhat.com
Subject: mq_timed... sem_timedwait, pthread_mutex_timed_lock
Jonathan, Nick and other nice guys,
As I promised, here is the patch that adds sem_timedwait,
pthread_mutex_timed_lock functions and also Cyg_Mutex::lock() with
timeout. It also slightly changes behavoir of mq_timedsend and
mq_timedreceive so that they try to figure out why there was a timeout.
Patch was created over the existing CVS that doesn't include mq_timedsend
and mq_timedreceive, so they are included again (I couldn't remove them
because I've changed them). Sorry for inconvinience and thank you for your
patience while you review my changes. And thank you very much for nice OS.
Regards,
--
Dmitriy
---------- Forwarded message ----------
Date: Wed, 15 Jan 2003 09:16:49 +0300 (MSK)
From: Dmitriy Korovkin <dkorovkin@rambler.ru>
To: Jonathan Larmour <jifl@ecoscentric.com>
Cc: Nick Garnett <nickg@ecoscentric.com>, <ecos-patches@sources.redhat.com>
Subject: Re: mq_timedsend & mq_timedreceive
OK, I'll try to add the required stuff on the nearest weekend.
Regards,
--
Dmitriy
On Tue, 14 Jan 2003, Jonathan Larmour wrote:
> Date: Tue, 14 Jan 2003 07:10:12 +0000
> From: Jonathan Larmour <jifl@ecoscentric.com>
> To: Dmitriy Korovkin <dkorovkin@rambler.ru>
> Cc: Nick Garnett <nickg@ecoscentric.com>, ecos-patches@sources.redhat.com
> Subject: Re: mq_timedsend & mq_timedreceive
>
> Dmitriy Korovkin wrote:
> > Nick, Jonathan
> > Does it mean I may do them?!
> > Yesturday I found that I'd be glad to have sem_timedwait and
> > pthread_mutextimedlock. I don't see a problem with implementing it but
> > standards... Huh, actually asking around brought me that QNX guys included
> > this into their manual pages and LynxOS guys seems to do this too. Why we
> > shouldn't do this? At least, some things that are almost reqired by that
> > ^&*@^$&*@ ISaGRAF PRO target.
>
> Feel free. It's not a priority for us though so the ball is in your court
> if you want it.
>
> But do take care with your treatment of error conditions, for example I
> had to add something to take care of invalid timeval nanosecond values
> causing an EINVAL error. You should refer closely to the standard for
> this. See <http://www.opengroup.org/onlinepubs/007904975/mindex.html>
>
> Jifl
>
-------------- next part --------------
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 <dkorovkin@rambler.ru>
+ * 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 <jifl@eCosCentric.com>
+
+ * 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 <dkorovkin@rambler.ru>
+
+ * src/mqueue.cxx (mq_timedsend): New function. Implementing POSIX
+ 1003.1d draft definition.
+ (mq_timedreceive): Ditto.
+
2002-12-10 Wade Jensen <waj4news@cox.net>
2002-12-10 Jonathan Larmour <jifl@eCosCentric.com>
* 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);
</screen>
+<para>From POSIX 1003.1d draft: </para>
+<screen>
+int sem_timedwait(sem_t *sem,
+ const struct timespec *abs_timeout);
+int pthread_mutex_lock(pthread_mutex_t *mutex,
+ const struct timespec *abs_timeout);
+</screen>
</sect2>
<!-- =================================================================== -->
<sect2>
@@ -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 );
+</screen>
+<para>From POSIX 1003.1d draft: </para>
+<screen>
+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 );
</screen>
</sect2>
<!-- =================================================================== -->
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 <new> // C++ new
#ifdef CYGFUN_POSIX_MQUEUE_NOTIFY
# include <signal.h>
# include "pprivate.h" // cyg_sigqueue()
#endif
-
+#ifdef CYGFUN_KERNEL_THREADS_TIMER
+# include <time.h>
+# 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 <cyg/kernel/mutex.hxx> // mutex definitions
#include <cyg/kernel/clock.hxx> // clock definitions
#include <pthread.h>
#include <cyg/kernel/thread.inl> // thread inlines
+#ifdef CYGFUN_KERNEL_THREADS_TIMER
+#include <time.h>
+#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 <cyg/kernel/ktypes.h> // base kernel types
#include <cyg/infra/cyg_trac.h> // tracing macros
#include <cyg/infra/cyg_ass.h> // assertion macros
+#ifdef CYGFUN_KERNEL_THREADS_TIMER
+#include <time.h>
+#endif
#include <semaphore.h> // our header
#include "pprivate.h" // POSIX private header
#include <cyg/kernel/thread.hxx> // 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 <jifl@eCosCentric.com>
+
+ * include/mqueue.h: Define POSIX 1003.1d draft mq_timedsend() and
+ mq_timedreceive() functions.
+
2002-12-12 Bart Veer <bartv@ecoscentric.com>
* 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 <pkgconf/isoinfra.h> /* Configuration header */
+#include <pkgconf/kernel.h> /* 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 <dkorovkin@rambler.ru>
+
+ * 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 <dkorovkin@rambler.ru>
+2003-01-13 Jonathan Larmour <jifl@eCosCentric.com>
+
+ * include/mqueue.hxx: Allow get/put to return time out.
+ * include mqueue.inl: Ditto.
+
2003-01-02 Gary Thomas <gary@mlbassoc.com>
* tests/kcache2.c: New subtest for raw data cache operations.
2002-12-12 Nick Garnett <nickg@ecoscentric.com>
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 <stddef.h> /* size_t */
#include <cyg/infra/cyg_type.h> /* Types */
#include <cyg/infra/cyg_ass.h> /* CYGDBG_DEFINE_CHECK_THIS,
CYGDBG_USE_ASSERTS */
+#include <cyg/kernel/ktypes.h> /* Kernel package types */
#include <cyg/kernel/sema.hxx> /* 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)
{
More information about the Ecos-patches
mailing list