Index: [thread] [date] [subject] [author]
  From: MenTaLguY <mentalg@geocities.com>
  To  : ggi-develop@eskimo.com
  Date: Sat, 29 Aug 1998 12:21:23 -0500 (EST)

Re: LibGGI Thread-safety (was Re: Some things that seem to be missing)

On Thu, 27 Aug 1998, Steve Cheng wrote:

> On Thu, 27 Aug 1998, MenTaLguY wrote:
> 
> > > ggiFlush should do a _ggiTryLock(), since that is the current behaviour
> > > (albeit X locks on ints!), but the real problem is that pthread_mutex_t
> > > isn't async signal safe, so if we do a _ggiLock() from mansync, we get
> > > a deadlock.
> > well... one possible way to do this is make a special provision for
> > ggiFlush() in _ggiUnlock() -- if the mutex is locked, ggiFlush() would just
> > set a "need flush" semaphore someplace, which would be checked by
> > _ggiUnlock(), and if the semaphore was set, _ggiUnlock() would call
> > _ggiFlush() or somesuch version of ggiFlush() that didn't check the
> > lock/semaphore.  sem_post is, after all, async-signal-safe.
> 
> It's too ugly.  We shouldn't hardcode mansync stuff into the _ggiLock stuff.

Well, not just for mansync.  If locks were made recursive in some fashion,
it would make using nested (user) drawing functions easier -- i.e. if you
wrote a general function to draw some general shape using some of the ggi
library stuff, and it got called either from some other user functions that
also locked, or sometimes on its own.

Actually, probably the best approach would be (I think) to make ggiLock() 
and ggiUnlock() public, use lock counts, and define ggiFlush() to flush as
soon as possible once the lock count is zero (i.e. ggiFlush() would return
immediately and the actual flush would be done from from ggiUnlock() once
the lock count hit zero), or immediately from ggiFlush() if the lock count
is already zero. 

That'd make a _lot_ of other things much easier, too.  I have implemented
something like that in a multithreaded ncurses wrapper I made once, and it
worked very, very well.

> Thought about that too, but I can't see how pthread_mutex_trylock could
> cause a deadlock (assuming this is the only problem caused by async-signal
> non-safety).

Maybe not a deadlock, but possibly a race condition -- in any case, what
problems arose, if any, would be highly implementation-dependent.

> I'd appreciate any help securing the existing code, but it's just this
> mansync dilemma :-(  -- see below.
> 
> > Oh, and even the non-threaded version of the library should (must) still be
>                    ^^^^^^^^^^^^
> The library doesn't start its own thread except the pthread.c of
> display/mansync.

That's probably as it should be.

> > thread-_safe_ (or at least reentrant and maybe async-signal-safe)! Please,
> > people... consider the state of the technology!
> 
> Is that what people want?  (pseudo-thread-safety without multi-threading
> support compiled)

If POSIX threads are supported by the target system, it should use mutexes
for locking instead of ints, even if explicit multi-threading support is not
enabled for libGGI.  GNU autoconf or some other similar detection setup
would be extremely useful for that.

ints are not really safe. not for signals, not for anything. 

(n.b. you can use the signal mask to protect the int lock to make it
async-signal-safe, but that is very expensive under many UNIXes, including, 
I think, Linux)

-=MenTaLguY=-

Index: [thread] [date] [subject] [author]