DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 1/3] eal: add core id param to eal_thread_set_affinity
       [not found] <1410445387-4849-1-git-send-email-bruce.richardson@intel.com>
@ 2014-09-11 14:23 ` Bruce Richardson
  2014-09-11 14:23 ` [dpdk-dev] [PATCH 2/3] eal: increase scope of eal_thread_set_affinity Bruce Richardson
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Bruce Richardson @ 2014-09-11 14:23 UTC (permalink / raw)
  To: dev

the function eal_thread_set_affinity always sets the affinity of the
thread to the lcore_id of the thread as given by the thread-local
variable. To allow this function to be used by arbitrary threads
(e.g. eal utility threads such as those for interrupts, timers, etc.),
add a parameter to specify the core id to be used for the affinity.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
 lib/librte_eal/bsdapp/eal/eal_thread.c   | 10 +++++-----
 lib/librte_eal/linuxapp/eal/eal_thread.c | 10 +++++-----
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal_thread.c b/lib/librte_eal/bsdapp/eal/eal_thread.c
index ab05368..18df2a3 100644
--- a/lib/librte_eal/bsdapp/eal/eal_thread.c
+++ b/lib/librte_eal/bsdapp/eal/eal_thread.c
@@ -96,7 +96,7 @@ rte_eal_remote_launch(int (*f)(void *), void *arg, unsigned slave_id)
 
 /* set affinity for current thread */
 static int
-eal_thread_set_affinity(void)
+eal_thread_set_affinity(unsigned lcore_id)
 {
 	int s;
 	pthread_t thread;
@@ -126,7 +126,7 @@ eal_thread_set_affinity(void)
 
 	size = CPU_ALLOC_SIZE(RTE_MAX_LCORE);
 	CPU_ZERO_S(size, cpusetp);
-	CPU_SET_S(rte_lcore_id(), size, cpusetp);
+	CPU_SET_S(lcore_id, size, cpusetp);
 
 	thread = pthread_self();
 	s = pthread_setaffinity_np(thread, size, cpusetp);
@@ -140,7 +140,7 @@ eal_thread_set_affinity(void)
 #else /* CPU_ALLOC */
 	cpuset_t cpuset;
 	CPU_ZERO( &cpuset );
-	CPU_SET( rte_lcore_id(), &cpuset );
+	CPU_SET(lcore_id, &cpuset );
 
 	thread = pthread_self();
 	s = pthread_setaffinity_np(thread, sizeof( cpuset ), &cpuset);
@@ -158,7 +158,7 @@ void eal_thread_init_master(unsigned lcore_id)
 	RTE_PER_LCORE(_lcore_id) = lcore_id;
 
 	/* set CPU affinity */
-	if (eal_thread_set_affinity() < 0)
+	if (eal_thread_set_affinity(lcore_id) < 0)
 		rte_panic("cannot set affinity\n");
 }
 
@@ -192,7 +192,7 @@ eal_thread_loop(__attribute__((unused)) void *arg)
 	RTE_PER_LCORE(_lcore_id) = lcore_id;
 
 	/* set CPU affinity */
-	if (eal_thread_set_affinity() < 0)
+	if (eal_thread_set_affinity(lcore_id) < 0)
 		rte_panic("cannot set affinity\n");
 
 	/* read on our pipe to get commands */
diff --git a/lib/librte_eal/linuxapp/eal/eal_thread.c b/lib/librte_eal/linuxapp/eal/eal_thread.c
index 80a985f..9dc3f98 100644
--- a/lib/librte_eal/linuxapp/eal/eal_thread.c
+++ b/lib/librte_eal/linuxapp/eal/eal_thread.c
@@ -96,7 +96,7 @@ rte_eal_remote_launch(int (*f)(void *), void *arg, unsigned slave_id)
 
 /* set affinity for current thread */
 static int
-eal_thread_set_affinity(void)
+eal_thread_set_affinity(unsigned lcore_id)
 {
 	int s;
 	pthread_t thread;
@@ -126,7 +126,7 @@ eal_thread_set_affinity(void)
 
 	size = CPU_ALLOC_SIZE(RTE_MAX_LCORE);
 	CPU_ZERO_S(size, cpusetp);
-	CPU_SET_S(rte_lcore_id(), size, cpusetp);
+	CPU_SET_S(lcore_id, size, cpusetp);
 
 	thread = pthread_self();
 	s = pthread_setaffinity_np(thread, size, cpusetp);
@@ -140,7 +140,7 @@ eal_thread_set_affinity(void)
 #else /* CPU_ALLOC */
 	cpu_set_t cpuset;
 	CPU_ZERO( &cpuset );
-	CPU_SET( rte_lcore_id(), &cpuset );
+	CPU_SET(lcore_id, &cpuset);
 
 	thread = pthread_self();
 	s = pthread_setaffinity_np(thread, sizeof( cpuset ), &cpuset);
@@ -158,7 +158,7 @@ void eal_thread_init_master(unsigned lcore_id)
 	RTE_PER_LCORE(_lcore_id) = lcore_id;
 
 	/* set CPU affinity */
-	if (eal_thread_set_affinity() < 0)
+	if (eal_thread_set_affinity(lcore_id) < 0)
 		rte_panic("cannot set affinity\n");
 }
 
@@ -192,7 +192,7 @@ eal_thread_loop(__attribute__((unused)) void *arg)
 	RTE_PER_LCORE(_lcore_id) = lcore_id;
 
 	/* set CPU affinity */
-	if (eal_thread_set_affinity() < 0)
+	if (eal_thread_set_affinity(lcore_id) < 0)
 		rte_panic("cannot set affinity\n");
 
 	/* read on our pipe to get commands */
-- 
1.9.3

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [dpdk-dev] [PATCH 2/3] eal: increase scope of eal_thread_set_affinity
       [not found] <1410445387-4849-1-git-send-email-bruce.richardson@intel.com>
  2014-09-11 14:23 ` [dpdk-dev] [PATCH 1/3] eal: add core id param to eal_thread_set_affinity Bruce Richardson
@ 2014-09-11 14:23 ` Bruce Richardson
  2014-09-11 14:23 ` [dpdk-dev] [PATCH 3/3] eal: affinitize low-priority threads to lcore 0 Bruce Richardson
  2014-09-11 23:47 ` [dpdk-dev] [PATCH 0/3] eal affinitize low priority " Hiroshi Shimamoto
  3 siblings, 0 replies; 6+ messages in thread
From: Bruce Richardson @ 2014-09-11 14:23 UTC (permalink / raw)
  To: dev

This patch changes eal_thread_set_affinity to the EAL-local function
rte_eal_thread_set_affinity. This will allow us to use the function
anywhere else in the EAL, while not having it part of the official APIs

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
 lib/librte_eal/bsdapp/eal/eal_thread.c      |  8 ++++----
 lib/librte_eal/common/include/eal_private.h | 10 ++++++++++
 lib/librte_eal/linuxapp/eal/eal_thread.c    |  8 ++++----
 3 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal_thread.c b/lib/librte_eal/bsdapp/eal/eal_thread.c
index 18df2a3..66191bb 100644
--- a/lib/librte_eal/bsdapp/eal/eal_thread.c
+++ b/lib/librte_eal/bsdapp/eal/eal_thread.c
@@ -95,8 +95,8 @@ rte_eal_remote_launch(int (*f)(void *), void *arg, unsigned slave_id)
 }
 
 /* set affinity for current thread */
-static int
-eal_thread_set_affinity(unsigned lcore_id)
+int
+rte_eal_thread_set_affinity(unsigned lcore_id)
 {
 	int s;
 	pthread_t thread;
@@ -158,7 +158,7 @@ void eal_thread_init_master(unsigned lcore_id)
 	RTE_PER_LCORE(_lcore_id) = lcore_id;
 
 	/* set CPU affinity */
-	if (eal_thread_set_affinity(lcore_id) < 0)
+	if (rte_eal_thread_set_affinity(lcore_id) < 0)
 		rte_panic("cannot set affinity\n");
 }
 
@@ -192,7 +192,7 @@ eal_thread_loop(__attribute__((unused)) void *arg)
 	RTE_PER_LCORE(_lcore_id) = lcore_id;
 
 	/* set CPU affinity */
-	if (eal_thread_set_affinity(lcore_id) < 0)
+	if (rte_eal_thread_set_affinity(lcore_id) < 0)
 		rte_panic("cannot set affinity\n");
 
 	/* read on our pipe to get commands */
diff --git a/lib/librte_eal/common/include/eal_private.h b/lib/librte_eal/common/include/eal_private.h
index b440ffb..0f01f81 100644
--- a/lib/librte_eal/common/include/eal_private.h
+++ b/lib/librte_eal/common/include/eal_private.h
@@ -196,4 +196,14 @@ int rte_eal_intr_init(void);
  */
 int rte_eal_alarm_init(void);
 
+/**
+ * Set the affinity of the current thread to a given core
+ *
+ * This function is private to EAL.
+ *
+ * @return
+ *  0 on success, negative on error
+ */
+int rte_eal_thread_set_affinity(unsigned lcore_id);
+
 #endif /* _EAL_PRIVATE_H_ */
diff --git a/lib/librte_eal/linuxapp/eal/eal_thread.c b/lib/librte_eal/linuxapp/eal/eal_thread.c
index 9dc3f98..cf5e75c 100644
--- a/lib/librte_eal/linuxapp/eal/eal_thread.c
+++ b/lib/librte_eal/linuxapp/eal/eal_thread.c
@@ -95,8 +95,8 @@ rte_eal_remote_launch(int (*f)(void *), void *arg, unsigned slave_id)
 }
 
 /* set affinity for current thread */
-static int
-eal_thread_set_affinity(unsigned lcore_id)
+int
+rte_eal_thread_set_affinity(unsigned lcore_id)
 {
 	int s;
 	pthread_t thread;
@@ -158,7 +158,7 @@ void eal_thread_init_master(unsigned lcore_id)
 	RTE_PER_LCORE(_lcore_id) = lcore_id;
 
 	/* set CPU affinity */
-	if (eal_thread_set_affinity(lcore_id) < 0)
+	if (rte_eal_thread_set_affinity(lcore_id) < 0)
 		rte_panic("cannot set affinity\n");
 }
 
@@ -192,7 +192,7 @@ eal_thread_loop(__attribute__((unused)) void *arg)
 	RTE_PER_LCORE(_lcore_id) = lcore_id;
 
 	/* set CPU affinity */
-	if (eal_thread_set_affinity(lcore_id) < 0)
+	if (rte_eal_thread_set_affinity(lcore_id) < 0)
 		rte_panic("cannot set affinity\n");
 
 	/* read on our pipe to get commands */
-- 
1.9.3

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [dpdk-dev] [PATCH 3/3] eal: affinitize low-priority threads to lcore 0
       [not found] <1410445387-4849-1-git-send-email-bruce.richardson@intel.com>
  2014-09-11 14:23 ` [dpdk-dev] [PATCH 1/3] eal: add core id param to eal_thread_set_affinity Bruce Richardson
  2014-09-11 14:23 ` [dpdk-dev] [PATCH 2/3] eal: increase scope of eal_thread_set_affinity Bruce Richardson
@ 2014-09-11 14:23 ` Bruce Richardson
  2014-09-11 23:47 ` [dpdk-dev] [PATCH 0/3] eal affinitize low priority " Hiroshi Shimamoto
  3 siblings, 0 replies; 6+ messages in thread
From: Bruce Richardson @ 2014-09-11 14:23 UTC (permalink / raw)
  To: dev

There are extra utility threads inside the linuxapp EAL, for managing
things like interrupts, requests for the vfio file handle for
multi-process, and hpet timer management. These are mostly sleeping, but
to avoid any possibility of conflict with threads handling packets, this
patch affinitizes those threads to lcore 0 explicitly.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
 lib/librte_eal/linuxapp/eal/eal_interrupts.c       | 5 +++++
 lib/librte_eal/linuxapp/eal/eal_pci_vfio_mp_sync.c | 6 ++++++
 lib/librte_eal/linuxapp/eal/eal_timer.c            | 5 +++++
 3 files changed, 16 insertions(+)

diff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
index dc2668a..6227f2b 100644
--- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c
+++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
@@ -739,6 +739,11 @@ eal_intr_thread_main(__rte_unused void *arg)
 {
 	struct epoll_event ev;
 
+	/* set our affinity to lcore 0 so we never interfere with the normal
+	 * data-plane threads. Lcore 0 is used by Linux so is subject to
+	 * interruptions anyway. */
+	rte_eal_thread_set_affinity(0);
+
 	/* host thread, never break out */
 	for (;;) {
 		/* build up the epoll fd with all descriptors we are to
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_vfio_mp_sync.c b/lib/librte_eal/linuxapp/eal/eal_pci_vfio_mp_sync.c
index 6588fb1..ccccbdb 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci_vfio_mp_sync.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci_vfio_mp_sync.c
@@ -53,6 +53,7 @@
 #include <rte_eal_memconfig.h>
 #include <rte_malloc.h>
 
+#include <eal_private.h>
 #include "eal_filesystem.h"
 #include "eal_pci_init.h"
 
@@ -268,6 +269,11 @@ pci_vfio_mp_sync_thread(void __rte_unused * arg)
 {
 	int ret, fd, vfio_group_no;
 
+	/* set our affinity to lcore 0 so we never interfere with the normal
+	 * data-plane threads. Lcore 0 is used by Linux so is subject to
+	 * interruptions anyway. */
+	rte_eal_thread_set_affinity(0);
+
 	/* wait for requests on the socket */
 	for (;;) {
 		int conn_sock;
diff --git a/lib/librte_eal/linuxapp/eal/eal_timer.c b/lib/librte_eal/linuxapp/eal/eal_timer.c
index ca57916..f61e303 100644
--- a/lib/librte_eal/linuxapp/eal/eal_timer.c
+++ b/lib/librte_eal/linuxapp/eal/eal_timer.c
@@ -125,6 +125,11 @@ hpet_msb_inc(__attribute__((unused)) void *arg)
 {
 	uint32_t t;
 
+	/* set our affinity to lcore 0 so we never interfere with the normal
+	 * data-plane threads. Lcore 0 is used by Linux so is subject to
+	 * interruptions anyway. */
+	rte_eal_thread_set_affinity(0);
+
 	while (1) {
 		t = (eal_hpet->counter_l >> 30);
 		if (t != (eal_hpet_msb & 3))
-- 
1.9.3

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [dpdk-dev] [PATCH 0/3] eal affinitize low priority threads to lcore 0
       [not found] <1410445387-4849-1-git-send-email-bruce.richardson@intel.com>
                   ` (2 preceding siblings ...)
  2014-09-11 14:23 ` [dpdk-dev] [PATCH 3/3] eal: affinitize low-priority threads to lcore 0 Bruce Richardson
@ 2014-09-11 23:47 ` Hiroshi Shimamoto
  2014-09-12  1:24   ` Stephen Hemminger
  2014-09-12  8:07   ` Richardson, Bruce
  3 siblings, 2 replies; 6+ messages in thread
From: Hiroshi Shimamoto @ 2014-09-11 23:47 UTC (permalink / raw)
  To: Bruce Richardson, dev

Hi Bruce,

> Subject: [dpdk-dev] [PATCH 0/3] eal affinitize low priority threads to lcore 0
> 
> This patchset sets things up so that we can affinitize the interrupt,
> vfio management, and hpet timer management threads to lcore 0, so that
> they never interfere with data plane threads.

I don't think it works well always.
The management threads can be floating all cpus on demand, because those
threads are created before the master thread affinity is set. The kernel
scheduler will take care of it. And we should isolate cpus which data plane
threads are pinned to, so the management threads cannot run on those isolated
cpus data plane thread run.
In some cases, the user may run data plane thread on lcore 0, but with
this patchset the data plane pinned to lcore 0 always run with the
management threads. That doesn't seem good.

I think this functionality should be conditional.
How about to add a parameter to specify the mask for the management threads
instead of statically assignment to lcore 0?

thanks,
Hiroshi

> 
> Bruce Richardson (3):
>   eal: add core id param to  eal_thread_set_affinity
>   eal: increase scope of eal_thread_set_affinity
>   eal: affinitize low-priority threads to lcore 0
> 
>  lib/librte_eal/bsdapp/eal/eal_thread.c             | 12 ++++++------
>  lib/librte_eal/common/include/eal_private.h        | 10 ++++++++++
>  lib/librte_eal/linuxapp/eal/eal_interrupts.c       |  5 +++++
>  lib/librte_eal/linuxapp/eal/eal_pci_vfio_mp_sync.c |  6 ++++++
>  lib/librte_eal/linuxapp/eal/eal_thread.c           | 12 ++++++------
>  lib/librte_eal/linuxapp/eal/eal_timer.c            |  5 +++++
>  6 files changed, 38 insertions(+), 12 deletions(-)
> 
> --
> 1.9.3

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [dpdk-dev] [PATCH 0/3] eal affinitize low priority threads to lcore 0
  2014-09-11 23:47 ` [dpdk-dev] [PATCH 0/3] eal affinitize low priority " Hiroshi Shimamoto
@ 2014-09-12  1:24   ` Stephen Hemminger
  2014-09-12  8:07   ` Richardson, Bruce
  1 sibling, 0 replies; 6+ messages in thread
From: Stephen Hemminger @ 2014-09-12  1:24 UTC (permalink / raw)
  To: Hiroshi Shimamoto; +Cc: dev

On Thu, 11 Sep 2014 23:47:52 +0000
Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com> wrote:

> Hi Bruce,
> 
> > Subject: [dpdk-dev] [PATCH 0/3] eal affinitize low priority threads to lcore 0
> > 
> > This patchset sets things up so that we can affinitize the interrupt,
> > vfio management, and hpet timer management threads to lcore 0, so that
> > they never interfere with data plane threads.
> 
> I don't think it works well always.
> The management threads can be floating all cpus on demand, because those
> threads are created before the master thread affinity is set. The kernel
> scheduler will take care of it. And we should isolate cpus which data plane
> threads are pinned to, so the management threads cannot run on those isolated
> cpus data plane thread run.
> In some cases, the user may run data plane thread on lcore 0, but with
> this patchset the data plane pinned to lcore 0 always run with the
> management threads. That doesn't seem good.
> 
> I think this functionality should be conditional.
> How about to add a parameter to specify the mask for the management threads
> instead of statically assignment to lcore 0?
> 
> thanks,
> Hiroshi
> 
> > 
> > Bruce Richardson (3):
> >   eal: add core id param to  eal_thread_set_affinity
> >   eal: increase scope of eal_thread_set_affinity
> >   eal: affinitize low-priority threads to lcore 0
> > 
> >  lib/librte_eal/bsdapp/eal/eal_thread.c             | 12 ++++++------
> >  lib/librte_eal/common/include/eal_private.h        | 10 ++++++++++
> >  lib/librte_eal/linuxapp/eal/eal_interrupts.c       |  5 +++++
> >  lib/librte_eal/linuxapp/eal/eal_pci_vfio_mp_sync.c |  6 ++++++
> >  lib/librte_eal/linuxapp/eal/eal_thread.c           | 12 ++++++------
> >  lib/librte_eal/linuxapp/eal/eal_timer.c            |  5 +++++
> >  6 files changed, 38 insertions(+), 12 deletions(-)
> > 
> > --
> > 1.9.3
> 

We just set the non-master DPDK worker threads to be real time by
using pthread_set_scheduler. This works very well and makes it clear to
Linux scheduler what the intention is. This also improves wakeup behavior
from sleeps.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [dpdk-dev] [PATCH 0/3] eal affinitize low priority threads to lcore 0
  2014-09-11 23:47 ` [dpdk-dev] [PATCH 0/3] eal affinitize low priority " Hiroshi Shimamoto
  2014-09-12  1:24   ` Stephen Hemminger
@ 2014-09-12  8:07   ` Richardson, Bruce
  1 sibling, 0 replies; 6+ messages in thread
From: Richardson, Bruce @ 2014-09-12  8:07 UTC (permalink / raw)
  To: Hiroshi Shimamoto, dev

> -----Original Message-----
> From: Hiroshi Shimamoto [mailto:h-shimamoto@ct.jp.nec.com]
> Sent: Friday, September 12, 2014 12:48 AM
> To: Richardson, Bruce; dev@dpdk.org
> Subject: RE: [dpdk-dev] [PATCH 0/3] eal affinitize low priority threads to lcore 0
> 
> Hi Bruce,
> 
> > Subject: [dpdk-dev] [PATCH 0/3] eal affinitize low priority threads to lcore 0
> >
> > This patchset sets things up so that we can affinitize the interrupt,
> > vfio management, and hpet timer management threads to lcore 0, so that
> > they never interfere with data plane threads.
> 
> I don't think it works well always.
> The management threads can be floating all cpus on demand, because those
> threads are created before the master thread affinity is set. The kernel
> scheduler will take care of it. And we should isolate cpus which data plane
> threads are pinned to, so the management threads cannot run on those isolated
> cpus data plane thread run.

Yes, this was my understanding as well of how things would work - we just had a report back of where the management threads were using the same core as the data-plane despite the core being isolated. I'll double-check to see if this really is happening and resubmit a new patch with a configurable core assignment if it is definitely needed.

/Bruce

> In some cases, the user may run data plane thread on lcore 0, but with
> this patchset the data plane pinned to lcore 0 always run with the
> management threads. That doesn't seem good.
> 
> I think this functionality should be conditional.
> How about to add a parameter to specify the mask for the management threads
> instead of statically assignment to lcore 0?
> 
> thanks,
> Hiroshi
> 
> >
> > Bruce Richardson (3):
> >   eal: add core id param to  eal_thread_set_affinity
> >   eal: increase scope of eal_thread_set_affinity
> >   eal: affinitize low-priority threads to lcore 0
> >
> >  lib/librte_eal/bsdapp/eal/eal_thread.c             | 12 ++++++------
> >  lib/librte_eal/common/include/eal_private.h        | 10 ++++++++++
> >  lib/librte_eal/linuxapp/eal/eal_interrupts.c       |  5 +++++
> >  lib/librte_eal/linuxapp/eal/eal_pci_vfio_mp_sync.c |  6 ++++++
> >  lib/librte_eal/linuxapp/eal/eal_thread.c           | 12 ++++++------
> >  lib/librte_eal/linuxapp/eal/eal_timer.c            |  5 +++++
> >  6 files changed, 38 insertions(+), 12 deletions(-)
> >
> > --
> > 1.9.3

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2014-09-12  8:02 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1410445387-4849-1-git-send-email-bruce.richardson@intel.com>
2014-09-11 14:23 ` [dpdk-dev] [PATCH 1/3] eal: add core id param to eal_thread_set_affinity Bruce Richardson
2014-09-11 14:23 ` [dpdk-dev] [PATCH 2/3] eal: increase scope of eal_thread_set_affinity Bruce Richardson
2014-09-11 14:23 ` [dpdk-dev] [PATCH 3/3] eal: affinitize low-priority threads to lcore 0 Bruce Richardson
2014-09-11 23:47 ` [dpdk-dev] [PATCH 0/3] eal affinitize low priority " Hiroshi Shimamoto
2014-09-12  1:24   ` Stephen Hemminger
2014-09-12  8:07   ` Richardson, Bruce

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).