* [Xenomai-core] [PATCH] solo/vxWorks: add rngLib (with testsuite)
@ 2008-10-24 21:48 Niklaus Giger
2008-10-26 16:02 ` Philippe Gerum
0 siblings, 1 reply; 3+ messages in thread
From: Niklaus Giger @ 2008-10-24 21:48 UTC (permalink / raw)
To: xenomai-core
Hi
I just found the time to prepare a patch for a substitute for the vxWorks
rngLib library I have written quite some time ago.
The remark from the vxWorks description applies here too
"In particular, ring buffers by themselves provide no task synchronization or mutual exclusion."
(http://www.slac.stanford.edu/exp/glast/flight/sw/vxdocs/vxworks/ref/rngLib.html)
Therefore this library is only good were there is exactly one writer an one reader
envolved.
It would be nice if it could find a place in the xenomai-solo. I am willing to
address any criticism/nitpicking needed to get it into a good shape.
Best regards
Signed-off-by: Niklaus Giger <niklaus.giger@domain.hid>
---
include/vxworks/Makefile.am | 1 +
include/vxworks/Makefile.in | 1 +
vxworks/Makefile.am | 2 +
vxworks/Makefile.in | 18 ++++-
vxworks/rngLib.c | 152 +++++++++++++++++++++++++++++++++++++++++++
vxworks/rngLib.h | 34 ++++++++++
vxworks/testsuite/Makefile | 2 +-
vxworks/testsuite/rng-1.c | 118 +++++++++++++++++++++++++++++++++
8 files changed, 323 insertions(+), 5 deletions(-)
create mode 100644 vxworks/rngLib.c
create mode 100644 vxworks/rngLib.h
create mode 100644 vxworks/testsuite/rng-1.c
diff --git a/include/vxworks/Makefile.am b/include/vxworks/Makefile.am
index 06dcab2..0c20861 100644
--- a/include/vxworks/Makefile.am
+++ b/include/vxworks/Makefile.am
@@ -7,6 +7,7 @@ includesub_HEADERS = \
lstLib.h \
memPartLib.h \
msgQLib.h \
+ rngLib.h \
semLib.h \
sysLib.h \
taskInfo.h \
diff --git a/include/vxworks/Makefile.in b/include/vxworks/Makefile.in
index 0fdc3c4..ad10fd1 100644
--- a/include/vxworks/Makefile.in
+++ b/include/vxworks/Makefile.in
@@ -205,6 +205,7 @@ includesub_HEADERS = \
lstLib.h \
memPartLib.h \
msgQLib.h \
+ rngLib.h \
semLib.h \
sysLib.h \
taskInfo.h \
diff --git a/vxworks/Makefile.am b/vxworks/Makefile.am
index 08e7cc8..a64141e 100644
--- a/vxworks/Makefile.am
+++ b/vxworks/Makefile.am
@@ -11,6 +11,8 @@ libvxworks_la_SOURCES = \
memPartLib.h \
msgQLib.c \
msgQLib.h \
+ rngLib.c \
+ rngLib.h \
semLib.c \
semLib.h \
taskLib.c \
diff --git a/vxworks/Makefile.in b/vxworks/Makefile.in
index b8d0ce7..2d08bbd 100644
--- a/vxworks/Makefile.in
+++ b/vxworks/Makefile.in
@@ -57,10 +57,10 @@ libvxworks_la_LIBADD =
am_libvxworks_la_OBJECTS = libvxworks_la-errnoLib.lo \
libvxworks_la-intLib.lo libvxworks_la-kernelLib.lo \
libvxworks_la-lstLib.lo libvxworks_la-memPartLib.lo \
- libvxworks_la-msgQLib.lo libvxworks_la-semLib.lo \
- libvxworks_la-taskLib.lo libvxworks_la-taskInfo.lo \
- libvxworks_la-tickLib.lo libvxworks_la-wdLib.lo \
- libvxworks_la-sysLib.lo
+ libvxworks_la-msgQLib.lo libvxworks_la-rngLib.lo \
+ libvxworks_la-semLib.lo libvxworks_la-taskLib.lo \
+ libvxworks_la-taskInfo.lo libvxworks_la-tickLib.lo \
+ libvxworks_la-wdLib.lo libvxworks_la-sysLib.lo
libvxworks_la_OBJECTS = $(am_libvxworks_la_OBJECTS)
libvxworks_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@@ -232,6 +232,8 @@ libvxworks_la_SOURCES = \
memPartLib.h \
msgQLib.c \
msgQLib.h \
+ rngLib.c \
+ rngLib.h \
semLib.c \
semLib.h \
taskLib.c \
@@ -324,6 +326,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@domain.hid@
@AMDEP_TRUE@@am__include@ @am__quote@domain.hid@
@AMDEP_TRUE@@am__include@ @am__quote@domain.hid@
+@AMDEP_TRUE@@am__include@ @am__quote@domain.hid@
@AMDEP_TRUE@@am__include@ @am__quote@domain.hid@
@AMDEP_TRUE@@am__include@ @am__quote@domain.hid@
@AMDEP_TRUE@@am__include@ @am__quote@domain.hid@
@@ -394,6 +397,13 @@ libvxworks_la-msgQLib.lo: msgQLib.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvxworks_la_CPPFLAGS)
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libvxworks_la-msgQLib.lo `test -f 'msgQLib.c' || echo '$(srcdir)/'`msgQLib.c
+libvxworks_la-rngLib.lo: rngLib.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvxworks_la_CPPFLAGS)
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libvxworks_la-rngLib.lo -MD -MP -MF $(DEPDIR)/libvxworks_la-rngLib.Tpo -c -o libvxworks_la-rngLib.lo `test -f 'rngLib.c' || echo
'$(srcdir)/'`rngLib.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libvxworks_la-rngLib.Tpo $(DEPDIR)/libvxworks_la-rngLib.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='rngLib.c' object='libvxworks_la-rngLib.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvxworks_la_CPPFLAGS)
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libvxworks_la-rngLib.lo `test -f 'rngLib.c' || echo '$(srcdir)/'`rngLib.c
+
libvxworks_la-semLib.lo: semLib.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvxworks_la_CPPFLAGS)
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libvxworks_la-semLib.lo -MD -MP -MF $(DEPDIR)/libvxworks_la-semLib.Tpo -c -o libvxworks_la-semLib.lo `test -f 'semLib.c' || echo
'$(srcdir)/'`semLib.c
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libvxworks_la-semLib.Tpo $(DEPDIR)/libvxworks_la-semLib.Plo
diff --git a/vxworks/rngLib.c b/vxworks/rngLib.c
new file mode 100644
index 0000000..d033db9
--- /dev/null
+++ b/vxworks/rngLib.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2008 Niklaus Giger <niklaus.giger@domain.hid>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <stdlib.h>
+#include <vxworks/errnoLib.h>
+#include "rngLib.h"
+
+#define WIND_RING_MAGIC 0x5432affe
+
+RING_ID rngCreate(int nbytes)
+{
+ RING_DESCRIPTOR *ring;
+ void *ring_mem;
+
+ if ( nbytes<=0) { errnoSet(S_memLib_NOT_ENOUGH_MEMORY); return 0; }
+ ring_mem = malloc( sizeof(RING_DESCRIPTOR*) + nbytes);
+ if ( ring_mem == 0) { errno = errnoSet(S_memLib_NOT_ENOUGH_MEMORY); return 0; }
+
+ ring = (RING_DESCRIPTOR *) ring_mem;
+ ring->magic = WIND_RING_MAGIC;
+ ring->bufSize = nbytes;
+ ring->readPos = 0;
+ ring->writePos = 0;
+ return (RING_ID) ring_mem;
+}
+
+
+void rngDelete(RING_ID ring_id)
+{
+ RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
+ if (ring->magic != WIND_RING_MAGIC) return;
+ ring->magic = 0;
+ free(ring);
+}
+
+
+void rngFlush(RING_ID ring_id)
+{
+ RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
+ if (ring->magic != WIND_RING_MAGIC) return;
+ ring->readPos = 0;
+ ring->writePos = 0;
+}
+
+
+int rngBufGet(RING_ID ring_id,
+ char * buffer,
+ int maxbytes)
+{
+ RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
+ int j, bytesRead=0;
+ unsigned int savedWritePos = ring->writePos;
+ if (ring->magic != WIND_RING_MAGIC) return -ENOSYS;
+ for (j=0; j < maxbytes; j++)
+ {
+ if ((ring->readPos) % (ring->bufSize + 1) == savedWritePos)
+ {
+ break;
+ }
+ buffer[j] = ring->buffer[ring->readPos];
+ ++bytesRead;
+ ring->readPos = (ring->readPos + 1) % (ring->bufSize + 1);
+ }
+ return bytesRead;
+}
+
+
+int rngBufPut(RING_ID ring_id,
+ char * buffer,
+ int nbytes)
+{
+ RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
+ int j, bytesWritten=0;
+ unsigned int savedReadPos = ring->readPos;
+ if (ring->magic != WIND_RING_MAGIC) return -ENOSYS;
+ for (j=0; j < nbytes; j++)
+ {
+ if ((ring->writePos + 1) % (ring->bufSize + 1) == savedReadPos)
+ {
+ break;
+ }
+ ring->buffer[ring->writePos] = buffer[j];
+ ++bytesWritten;
+ ring->writePos = (ring->writePos + 1) % (ring->bufSize + 1);
+ }
+ return bytesWritten;
+}
+
+
+BOOL rngIsEmpty(RING_ID ring_id)
+{
+ RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
+ if (ring->magic != WIND_RING_MAGIC) return -ENOSYS;
+ return rngFreeBytes(ring_id) == (int) ring->bufSize;
+}
+
+
+BOOL rngIsFull(RING_ID ring_id)
+{
+ RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
+ if (ring->magic != WIND_RING_MAGIC) return -ENOSYS;
+ return rngFreeBytes(ring_id) == 0;
+}
+
+
+int rngFreeBytes(RING_ID ring_id)
+{
+ RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
+ if (ring->magic != WIND_RING_MAGIC) return -ENOSYS;
+ return ((ring->bufSize - (ring->writePos - ring->readPos)) % (ring->bufSize+1));
+}
+
+
+int rngNBytes(RING_ID ring_id)
+{
+ RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
+ if (ring->magic != WIND_RING_MAGIC) return -ENOSYS;
+ return ring->bufSize - rngFreeBytes(ring_id);
+}
+
+void rngPutAhead(RING_ID ring_id,
+ char byte,
+ int offset)
+{
+ RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
+ if (ring->magic != WIND_RING_MAGIC) return;
+ return;
+}
+
+
+void rngMoveAhead(RING_ID ring_id,
+ int n)
+{
+ RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
+ if (ring->magic != WIND_RING_MAGIC) return;
+ return;
+}
diff --git a/vxworks/rngLib.h b/vxworks/rngLib.h
new file mode 100644
index 0000000..d646614
--- /dev/null
+++ b/vxworks/rngLib.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2008 Philippe Gerum <rpm@xenomai.org>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _VXWORKS_RNGLIB_H
+#define _VXWORKS_RNGLIB_H
+
+#include <xenomai/syncobj.h>
+#include <xenomai/heapobj.h>
+#include <vxworks/rngLib.h>
+
+typedef struct {
+ unsigned int magic;
+ unsigned int bufSize;
+ unsigned int readPos;
+ unsigned int writePos;
+ char buffer[];
+} RING_DESCRIPTOR ;
+
+#endif /* _VXWORKS_RNGLIB_H */
diff --git a/vxworks/testsuite/Makefile b/vxworks/testsuite/Makefile
index d1ce203..d391406 100644
--- a/vxworks/testsuite/Makefile
+++ b/vxworks/testsuite/Makefile
@@ -5,7 +5,7 @@ ifeq ($(prefix),)
$(error Please add <xenomai-install-path>/bin to your PATH variable)
endif
-TESTS := task-1 task-2 msgQ-1 msgQ-2 msgQ-3 wd-1 sem-1 sem-2 sem-3 sem-4 lst-1
+TESTS := task-1 task-2 msgQ-1 msgQ-2 msgQ-3 wd-1 sem-1 sem-2 sem-3 sem-4 lst-1 rng-1
CFLAGS := $(shell $(XENO_CONFIG) --cflags) -g
LDFLAGS := -lvxworks $(shell $(XENO_CONFIG) --ldflags)
diff --git a/vxworks/testsuite/rng-1.c b/vxworks/testsuite/rng-1.c
new file mode 100644
index 0000000..fab36ab
--- /dev/null
+++ b/vxworks/testsuite/rng-1.c
@@ -0,0 +1,118 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <xenomai/traceobj.h>
+#include <vxworks/errnoLib.h>
+#include <vxworks/taskLib.h>
+#include <vxworks/rngLib.h>
+
+static struct traceobj trobj;
+
+void rootTask(long a0, long a1, long a2, long a3, long a4,
+ long a5, long a6, long a7, long a8, long a9)
+{
+ RING_ID ring;
+
+ int j, chunks;
+ const int putBytes = 10;
+ const int nrChunks = 3;
+ const int rngBytes = putBytes * nrChunks;
+ char buffer[putBytes];
+ char bigBuffer[putBytes*2*nrChunks];
+ int bytesPut;
+ int bytesGot;
+ traceobj_enter(&trobj);
+
+ RING_ID rng = rngCreate(rngBytes);
+
+ traceobj_assert(&trobj, rng != 0);
+ traceobj_assert(&trobj, rngIsEmpty(rng));
+ traceobj_assert(&trobj, !rngIsFull(rng));
+
+ /* Fill a few chunks */
+ for (chunks=0; chunks < nrChunks; chunks++) {
+ traceobj_assert(&trobj, rngNBytes(rng) == chunks*(int)sizeof(buffer));
+ traceobj_assert(&trobj, rngFreeBytes(rng) == rngBytes - chunks*(int)sizeof(buffer));
+ for (j=0; j < (int)sizeof(buffer); j++) {
+ buffer[j] = (char)j+(int)sizeof(buffer)*chunks;
+ }
+ bytesPut = rngBufPut(rng, &buffer[0], sizeof(buffer));
+ traceobj_assert(&trobj, bytesPut == sizeof(buffer));
+ traceobj_assert(&trobj, !rngIsEmpty(rng));
+ traceobj_assert(&trobj, rngIsFull(rng) == (nrChunks - 1 == chunks));
+ traceobj_assert(&trobj, rngFreeBytes(rng) == rngBytes-bytesPut*(chunks+1));
+ traceobj_assert(&trobj, rngNBytes(rng) == (chunks + 1)*(int)sizeof(buffer));
+ }
+ traceobj_assert(&trobj, rngIsFull(rng));
+ bytesPut = rngBufPut(rng, &buffer[0], sizeof(buffer));
+ traceobj_assert(&trobj, bytesPut ==0);
+ traceobj_assert(&trobj, rngIsFull(rng));
+
+ /* Read chunks back and check content */
+ for (chunks=0; chunks < nrChunks; chunks++)
+ {
+ for (j=0; j < (int)sizeof(buffer); j++) {
+ buffer[j] = 0;
+ }
+ traceobj_assert(&trobj, rngNBytes(rng) == (nrChunks - chunks)*(int)sizeof(buffer));
+ traceobj_assert(&trobj, rngFreeBytes(rng) == chunks*(int)sizeof(buffer));
+ bytesGot = rngBufGet(rng, &buffer[0], sizeof(buffer));
+ traceobj_assert(&trobj, bytesGot == (int)sizeof(buffer));
+ for (j=0; j < (int)sizeof(buffer); j++) {
+ traceobj_assert(&trobj, buffer[j] == (char)j + sizeof(buffer)*chunks);
+ }
+ traceobj_assert(&trobj, !rngIsFull(rng));
+ traceobj_assert(&trobj, rngIsEmpty(rng) == (chunks == nrChunks -1));
+
+ traceobj_assert(&trobj, rngFreeBytes(rng) == (chunks + 1)*(int)sizeof(buffer));
+ traceobj_assert(&trobj, rngNBytes(rng) == (nrChunks - chunks - 1)*(int)sizeof(buffer));
+ }
+
+ /* Testing filling too many */
+ for (j=0; j < (int)sizeof(bigBuffer); j++) {
+ bigBuffer[j] = 32+j;
+ }
+ bytesPut = rngBufPut(rng, &bigBuffer[0], sizeof(bigBuffer));
+ traceobj_assert(&trobj, bytesPut == rngBytes);
+ traceobj_assert(&trobj, !rngIsEmpty(rng));
+ traceobj_assert(&trobj, rngIsFull(rng));
+ traceobj_assert(&trobj, rngFreeBytes(rng) == 0);
+ traceobj_assert(&trobj, rngNBytes(rng) == rngBytes);
+
+ /* Getting too many */
+ for (j=0; j < (int)sizeof(bigBuffer); j++) {
+ bigBuffer[j] = 0;
+ }
+ bytesGot = rngBufGet(rng, &bigBuffer[0], sizeof(bigBuffer));
+ traceobj_assert(&trobj, bytesGot == rngBytes);
+ traceobj_assert(&trobj, rngIsEmpty(rng));
+ traceobj_assert(&trobj, !rngIsFull(rng));
+ traceobj_assert(&trobj, rngFreeBytes(rng) == rngBytes);
+ traceobj_assert(&trobj, rngNBytes(rng) == 0);
+ for (j=0; j <rngBytes; j++) {
+ traceobj_assert(&trobj, bigBuffer[j] == (char)32+j);
+ }
+
+ bytesPut = rngBufPut(rng, &bigBuffer[0], sizeof(bigBuffer));
+ traceobj_assert(&trobj, bytesPut == rngBytes);
+ rngFlush(rng);
+ traceobj_assert(&trobj, rngIsEmpty(rng));
+ traceobj_assert(&trobj, !rngIsFull(rng));
+ traceobj_assert(&trobj, rngFreeBytes(rng) == rngBytes);
+ traceobj_assert(&trobj, rngNBytes(rng) == 0);
+ rngDelete(rng);
+
+ traceobj_exit(&trobj);
+}
+
+int main(int argc, char *argv[])
+{
+ int ret;
+
+ traceobj_init(&trobj, argv[0], 0);
+
+ ret = kernelInit(rootTask, argc, argv);
+ traceobj_assert(&trobj, ret == OK);
+
+ traceobj_join(&trobj);
+ exit(0);
+}
+
--
1.6.0.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [Xenomai-core] [PATCH] solo/vxWorks: add rngLib (with testsuite)
2008-10-24 21:48 [Xenomai-core] [PATCH] solo/vxWorks: add rngLib (with testsuite) Niklaus Giger
@ 2008-10-26 16:02 ` Philippe Gerum
2008-10-28 16:11 ` Niklaus Giger
0 siblings, 1 reply; 3+ messages in thread
From: Philippe Gerum @ 2008-10-26 16:02 UTC (permalink / raw)
To: Niklaus Giger; +Cc: xenomai-core
Niklaus Giger wrote:
> Hi
>
> I just found the time to prepare a patch for a substitute for the vxWorks
> rngLib library I have written quite some time ago.
>
> The remark from the vxWorks description applies here too
> "In particular, ring buffers by themselves provide no task synchronization or mutual exclusion."
> (http://www.slac.stanford.edu/exp/glast/flight/sw/vxdocs/vxworks/ref/rngLib.html)
>
> Therefore this library is only good were there is exactly one writer an one reader
> envolved.
>
Fair enough, but we would have to pin all VxWorks tasks to the same CPU on SMP
systems; otherwise, out-of-order memory accesses would kill that code.
> It would be nice if it could find a place in the xenomai-solo. I am willing to
> address any criticism/nitpicking needed to get it into a good shape.
>
> Best regards
>
> Signed-off-by: Niklaus Giger <niklaus.giger@domain.hid>
> ---
> include/vxworks/Makefile.am | 1 +
> include/vxworks/Makefile.in | 1 +
> vxworks/Makefile.am | 2 +
> vxworks/Makefile.in | 18 ++++-
> vxworks/rngLib.c | 152 +++++++++++++++++++++++++++++++++++++++++++
> vxworks/rngLib.h | 34 ++++++++++
Something must be missing here. vxworks/rngLib.h should contain internal
definitions, used by the ring buffer implementation code, and that is correct in
your code. However, include/vxworks/rngLib.h should provide the interface to
applications; it seems we are missing such a file.
Since we don't want to export the innards of a ring buffer implementation to
applications, the interface header should only define the opaque ring buffer
handle type (i.e. typedef intptr_t RING_ID), and the RNG routine prototypes.
> vxworks/testsuite/Makefile | 2 +-
> vxworks/testsuite/rng-1.c | 118 +++++++++++++++++++++++++++++++++
> 8 files changed, 323 insertions(+), 5 deletions(-)
> create mode 100644 vxworks/rngLib.c
> create mode 100644 vxworks/rngLib.h
> create mode 100644 vxworks/testsuite/rng-1.c
>
[snip]
diff --git a/vxworks/rngLib.c b/vxworks/rngLib.c
> new file mode 100644
> index 0000000..d033db9
> --- /dev/null
> +++ b/vxworks/rngLib.c
> @@ -0,0 +1,152 @@
> +/*
> + * Copyright (C) 2008 Niklaus Giger <niklaus.giger@domain.hid>.
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library 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
> + * Lesser General Public License for more details.
> +
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
> + */
> +
> +#include <stdlib.h>
> +#include <vxworks/errnoLib.h>
> +#include "rngLib.h"
> +
> +#define WIND_RING_MAGIC 0x5432affe
> +
> +RING_ID rngCreate(int nbytes)
> +{
> + RING_DESCRIPTOR *ring;
> + void *ring_mem;
> +
> + if ( nbytes<=0) { errnoSet(S_memLib_NOT_ENOUGH_MEMORY); return 0; }
Please use the linux-c coding style, basically K&R + preposterously large indent
tabs (8 chars)
Emacs can be taught this way:
(defun linux-c-mode ()
"C mode with adjusted defaults for use with Xenomai."
(interactive)
(c-mode)
(c-set-style "K&R")
(setq tab-width 8)
(setq indent-tabs-mode t)
(setq c-basic-offset 8))
Indent will reformat almost properly with (-T should be used to teach indent
about the known non-standard types as well):
$ indent -npro -kr -i8 -ts8 -sob -l80 -ss -ncs -cp1
> + ring_mem = malloc( sizeof(RING_DESCRIPTOR*) + nbytes);
The sizeof() argument is wrong. Out-of-bound memory writes are knocking at the door.
Also, please use xnmalloc(). This call will pull memory from the allocator
selected at built time for the SOLO stack, either TLSF, or standard malloc().
--enable-malloc is false by default (i.e. TLSF enabled).
> + if ( ring_mem == 0) { errno = errnoSet(S_memLib_NOT_ENOUGH_MEMORY); return 0; }
> +
Please compare pointers to NULL (and return null pointers the same way), that
gives a better hint about the pointerness of the data involved.
> + ring = (RING_DESCRIPTOR *) ring_mem;
Cast is useless; let's remove visual clutter as much as we can. Actually,
ring_mem is useless as well; you could optimally work only using the ring
variable directly. Reducing the number of variable hops allows people to work
late at night with half a brain.
> + ring->magic = WIND_RING_MAGIC;
> + ring->bufSize = nbytes;
> + ring->readPos = 0;
> + ring->writePos = 0;
Nitpicking alert: line-feed please. It is visually easier to locate the main
return value.
> + return (RING_ID) ring_mem;
> +}
> +
> +
> +void rngDelete(RING_ID ring_id)
> +{
> + RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
> + if (ring->magic != WIND_RING_MAGIC) return;
K&R
> + ring->magic = 0;
> + free(ring);
xnfree() is the converse call for xnmalloc().
> +}
> +
> +
> +void rngFlush(RING_ID ring_id)
> +{
> + RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
> + if (ring->magic != WIND_RING_MAGIC) return;
> + ring->readPos = 0;
> + ring->writePos = 0;
> +}
> +
> +
> +int rngBufGet(RING_ID ring_id,
> + char * buffer,
> + int maxbytes)
> +{
> + RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
> + int j, bytesRead=0;
> + unsigned int savedWritePos = ring->writePos;
linefeed please. Splitting declarations and pure executable statements makes it
easier for the eyes as well.
> + if (ring->magic != WIND_RING_MAGIC) return -ENOSYS;
Mm, I guess VxWorks is not even checking there, right? If it does not, then I
would rather raise an assertion when a bad magic is detected, that would only
trigger with --enable-debug/--enable-assert.
> + for (j=0; j < maxbytes; j++)
> + {
> + if ((ring->readPos) % (ring->bufSize + 1) == savedWritePos)
ring->readPos should never be out of bounds anyway. Do we actually need to
constrain the value to bufSize again?
> + {
Single statement, save energy spent typing, no brace needed.
> + break;
> + }
> + buffer[j] = ring->buffer[ring->readPos];
> + ++bytesRead;
> + ring->readPos = (ring->readPos + 1) % (ring->bufSize + 1);
> + }
> + return bytesRead;
> +}
> +
> +
> +int rngBufPut(RING_ID ring_id,
> + char * buffer,
> + int nbytes)
> +{
> + RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
> + int j, bytesWritten=0;
> + unsigned int savedReadPos = ring->readPos;
> + if (ring->magic != WIND_RING_MAGIC) return -ENOSYS;
> + for (j=0; j < nbytes; j++)
> + {
> + if ((ring->writePos + 1) % (ring->bufSize + 1) == savedReadPos)
> + {
> + break;
> + }
> + ring->buffer[ring->writePos] = buffer[j];
> + ++bytesWritten;
> + ring->writePos = (ring->writePos + 1) % (ring->bufSize + 1);
> + }
> + return bytesWritten;
> +}
Same remarks as for rngBufGet().
More generally, I see off-by-one errors in both rngGet() and rngPut(), the way
they determine the next readable/writable byte index. In the following scenario
for instance, we would write two bytes to the ring buffer at indices #0 et #1,
albeit we only have space for a single character.
rngCreate(1);
rngPut(rng, buf, 1);
rngGet(rng, buf, 1);
rngPut(rng, buf, 1);
Dynamically maintaining a count of free bytes in the ring would allow easy
watermark checks in rngPut() and rngGet(), while providing a straigthforward
implementation for rngIsEmpy(), rngIsFull() and rngFreeBytes().
> +
> +
> +BOOL rngIsEmpty(RING_ID ring_id)
> +{
> + RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
> + if (ring->magic != WIND_RING_MAGIC) return -ENOSYS;
> + return rngFreeBytes(ring_id) == (int) ring->bufSize;
> +}
> +
> +
> +BOOL rngIsFull(RING_ID ring_id)
> +{
> + RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
> + if (ring->magic != WIND_RING_MAGIC) return -ENOSYS;
> + return rngFreeBytes(ring_id) == 0;
> +}
> +
> +
> +int rngFreeBytes(RING_ID ring_id)
> +{
> + RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
> + if (ring->magic != WIND_RING_MAGIC) return -ENOSYS;
> + return ((ring->bufSize - (ring->writePos - ring->readPos)) % (ring->bufSize+1));
> +}
> +
> +
> +int rngNBytes(RING_ID ring_id)
> +{
> + RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
> + if (ring->magic != WIND_RING_MAGIC) return -ENOSYS;
> + return ring->bufSize - rngFreeBytes(ring_id);
> +}
> +
Missing code in the following routines?
> +void rngPutAhead(RING_ID ring_id,
> + char byte,
> + int offset)
> +{
> + RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
> + if (ring->magic != WIND_RING_MAGIC) return;
> + return;
> +}
> +
> +
> +void rngMoveAhead(RING_ID ring_id,
> + int n)
> +{
> + RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
> + if (ring->magic != WIND_RING_MAGIC) return;
> + return;
> +}
> diff --git a/vxworks/rngLib.h b/vxworks/rngLib.h
> new file mode 100644
> index 0000000..d646614
> --- /dev/null
> +++ b/vxworks/rngLib.h
> @@ -0,0 +1,34 @@
> +/*
> + * Copyright (C) 2008 Philippe Gerum <rpm@xenomai.org>.
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library 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
> + * Lesser General Public License for more details.
> +
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
> + */
> +
> +#ifndef _VXWORKS_RNGLIB_H
> +#define _VXWORKS_RNGLIB_H
> +
> +#include <xenomai/syncobj.h>
> +#include <xenomai/heapobj.h>
> +#include <vxworks/rngLib.h>
> +
> +typedef struct {
> + unsigned int magic;
> + unsigned int bufSize;
> + unsigned int readPos;
> + unsigned int writePos;
> + char buffer[];
> +} RING_DESCRIPTOR ;
> +
--
Philippe.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Xenomai-core] [PATCH] solo/vxWorks: add rngLib (with testsuite)
2008-10-26 16:02 ` Philippe Gerum
@ 2008-10-28 16:11 ` Niklaus Giger
0 siblings, 0 replies; 3+ messages in thread
From: Niklaus Giger @ 2008-10-28 16:11 UTC (permalink / raw)
To: rpm; +Cc: xenomai-core
[-- Attachment #1: Type: text/plain, Size: 6612 bytes --]
Am Sonntag 26 Oktober 2008 17.02:08 schrieb Philippe Gerum:
> Niklaus Giger wrote:
> > Hi
> >
> > I just found the time to prepare a patch for a substitute for the vxWorks
> > rngLib library I have written quite some time ago.
<..>
Thank you for your review. Attached a corrected version of my patch.
But there a some more points, which I would like to discuss.
> Fair enough, but we would have to pin all VxWorks tasks to the same CPU on
> SMP systems; otherwise, out-of-order memory accesses would kill that code.
>
Can you do it this?
I am not familiar with this kind of problem as I am still running single
processor boards. But I am quite sure that our next board will have two (or
more) processore cores sitting on it. Though I have quite an interest in
providing a correct solution.
I am not familiar with vxWorks-SMP and therefore I am not sure whether it is a
good idea to pin all vxWorks tasks to one CPU or whether the user should be
able to select the tasks he wants. E.g. you might want only the reader and the
writer of a ring or list on one CPU and other ones to other CPU(s).
<..>
> > vxworks/Makefile.in | 18 ++++-
> > vxworks/rngLib.c | 152
> > +++++++++++++++++++++++++++++++++++++++++++ vxworks/rngLib.h |
> > 34 ++++++++++
>
> Something must be missing here. vxworks/rngLib.h should contain internal
> definitions, used by the ring buffer implementation code, and that is
> correct in your code. However, include/vxworks/rngLib.h should provide the
> interface to applications; it seems we are missing such a file.
Sorry, I forgot to do git add include/vxworks/rngLib.h, which is attached now
and which provides the (opaque) interface to the vxWorks users.
> Since we don't want to export the innards of a ring buffer implementation
> to applications, the interface header should only define the opaque ring
> buffer handle type (i.e. typedef intptr_t RING_ID), and the RNG routine
> prototypes.
>
<..>
> Please use the linux-c coding style, basically K&R + preposterously large
> indent tabs (8 chars)
>
Thank you for code snippets for emacs and ident (did put it into my notes as
it is not the first time I have to deal with such problems).
> Emacs can be taught this way:
>
> (defun linux-c-mode ()
> "C mode with adjusted defaults for use with Xenomai."
> (interactive)
> (c-mode)
> (c-set-style "K&R")
> (setq tab-width 8)
> (setq indent-tabs-mode t)
> (setq c-basic-offset 8))
>
> Indent will reformat almost properly with (-T should be used to teach
> indent about the known non-standard types as well):
>
> $ indent -npro -kr -i8 -ts8 -sob -l80 -ss -ncs -cp1
>
> > + ring_mem = malloc( sizeof(RING_DESCRIPTOR*) + nbytes);
>
> The sizeof() argument is wrong. Out-of-bound memory writes are knocking at
> the door.
Thanks for catching this error. The following code should be correct.
ring_mem = xnmalloc(sizeof(RING_DESCRIPTOR) + nbytes + 1);
I need 1 additional byte to be able to use only the read/write-position. This
allows that the reader only modifies the readPosition and ther writer only
the writePosition.
>
> Also, please use xnmalloc(). This call will pull memory from the allocator
> selected at built time for the SOLO stack, either TLSF, or standard
> malloc(). --enable-malloc is false by default (i.e. TLSF enabled).
> > + if ( ring_mem == 0) { errno = errnoSet(S_memLib_NOT_ENOUGH_MEMORY);
> > return 0; } +
Ack.
>
> Please compare pointers to NULL (and return null pointers the same way),
> that gives a better hint about the pointerness of the data involved.
>
Ack.
> > + ring = (RING_DESCRIPTOR *) ring_mem;
>
> Cast is useless; let's remove visual clutter as much as we can. Actually,
> ring_mem is useless as well; you could optimally work only using the ring
> variable directly. Reducing the number of variable hops allows people to
> work late at night with half a brain.
Ack.
>
> > + ring->magic = WIND_RING_MAGIC;
> > + ring->bufSize = nbytes;
> > + ring->readPos = 0;
> > + ring->writePos = 0;
>
> Nitpicking alert: line-feed please. It is visually easier to locate the
> main return value.
Ack.
>
> > + return (RING_ID) ring_mem;
> > +}
> > +
> > +
> > +void rngDelete(RING_ID ring_id)
> > +{
> > + RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
> > + if (ring->magic != WIND_RING_MAGIC) return;
>
Ack.
> K&R
>
> > + ring->magic = 0;
> > + free(ring);
>
> xnfree() is the converse call for xnmalloc().
Ack.
>
<..>
> linefeed please. Splitting declarations and pure executable statements
> makes it easier for the eyes as well.
Ack.
>
> > + if (ring->magic != WIND_RING_MAGIC) return -ENOSYS;
>
> Mm, I guess VxWorks is not even checking there, right? If it does not, then
> I would rather raise an assertion when a bad magic is detected, that would
> only trigger with --enable-debug/--enable-assert.
It is true, that vxWorks does not use a magic.
What is your prefered way to raise an exception?
> > + for (j=0; j < maxbytes; j++)
> > + {
> > + if ((ring->readPos) % (ring->bufSize + 1) == savedWritePos)
>
> ring->readPos should never be out of bounds anyway. Do we actually need to
> constrain the value to bufSize again?
Yes, we do. It happens if you want to get/put more characters from the ring
buffer, than there are available.
> > + {
>
> Single statement, save energy spent typing, no brace needed.
Ack.
<..>
> Same remarks as for rngBufGet().
>
> More generally, I see off-by-one errors in both rngGet() and rngPut(), the
> way they determine the next readable/writable byte index. In the following
> scenario for instance, we would write two bytes to the ring buffer at
> indices #0 et #1, albeit we only have space for a single character.
>
> rngCreate(1);
> rngPut(rng, buf, 1);
> rngGet(rng, buf, 1);
> rngPut(rng, buf, 1);
See my answer for rngCreate. BufferSize is one bigger than bufSize. But you
really have a sharp eye to find corner cases! Added them to my unit test.
> Dynamically maintaining a count of free bytes in the ring would allow easy
> watermark checks in rngPut() and rngGet(), while providing a
> straigthforward implementation for rngIsEmpy(), rngIsFull() and
> rngFreeBytes().
See discussion above. I want any additional dependency on a variable shared
between the reader and the writer thread.
<..>
> Missing code in the following routines?
>
Thanks for spotting them. I never used them, therefore they were very low on
my priority list. But for the sake of completeness I added them with their
corresponding test case.
All testcases were run on my vxWorks board.
> > +void rngPutAhead(RING_ID ring_id,
<..>
Best regards
Niklaus
[-- Attachment #2: 0001-SOLO-Add-vxworks-rngLib-replacement.patch --]
[-- Type: text/x-patch, Size: 20981 bytes --]
From f7eea15b94af58602eef2d5f9c84a69743c94fe8 Mon Sep 17 00:00:00 2001
From: Niklaus Giger <niklaus.giger@domain.hid>
Date: Tue, 28 Oct 2008 17:09:35 +0100
Subject: [PATCH] SOLO: Add vxworks rngLib replacement
---
include/vxworks/Makefile.am | 1 +
include/vxworks/Makefile.in | 1 +
include/vxworks/rngLib.h | 56 +++++++++++
vxworks/Makefile.am | 2 +
vxworks/Makefile.in | 18 +++-
vxworks/rngLib.c | 168 +++++++++++++++++++++++++++++++++
vxworks/rngLib.h | 34 +++++++
vxworks/testsuite/Makefile | 2 +-
vxworks/testsuite/rng-1.c | 215 +++++++++++++++++++++++++++++++++++++++++++
9 files changed, 492 insertions(+), 5 deletions(-)
create mode 100644 include/vxworks/rngLib.h
create mode 100644 vxworks/rngLib.c
create mode 100644 vxworks/rngLib.h
create mode 100644 vxworks/testsuite/rng-1.c
diff --git a/include/vxworks/Makefile.am b/include/vxworks/Makefile.am
index 06dcab2..0c20861 100644
--- a/include/vxworks/Makefile.am
+++ b/include/vxworks/Makefile.am
@@ -7,6 +7,7 @@ includesub_HEADERS = \
lstLib.h \
memPartLib.h \
msgQLib.h \
+ rngLib.h \
semLib.h \
sysLib.h \
taskInfo.h \
diff --git a/include/vxworks/Makefile.in b/include/vxworks/Makefile.in
index 0fdc3c4..ad10fd1 100644
--- a/include/vxworks/Makefile.in
+++ b/include/vxworks/Makefile.in
@@ -205,6 +205,7 @@ includesub_HEADERS = \
lstLib.h \
memPartLib.h \
msgQLib.h \
+ rngLib.h \
semLib.h \
sysLib.h \
taskInfo.h \
diff --git a/include/vxworks/rngLib.h b/include/vxworks/rngLib.h
new file mode 100644
index 0000000..d2bc8fe
--- /dev/null
+++ b/include/vxworks/rngLib.h
@@ -0,0 +1,56 @@
+/*
+ * * Copyright (C) 2008 Niklaus Giger <niklaus.giger@domain.hid>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * This file satisfies the references within the emulator code
+ * mimicking a VxWorks-like API built upon the Xenomai/SOLO core.
+ *
+ * VxWorks is a registered trademark of Wind River Systems, Inc.
+ */
+
+#ifndef _XENOMAI_VXWORKS_RNGLIB_H
+#define _XENOMAI_VXWORKS_RNGLIB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ typedef int *RING_ID;
+
+ RING_ID rngCreate(int nbytes);
+
+ void rngDelete(RING_ID ringId);
+
+ void rngFlush(RING_ID ringId);
+
+ int rngBufGet(RING_ID rngId, char *buffer, int maxbytes);
+
+ int rngBufPut(RING_ID rngId, char *buffer, int nbytes);
+
+ BOOL rngIsEmpty(RING_ID ringId);
+
+ BOOL rngIsFull(RING_ID ringId);
+
+ int rngFreeBytes(RING_ID ringId);
+
+ int rngNBytes(RING_ID ringId);
+ void rngPutAhead(RING_ID ringId, char byte, int offset);
+ void rngMoveAhead(RING_ID ringId, int n);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !_XENOMAI_VXWORKS_RNGLIB_H */
diff --git a/vxworks/Makefile.am b/vxworks/Makefile.am
index 08e7cc8..a64141e 100644
--- a/vxworks/Makefile.am
+++ b/vxworks/Makefile.am
@@ -11,6 +11,8 @@ libvxworks_la_SOURCES = \
memPartLib.h \
msgQLib.c \
msgQLib.h \
+ rngLib.c \
+ rngLib.h \
semLib.c \
semLib.h \
taskLib.c \
diff --git a/vxworks/Makefile.in b/vxworks/Makefile.in
index b8d0ce7..2d08bbd 100644
--- a/vxworks/Makefile.in
+++ b/vxworks/Makefile.in
@@ -57,10 +57,10 @@ libvxworks_la_LIBADD =
am_libvxworks_la_OBJECTS = libvxworks_la-errnoLib.lo \
libvxworks_la-intLib.lo libvxworks_la-kernelLib.lo \
libvxworks_la-lstLib.lo libvxworks_la-memPartLib.lo \
- libvxworks_la-msgQLib.lo libvxworks_la-semLib.lo \
- libvxworks_la-taskLib.lo libvxworks_la-taskInfo.lo \
- libvxworks_la-tickLib.lo libvxworks_la-wdLib.lo \
- libvxworks_la-sysLib.lo
+ libvxworks_la-msgQLib.lo libvxworks_la-rngLib.lo \
+ libvxworks_la-semLib.lo libvxworks_la-taskLib.lo \
+ libvxworks_la-taskInfo.lo libvxworks_la-tickLib.lo \
+ libvxworks_la-wdLib.lo libvxworks_la-sysLib.lo
libvxworks_la_OBJECTS = $(am_libvxworks_la_OBJECTS)
libvxworks_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@@ -232,6 +232,8 @@ libvxworks_la_SOURCES = \
memPartLib.h \
msgQLib.c \
msgQLib.h \
+ rngLib.c \
+ rngLib.h \
semLib.c \
semLib.h \
taskLib.c \
@@ -324,6 +326,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@domain.hid@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@domain.hid.Plo@domain.hid@
@AMDEP_TRUE@@am__include@ @am__quote@domain.hid@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@domain.hid@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@domain.hid@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@domain.hid@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@domain.hido@domain.hid@
@@ -394,6 +397,13 @@ libvxworks_la-msgQLib.lo: msgQLib.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvxworks_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libvxworks_la-msgQLib.lo `test -f 'msgQLib.c' || echo '$(srcdir)/'`msgQLib.c
+libvxworks_la-rngLib.lo: rngLib.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvxworks_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libvxworks_la-rngLib.lo -MD -MP -MF $(DEPDIR)/libvxworks_la-rngLib.Tpo -c -o libvxworks_la-rngLib.lo `test -f 'rngLib.c' || echo '$(srcdir)/'`rngLib.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libvxworks_la-rngLib.Tpo $(DEPDIR)/libvxworks_la-rngLib.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='rngLib.c' object='libvxworks_la-rngLib.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvxworks_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libvxworks_la-rngLib.lo `test -f 'rngLib.c' || echo '$(srcdir)/'`rngLib.c
+
libvxworks_la-semLib.lo: semLib.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvxworks_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libvxworks_la-semLib.lo -MD -MP -MF $(DEPDIR)/libvxworks_la-semLib.Tpo -c -o libvxworks_la-semLib.lo `test -f 'semLib.c' || echo '$(srcdir)/'`semLib.c
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libvxworks_la-semLib.Tpo $(DEPDIR)/libvxworks_la-semLib.Plo
diff --git a/vxworks/rngLib.c b/vxworks/rngLib.c
new file mode 100644
index 0000000..19144b4
--- /dev/null
+++ b/vxworks/rngLib.c
@@ -0,0 +1,168 @@
+/*
+* Copyright (C) 2008 Niklaus Giger <niklaus.giger@domain.hid>.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2 of the License, or (at your option) any later version.
+*
+* This library 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
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+*/
+
+#include <stdlib.h>
+#include <vxworks/errnoLib.h>
+#include "rngLib.h"
+
+#define WIND_RING_MAGIC 0x5432affe
+
+RING_ID rngCreate(int nbytes)
+{
+ RING_DESCRIPTOR *ring;
+ void *ring_mem;
+
+ if (nbytes <= 0) {
+ errnoSet(S_memLib_NOT_ENOUGH_MEMORY);
+ return 0;
+ }
+ ring_mem = xnmalloc(sizeof(RING_DESCRIPTOR) + nbytes + 1);
+ if (ring_mem == NULL) {
+ errno = errnoSet(S_memLib_NOT_ENOUGH_MEMORY);
+ return 0;
+ }
+
+ ring = (RING_DESCRIPTOR *) ring_mem;
+ ring->magic = WIND_RING_MAGIC;
+ ring->bufSize = nbytes;
+ ring->readPos = 0;
+ ring->writePos = 0;
+
+ return (RING_ID) ring_mem;
+}
+
+void rngDelete(RING_ID ring_id)
+{
+ RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
+
+ if (ring->magic != WIND_RING_MAGIC)
+ return;
+ ring->magic = 0;
+ xnfree(ring);
+}
+
+void rngFlush(RING_ID ring_id)
+{
+ RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
+
+ if (ring->magic != WIND_RING_MAGIC)
+ return;
+ ring->readPos = 0;
+ ring->writePos = 0;
+}
+
+int rngBufGet(RING_ID ring_id, char *buffer, int maxbytes)
+{
+ RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
+ int j, bytesRead = 0;
+ unsigned int savedWritePos = ring->writePos;
+
+ if (ring->magic != WIND_RING_MAGIC)
+ return -ENOSYS;
+ for (j = 0; j < maxbytes; j++) {
+ if ((ring->readPos) % (ring->bufSize + 1) == savedWritePos) {
+ break;
+ }
+ buffer[j] = ring->buffer[ring->readPos];
+ ++bytesRead;
+ ring->readPos = (ring->readPos + 1) % (ring->bufSize + 1);
+ }
+
+ return bytesRead;
+}
+
+int rngBufPut(RING_ID ring_id, char *buffer, int nbytes)
+{
+ RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
+ int j, bytesWritten = 0;
+ unsigned int savedReadPos = ring->readPos;
+
+ if (ring->magic != WIND_RING_MAGIC)
+ return ERROR;
+ for (j = 0; j < nbytes; j++) {
+ if ((ring->writePos + 1) % (ring->bufSize + 1) == savedReadPos) {
+ break;
+ }
+ ring->buffer[ring->writePos] = buffer[j];
+ ++bytesWritten;
+ ring->writePos = (ring->writePos + 1) % (ring->bufSize + 1);
+ }
+
+ return bytesWritten;
+}
+
+BOOL rngIsEmpty(RING_ID ring_id)
+{
+ RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
+
+ if (ring->magic != WIND_RING_MAGIC)
+ return -ENOSYS;
+ return rngFreeBytes(ring_id) == (int)ring->bufSize;
+}
+
+BOOL rngIsFull(RING_ID ring_id)
+{
+ RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
+
+ if (ring->magic != WIND_RING_MAGIC)
+ return -ENOSYS;
+ return rngFreeBytes(ring_id) == 0;
+}
+
+int rngFreeBytes(RING_ID ring_id)
+{
+ RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
+
+ if (ring->magic != WIND_RING_MAGIC)
+ return -ENOSYS;
+
+ return ((ring->bufSize -
+ (ring->writePos - ring->readPos)) % (ring->bufSize + 1));
+}
+
+int rngNBytes(RING_ID ring_id)
+{
+ RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
+
+ if (ring->magic != WIND_RING_MAGIC)
+ return -ENOSYS;
+
+ return ring->bufSize - rngFreeBytes(ring_id);
+}
+
+void rngPutAhead(RING_ID ring_id, char byte, int offset)
+{
+ RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
+ int where;
+
+ if (ring->magic != WIND_RING_MAGIC)
+ return;
+ where = (ring->writePos + offset) % (ring->bufSize + 1);
+ ring->buffer[where] = byte;
+}
+
+void rngMoveAhead(RING_ID ring_id, int n)
+{
+ RING_DESCRIPTOR *ring = (RING_DESCRIPTOR *) ring_id;
+
+ if (ring->magic != WIND_RING_MAGIC)
+ return;
+ /* ring->writePos = (ring->writePos + n) % (ring->bufSize + 1); */
+ ring->writePos += n;
+ ring->writePos %= (ring->bufSize + 1);
+}
diff --git a/vxworks/rngLib.h b/vxworks/rngLib.h
new file mode 100644
index 0000000..eeb324c
--- /dev/null
+++ b/vxworks/rngLib.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2008 Philippe Gerum <rpm@xenomai.org>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _VXWORKS_RNGLIB_H
+#define _VXWORKS_RNGLIB_H
+
+#include <xenomai/syncobj.h>
+#include <xenomai/heapobj.h>
+#include <vxworks/rngLib.h>
+
+typedef struct {
+ unsigned int magic;
+ unsigned int bufSize;
+ unsigned int readPos;
+ unsigned int writePos;
+ unsigned char buffer[];
+} RING_DESCRIPTOR;
+
+#endif /* _VXWORKS_RNGLIB_H */
diff --git a/vxworks/testsuite/Makefile b/vxworks/testsuite/Makefile
index d1ce203..d391406 100644
--- a/vxworks/testsuite/Makefile
+++ b/vxworks/testsuite/Makefile
@@ -5,7 +5,7 @@ ifeq ($(prefix),)
$(error Please add <xenomai-install-path>/bin to your PATH variable)
endif
-TESTS := task-1 task-2 msgQ-1 msgQ-2 msgQ-3 wd-1 sem-1 sem-2 sem-3 sem-4 lst-1
+TESTS := task-1 task-2 msgQ-1 msgQ-2 msgQ-3 wd-1 sem-1 sem-2 sem-3 sem-4 lst-1 rng-1
CFLAGS := $(shell $(XENO_CONFIG) --cflags) -g
LDFLAGS := -lvxworks $(shell $(XENO_CONFIG) --ldflags)
diff --git a/vxworks/testsuite/rng-1.c b/vxworks/testsuite/rng-1.c
new file mode 100644
index 0000000..48a2d72
--- /dev/null
+++ b/vxworks/testsuite/rng-1.c
@@ -0,0 +1,215 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <xenomai/traceobj.h>
+#include <vxworks/errnoLib.h>
+#include <vxworks/taskLib.h>
+#include <vxworks/rngLib.h>
+
+static struct traceobj trobj;
+
+#define ADD_CONTENT(buffer,bytes,counter) \
+ { \
+ char *bufPtr = buffer; \
+ for (k=0; k<bytes; k++) { \
+ *bufPtr = counter; \
+ counter ++; \
+ bufPtr ++; \
+ } \
+ }
+
+#define CHECK_CONTENT(buffer,bytes,counter) \
+ { \
+ unsigned char *bufPtr = buffer; \
+ for (k=0; k<bytes; k++) { \
+ traceobj_assert(&trobj, *bufPtr == (unsigned char)counter); \
+ counter ++; \
+ bufPtr ++; \
+ } \
+ }
+
+void rootTask(long a0, long a1, long a2, long a3, long a4,
+ long a5, long a6, long a7, long a8, long a9)
+{
+ RING_ID ring;
+
+ int j, res, k, chunks;
+ const int putBytes = 10;
+ const int nrChunks = 3;
+ const int rngBytes = putBytes * nrChunks;
+ char buffer[putBytes];
+ char bigBuffer[putBytes * 2 * nrChunks];
+ int bytesPut;
+ int bytesGot;
+ int expectedCounter = 0;
+ int checkCounter = 0;
+ RING_ID rng;
+ char not_a_ring[32];
+
+ traceobj_enter(&trobj);
+ ADD_CONTENT(buffer, sizeof(buffer), expectedCounter);
+ rng = rngCreate(1);
+ traceobj_assert(&trobj, rngIsEmpty(rng));
+ memset(buffer, 0, sizeof(buffer));
+ buffer[0] = 17;
+ rngBufPut(rng, buffer, 1);
+ traceobj_assert(&trobj, rngIsFull(rng));
+ rngBufGet(rng, buffer, 1);
+ traceobj_assert(&trobj, rngIsEmpty(rng));
+ buffer[0] = 34;
+ rngBufPut(rng, buffer, 1);
+ traceobj_assert(&trobj, rngIsFull(rng));
+ expectedCounter = 0;
+ rngDelete(rng);
+
+ /* Here real vxWorks 6.6 just return ERROR */
+ memset(not_a_ring, 0, sizeof(not_a_ring));
+ errnoSet(0);
+ res = rngBufPut((RING_ID) & not_a_ring[0], buffer, 1);
+ traceobj_assert(&trobj, res == ERROR);
+
+/* rng = rngCreate(1 * 1024 * 1024 * 1024);
+ traceobj_assert(&trobj, res == ERROR);
+ traceobj_assert(&trobj, errnoGet() == S_memLib_NOT_ENOUGH_MEMORY);
+ */
+ rng = rngCreate(rngBytes);
+ traceobj_assert(&trobj, rng != 0);
+ traceobj_assert(&trobj, rngIsEmpty(rng));
+ traceobj_assert(&trobj, !rngIsFull(rng));
+
+ /* Fill a few chunks */
+ for (chunks = 0; chunks < nrChunks; chunks++) {
+ traceobj_assert(&trobj,
+ rngNBytes(rng) == chunks * (int)sizeof(buffer));
+ traceobj_assert(&trobj,
+ rngFreeBytes(rng) ==
+ rngBytes - chunks * (int)sizeof(buffer));
+ for (j = 0; j < (int)sizeof(buffer); j++) {
+ buffer[j] = (char)j + (int)sizeof(buffer) * chunks;
+ }
+ ADD_CONTENT(buffer, sizeof(buffer), checkCounter);
+ bytesPut = rngBufPut(rng, &buffer[0], sizeof(buffer));
+ traceobj_assert(&trobj, bytesPut == sizeof(buffer));
+ traceobj_assert(&trobj, !rngIsEmpty(rng));
+ traceobj_assert(&trobj,
+ rngIsFull(rng) == (nrChunks - 1 == chunks));
+ traceobj_assert(&trobj,
+ rngFreeBytes(rng) ==
+ rngBytes - bytesPut * (chunks + 1));
+ traceobj_assert(&trobj,
+ rngNBytes(rng) ==
+ (chunks + 1) * (int)sizeof(buffer));
+ }
+ traceobj_assert(&trobj, rngIsFull(rng));
+ ADD_CONTENT(buffer, sizeof(buffer), checkCounter);
+ bytesPut = rngBufPut(rng, &buffer[0], sizeof(buffer));
+ traceobj_assert(&trobj, bytesPut == 0);
+ traceobj_assert(&trobj, rngIsFull(rng));
+
+ /* Read chunks back and check content */
+ for (chunks = 0; chunks < nrChunks; chunks++) {
+ memset(buffer, 0, sizeof(buffer));
+ traceobj_assert(&trobj,
+ rngNBytes(rng) ==
+ (nrChunks - chunks) * (int)sizeof(buffer));
+ traceobj_assert(&trobj,
+ rngFreeBytes(rng) ==
+ chunks * (int)sizeof(buffer));
+ bytesGot = rngBufGet(rng, &buffer[0], sizeof(buffer));
+ traceobj_assert(&trobj, bytesGot == (int)sizeof(buffer));
+ CHECK_CONTENT(buffer, (unsigned int)bytesGot, expectedCounter);
+ traceobj_assert(&trobj, !rngIsFull(rng));
+ traceobj_assert(&trobj,
+ rngIsEmpty(rng) == (chunks == nrChunks - 1));
+
+ traceobj_assert(&trobj,
+ rngFreeBytes(rng) ==
+ (chunks + 1) * (int)sizeof(buffer));
+ traceobj_assert(&trobj,
+ rngNBytes(rng) ==
+ (nrChunks - chunks - 1) * (int)sizeof(buffer));
+ }
+
+ /* Testing filling too many */
+ ADD_CONTENT(bigBuffer, sizeof(bigBuffer), checkCounter)
+ bytesPut = rngBufPut(rng, &bigBuffer[0], sizeof(bigBuffer));
+ traceobj_assert(&trobj, bytesPut == rngBytes);
+ traceobj_assert(&trobj, !rngIsEmpty(rng));
+ traceobj_assert(&trobj, rngIsFull(rng));
+ traceobj_assert(&trobj, rngFreeBytes(rng) == 0);
+ traceobj_assert(&trobj, rngNBytes(rng) == rngBytes);
+
+ /* Getting too many */
+ memset(bigBuffer, 0, sizeof(bigBuffer));
+ bytesGot = rngBufGet(rng, &bigBuffer[0], sizeof(bigBuffer));
+ traceobj_assert(&trobj, bytesGot == rngBytes);
+ traceobj_assert(&trobj, rngIsEmpty(rng));
+ traceobj_assert(&trobj, !rngIsFull(rng));
+ traceobj_assert(&trobj, rngFreeBytes(rng) == rngBytes);
+ traceobj_assert(&trobj, rngNBytes(rng) == 0);
+
+ /* Now we need to adjust our expectedCounter */
+ expectedCounter += sizeof(buffer);
+
+ CHECK_CONTENT(bigBuffer, (unsigned int)bytesGot, expectedCounter);
+
+ ADD_CONTENT(bigBuffer, sizeof(bigBuffer), checkCounter);
+ bytesPut = rngBufPut(rng, &bigBuffer[0], sizeof(bigBuffer));
+ traceobj_assert(&trobj, bytesPut == rngBytes);
+ rngFlush(rng);
+ traceobj_assert(&trobj, rngIsEmpty(rng));
+ traceobj_assert(&trobj, !rngIsFull(rng));
+ traceobj_assert(&trobj, rngFreeBytes(rng) == rngBytes);
+ traceobj_assert(&trobj, rngNBytes(rng) == 0);
+ while (bytesGot > 0) {
+ bytesGot = rngBufGet(rng, &bigBuffer[0], sizeof(bigBuffer));
+ CHECK_CONTENT(bigBuffer, (unsigned int)bytesGot,
+ expectedCounter);
+ }
+ rngDelete(rng);
+
+ chunks = 10;
+ rng = rngCreate(chunks);
+ bytesPut = 5;
+ traceobj_assert(&trobj, rngFreeBytes(rng) > bytesPut);
+ checkCounter = 0xaa;
+ expectedCounter = checkCounter;
+ for (j = 0; j < bytesPut; j++) {
+ rngPutAhead(rng, checkCounter, j);
+ checkCounter++;
+ }
+ rngMoveAhead(rng, bytesPut);
+ bytesGot = rngBufGet(rng, &bigBuffer[0], sizeof(bigBuffer));
+ traceobj_assert(&trobj, bytesGot == bytesPut);
+ CHECK_CONTENT(bigBuffer, (unsigned int)bytesGot, expectedCounter);
+
+ /* Check also wrap-around */
+ bytesPut = chunks -2;
+ traceobj_assert(&trobj, rngFreeBytes(rng) > bytesPut);
+ checkCounter = 0xaa;
+ expectedCounter = checkCounter;
+ for (j = 0; j < bytesPut; j++) {
+ rngPutAhead(rng, checkCounter, j);
+ checkCounter++;
+ }
+ rngMoveAhead(rng, bytesPut);
+ bytesGot = rngBufGet(rng, &bigBuffer[0], sizeof(bigBuffer));
+ traceobj_assert(&trobj, bytesGot == bytesPut);
+ CHECK_CONTENT(bigBuffer, (unsigned int)bytesGot, expectedCounter);
+ rngDelete(rng);
+
+ traceobj_exit(&trobj);
+}
+
+int main(int argc, char *argv[])
+{
+ int ret;
+
+ traceobj_init(&trobj, argv[0], 0);
+
+ ret = kernelInit(rootTask, argc, argv);
+ traceobj_assert(&trobj, ret == OK);
+
+ traceobj_join(&trobj);
+ exit(0);
+}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2008-10-28 16:11 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-10-24 21:48 [Xenomai-core] [PATCH] solo/vxWorks: add rngLib (with testsuite) Niklaus Giger
2008-10-26 16:02 ` Philippe Gerum
2008-10-28 16:11 ` Niklaus Giger
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.