nanogui: Thread: Thread-safety, wrapping globals in structs, RTEMS


[<<] [<] Page 1 of 1 [>] [>>]
Subject: Thread-safety, wrapping globals in structs, RTEMS
From: Kaben Nanlohy ####@####.####
Date: 18 Dec 2000 22:04:58 -0000
Message-Id: <Pine.NEB.4.21.0012181400180.14684-100000@kaben.frye.com>

Some time ago there was mention of the toils required to wrap all of our
globals into structs so as to give us thread-safety in our nano-X clients.

I'm using nano-X and RTEMS, and for some time I've been shutting-off
preemption before every graphics call in order to avoid clobbering nano-X
globals.  RTEMS has provisions for giving each rtems_task a private copy
of global variables, and I haven't yet played with this and so I haven't
yet identified the gotchas I'd encounter by trying to privatize nano-X
globals.

Much more elegant would be the wrapping of globals into structs.  Has
anyone tried tackling this, or given thought to doing so?  Or how to do so
without destroying everything?  and if not, is anyone interested in
giving it a shot with me?  I'd start in about two weeks.

-- Kaben Nanlohy

Subject: Re: Thread-safety, wrapping globals in structs, RTEMS
From: "Greg Haerr" ####@####.####
Date: 18 Dec 2000 22:48:52 -0000
Message-Id: <002201c06945$d8ebdd10$6817dbd0@censoft.com>

: RTEMS has provisions for giving each rtems_task a private copy
: of global variables, and I haven't yet played with this and so I haven't
: yet identified the gotchas I'd encounter by trying to privatize nano-X
: globals.

I'd like to get your list of globals used.  There are two basic
types, static's per file and shared globals.  I've had some
thought on moving some of the g_ globals in engine/devopen.c into
the PSD struct, for various reasons.  Others, including all the
statics, are really global and shouldn't be per-task nor should
they affect the operation of Microwindows in a multi-threaded
environment, unless you're wanting to be able to draw simultaneously
from multiple tasks.

:
: Much more elegant would be the wrapping of globals into structs.  Has
: anyone tried tackling this, or given thought to doing so?  Or how to do so
: without destroying everything?  and if not, is anyone interested in
: giving it a shot with me?  I'd start in about two weeks.

I like the idea, but what really does wrapping into a struct buy
us from a multi-tasking perspective?

Regards,

Greg


Subject: Re: Thread-safety, wrapping globals in structs, RTEMS
From: Kaben Nanlohy ####@####.####
Date: 19 Dec 2000 19:20:21 -0000
Message-Id: <Pine.NEB.4.21.0012191105380.17217-100000@kaben.frye.com>

On Mon, 18 Dec 2000, Greg Haerr wrote:
> Trying to think deeply about this, I came up with the following.  Making
> Nano-X or Microwindows work fully reentrant (which is essentially
> what you're talking about with state-variables in a per-task structure)
> isn't really the best solution, unless you really are running multiple
> CPUs.  That is, with a single CPU, all of this modification ultimately
> just becomes a "programming methodology" rather than an actual
> speed enhancement, since there's only one CPU anyway.
> 
> So, I think a better idea isn't to make Microwindows reentrant,
> but, rather, thread-safe.  Here, I am assuming that you're not using
> the client/server Nano-X style, since it already works by serializing
> requests read by the socket in the server. (And RTEMS doesn't have
> processes, only tasks).  So, in the linked-together version, all we
> really need is a couple of global semaphores and then wrapping
> them around most graphics calls in order to protect the server's
> state.  These could be built as macros and left out of a non-threaded
> version.  What do you think of doing it this way?
> 

I think that this would fix things for me.  Thanks.

I'll share when it works.

-- Kaben.

Subject: Re: Thread-safety, wrapping globals in structs, RTEMS
From: "Thompson, Brent" ####@####.####
Date: 20 Dec 2000 15:30:58 -0000
Message-Id: <3A40D12D.7020903@nlc.com>

I've been working on porting Microwindows (both Mwin32 and
NanoX) to a VxWorks platform.  VxWorks is a small, thread-based,
shared-namespace kernel, and it sounds like we share some of the
same issues as RTEMS.

"Greg Haerr" ####@####.#### wrote: 
> 

> : RTEMS has provisions for giving each rtems_task a private copy
> : of global variables, and I haven't yet played with this and so I haven't
> : yet identified the gotchas I'd encounter by trying to privatize nano-X
> : globals.
> 
> I'd like to get your list of globals used.  There are two basic
> types, static's per file and shared globals.  I've had some
> thought on moving some of the g_ globals in engine/devopen.c into
> the PSD struct, for various reasons.  Others, including all the
> statics, are really global and shouldn't be per-task nor should
> they affect the operation of Microwindows in a multi-threaded
> environment, unless you're wanting to be able to draw simultaneously
> from multiple tasks.
 >

> : Much more elegant would be the wrapping of globals into structs.  Has
> : anyone tried tackling this, or given thought to doing so?  Or how to do so
> : without destroying everything?  and if not, is anyone interested in
> : giving it a shot with me?  I'd start in about two weeks.
> 
> I like the idea, but what really does wrapping into a struct buy
> us from a multi-tasking perspective?

I did successfully get the engine code "de-globalized" by
moving all of the globals (and statics) into the PSD.
What this gets you (in my case, anyway) is the chance to
support multiple independent screen devices with just a
little more init code (ie, each screen will have its own
root window, fore/back-ground colors, cursors, clipping regions,
etc.).  I do have this code available, but have not yet
sent in any patches (see next Paragraph for why!).  If you
would like to see this code, just ask and I'll package it
up for you.

But when I moved onto the Mwin32 and NanoX code, there was
a *lot* more work to be done.  Especially problematic are
the Win32 calls which don't pass in any pointers, so you
*have* to use globals to get anywhere.  So I dropped work
on this and am re-evaluating how to support multiple
independent screens.

As for making Microwindows thread-safe (which is what
Kaben was originally asking for -- I think! ;-)  I don't
think you necessarily need to "de-globalize" the code.  As
long as your system can share globals, we just need a
semaphore type of lock/unlock every time we access one of
the globals (or, at a more gross level, every time we enter/leave
a Microwindows function).  I think it would be useful to
add some access control functions (ie, semaphore lock/unlock)
to all of the Microwindows functions.  By default, they
can just be empty functions (and so, with compiler optimization,
would be optimized out and the code should work just as
fast as it does today).  But if an implementor over-rode these
functions with real semaphore lock/unlocks for a particular
OS, then you would have a multi-tasking thread-safe
Microwindows implementation!

I'm not a Linux-guru, but how do Linux handle multiple
Microwindows processes?  I have experience in OS-9 (a real-time
process-oriented OS) and in that environment we would package
up all of the globals/statics to be shared into a "data module"
which all of the apps could then link to and use (with proper
semaphore access control, of course!)  Is this what you
mean, Kaben?  In this case, you would need both the
"de-globalization" and semaphore control added to Microwindows.

Well, that's enough of me yapping for now.  What do you
guys think?

BAT
-- 
Brent A. Thompson, Next Level Communications <www.nlc.com>
1776 22nd Street #100, West Des Moines, IA 50266-1444
EMail: ####@####.#### Phone: (515)991-3853

Subject: Re: Thread-safety, wrapping globals in structs, RTEMS
From: Kaben Nanlohy ####@####.####
Date: 20 Dec 2000 20:39:54 -0000
Message-Id: <Pine.NEB.4.21.0012201127530.19415-100000@kaben.frye.com>

On Wed, 20 Dec 2000, Thompson, Brent wrote:

> I did successfully get the engine code "de-globalized" by
> moving all of the globals (and statics) into the PSD.
> What this gets you (in my case, anyway) is the chance to
> support multiple independent screen devices with just a
> little more init code (ie, each screen will have its own
> root window, fore/back-ground colors, cursors, clipping regions,
> etc.).  I do have this code available, but have not yet
> sent in any patches (see next Paragraph for why!).  If you
> would like to see this code, just ask and I'll package it
> up for you.

I had separate nano-X clients running in separate threads in an rtems
(linux-posix) application.  This was using the client/server setup; each
task had its own vt52 text-out panel (modified nxterm).  It worked
smoothly as long as the nano-X server ran as a separate linux process.  
But as it was only an experiment, and a series of ugly hacks, I tabled it
some months ago.

It was done by encapsulating client globals and statics into structs
created by GrOpen(), where GrOpen() stored the struct pointer in an
rtems-notepad of the client task.  When I tried to run the server as a
separate thread in the same application, deadlock resulted on sockets (I
think) on the linux side.


> But when I moved onto the Mwin32 and NanoX code, there was
> a *lot* more work to be done.  Especially problematic are
> the Win32 calls which don't pass in any pointers, so you
> *have* to use globals to get anywhere.  So I dropped work
> on this and am re-evaluating how to support multiple
> independent screens.
> 
> As for making Microwindows thread-safe (which is what
> Kaben was originally asking for -- I think! ;-)  I don't
> think you necessarily need to "de-globalize" the code.  As
> long as your system can share globals, we just need a
> semaphore type of lock/unlock every time we access one of
> the globals (or, at a more gross level, every time we enter/leave
> a Microwindows function).  I think it would be useful to
> add some access control functions (ie, semaphore lock/unlock)
> to all of the Microwindows functions.  By default, they
> can just be empty functions (and so, with compiler optimization,
> would be optimized out and the code should work just as
> fast as it does today).  But if an implementor over-rode these
> functions with real semaphore lock/unlocks for a particular
> OS, then you would have a multi-tasking thread-safe
> Microwindows implementation!

I'm running rtems on a single M68332, so all threads can see globals.

Making microwindows thread safe rather than reentrant, using the ideas you
suggest, was suggested by Greg, too.  And I don't need to have one nano-x
client per rtems task, so the solution is a good one for me at the moment.

But I can see, somewhere down the road, the need to display data from from
multiple devices on multiple displays.  One device sending data to
multiple displays on a local network, multiple devices sending data to a
single display.  Etcetera.

That's way down the road if it happens at all.  I perked right up when I
read the discussion of networking microwindows/nano-X.

So while right now I'm looking for thread safety, I was hoping to not
paint anybody into a corner with a thread-safe solution that precludes
reentrancy if it begins to look attractive.


I realize that this is an ambitious discussion, and perhaps not the route
intended by others for nano-X.  But my current rtems/nano-x project makes
for a 290k executable, with a tiny gui and signal processing and stuff,
and I'm very pleased with both rtems and nano-x.  When we see what sort of
networking is given to us by Alex Holden, I expect we'll also see that
multiple clients in multiple threads, connected to nano-x servers on a
network, isn't a far reach.

> I'm not a Linux-guru, but how do Linux handle multiple
> Microwindows processes?  I have experience in OS-9 (a real-time
> process-oriented OS) and in that environment we would package
> up all of the globals/statics to be shared into a "data module"
> which all of the apps could then link to and use (with proper
> semaphore access control, of course!)  Is this what you
> mean, Kaben?  In this case, you would need both the
> "de-globalization" and semaphore control added to Microwindows.
> 

I don't know if this is what I mean.  I think I mean, for now, multiple
threads getting preempted without clobbering globals in the linked-in
server model.  I think, later, distinct clients, potentially one per
thread, each with its own set of client globals.

In linux nano-x, as far as I can tell, each process that's a microwindows
client can make one connection to a server process on the same machine
using a local socket (or shared memory).  The server keeps track of the
clients and the objects they own.  But as far as the application
programmer is concerned, at least at the moment, there's no difference
between the client/server and the linked-in server models.

***


Right now I'm listing and trying to organize the globals and statics used
in a linked-in server application.

Questions for the moment:

Call these hooks "Gr(Un)LockSomethingOrOther()" or
"GrObtainSomeSemaphore()"...  Does anyone want to name these functions
after their favorite pet or anything like that?

Giving them the same kind of abstraction used in the drivers seems
excessive, but it would be pretty.  Using makefile or macro magic or just
leaving hooks for implementors to fill would be clunkier but easier.  Are
there preferences?

-- Kaben.

Subject: Re: Thread-safety, wrapping globals in structs, RTEMS
From: "Greg Haerr" ####@####.####
Date: 20 Dec 2000 22:13:19 -0000
Message-Id: <015101c06ad3$41566a80$6817dbd0@censoft.com>

: Call these hooks "Gr(Un)LockSomethingOrOther()" or
: "GrObtainSomeSemaphore()"...  Does anyone want to name these functions
: after their favorite pet or anything like that?

Use
    LOCK(mutex)
and
    UNLOCK(mutex)

where LOCK and UNLOCK are #define's.  In addition,
the mutex itself can be declared as a MUTEX, allowing
any different means of critical section handling routines
to be used without having to re-hack Nano-X all the time.

Since we're talking about code that's internal to Nano-X,
we won't use the GrXXX functions, since they're not allowed
to be called by users.

At this point, I'd recommend a #include "mutex.h" in serv.h,
with the 

#if RTEMS_MUTEX
#include <pthread.h>
#define MUTEX            pthread_mutex
#define LOCK(mutex)   pthread_lock(&mutex)
#endif
etc 

or whatever in mutex.h.

Then, a single global mutex can be used in each GrXXX routine
to guarantee thread safety.

Regards,

Greg

Subject: Re: Thread-safety, wrapping globals in structs, RTEMS
From: "Jason C. Garcowski" ####@####.####
Date: 21 Dec 2000 00:29:10 -0000
Message-Id: <Pine.LNX.4.10.10012201730550.11913-100000@cx111693-f.chnd1.az.home.com>

On Wed, 20 Dec 2000, Greg Haerr wrote:

> Use
>     LOCK(mutex)
> and
>     UNLOCK(mutex)
> 

I don't know anything about the internals of microwindows or nano-X or
anything, so take this thought with a grain of salt.  Wouldn't it be
better to use rwlocks?  They exist in the thread.h library in solaris, but
linux uses pthreads, hence no thread.h.  However read/write locks can be
emulated using multiple semaphores, correct?  Do you think that'd be worth 
the effort, or no?  Do rwlocks exist natively on the other platforms
supported by microwindows & nano-X?  Just a thought.

jason

[<<] [<] Page 1 of 1 [>] [>>]


Powered by ezmlm-browse 0.20.