Re: gcc2.95 and GHC

1999-08-24 Thread Simon Marlow


I seem to have found the ghc/gcc 2.95 problem.  There was a bug in one of
the constraints on an inline-assembly fragment in the PrimOp for small
integer multiplication; patch below.

I've run some benchmarks, and gcc 2.95 does a *much* better job than 2.7.2.1
of compiling the garbage collector: it lops an average of something like 15%
off the GC time.  wheyhey!

Haven't tried gcc 2.95 on a Sparc yet.

Cheers,
Simon

*** PrimOps.h   1999/07/29 10:00:22 1.33
--- PrimOps.h   1999/08/24 09:36:41 1.35
***
*** 1,5 
  /*

-
!  * $Id: PrimOps.h,v 1.33 1999/07/29 10:00:22 simonmar Exp $
   *
   * (c) The GHC Team, 1998-1999
   *
--- 1,5 
  /*

-
!  * $Id: PrimOps.h,v 1.35 1999/08/24 09:36:41 simonmar Exp $
   *
   * (c) The GHC Team, 1998-1999
   *
***
*** 132,138 
   jno 1f\n\t   \
   movl $1,%1\n\t   \
   1:"  \
!   : "=r" (r), "=r" (c) : "r" (a), "0" (b));   \
  }
  
  #elif SIZEOF_VOID_P == 4
--- 132,138 
   jno 1f\n\t   \
   movl $1,%1\n\t   \
   1:"  \
!   : "=r" (r), "=&r" (c) : "r" (a), "0" (b));  \
  }
  
  #elif SIZEOF_VOID_P == 4



RE: NON-daemonic forking

1999-08-24 Thread Simon Marlow

[posting to the right list... ]

> I guess not.  How can you define a non-daemonic forkIO in 
> terms of a daemonic one?
> Both suggestions so far involve adding something extra to the 
> end of the main
> thread to wait on MVars.  And as a matter of fact, neither of 
> these solutions
> address the problem of an exception in the main thread 
> itself.  The only way I can
> see of implementing non-daemonic fork would be to insist that 
> the user always write
> main functions with a containing try-finally clause (or 
> whatever it's called) which
> does the business of waiting for any unfinished non-daemonic threads.

This is what I'd do.  You do need the top-level enclosing exception handler,
but its not at all painful and any program that pretends to be robust will
need one anyway:

(this code is completely untested, BTW)

> import Exception
> 
> children :: MVar [MVar ()]
> children = unsafePerformIO (newMVar [])
> 
> waitForChildren :: IO ()
> waitForChildren = do
>   (mvar:mvars) <- takeMVar children
>   putMVar children mvars
>   takeMVar mvar
>   waitForChildren
> 
> forkNonDaemonic :: IO () -> IO ()
> forkNonDaemonic io = do
>mvar <- newEmptyMVar
>forkIO (p `finally` putMVar mvar ())
>childs <- takeMVar children
>putMVar children (mvar:childs)
> 
> later = flip finally
> 
> main =
>   later waitForChildren $
>   ...

The trick of having a top-level global mutable variable or MVar is turning
up in a disturbingly large proportion of the code I tend to write these days
:)

Cheers,
Simon



RE: NON-daemonic forking

1999-08-24 Thread Simon Marlow



> forkChild :: IO () -> IO (MVar ())
> forkChild p = do
> mvar <- newEmptyMVar
> forkIO (p >> putMVar mvar ())
> return mvar

A slightly better version:

> import Exception
>
> forkChild :: IO () -> IO (MVar ())
> forkChild p = do
> mvar <- newEmptyMVar
> forkIO (p `finally` putMVar mvar ())
> return mvar

which catches exceptions as well as clean exits from the forked thread. 

Cheers,
Simon



Re: NON-daemonic forking

1999-08-24 Thread Michael Weber

On Mon, Aug 23, 1999 at 11:30:47 +0200, George Russell wrote:
> Michael Weber <[EMAIL PROTECTED]> wrote
> [snip]
> > forkChild :: IO () -> IO (MVar ())
> > forkChild p = do
> > mvar <- newEmptyMVar
> > forkIO (p >> putMVar mvar ())
> > return mvar
> This does not of course synthesise a non-daemonic forkIO from a daemonic one, because
> it requires the parent thread to wait for the MVar.  I suppose that a possible 
>alternative
> to having separate daemonic and non-daemonic forking would be to have an atexit-type
> function:
>atThreadExit :: IO () -> IO()
> which forkChild could use to wait for the mvar.  But I'm not sure I like this, unless
> there are other likely uses for atThreadExit.

You're right. With the above code, the parent chooses, for which children it
has to wait (like this is done with Un*x fork() syscalls). 

If I get it right, you want a forked process to be able to shutdown the
whole system?

\begin{code}
import Concurrent( forkIO, yield )
import System( exitWith, ExitCode(ExitSuccess) )
import Monad ( mapM_ )

main :: IO ()
main = do
forkIO (forever $ putChar 'a')
forkIO (mapM_ putChar (replicate 1 'b') >> exitWith ExitSuccess)
forever $ return ()
  where
forever :: IO a -> IO a
forever p = p >> yield >> forever p
\end{code}


Cheers,
Michael
-- 
* Chemical Engineering is like looking for a black cat in a dark room.
* Software Engineering is like looking for a black cat in a dark room in
  which there is no cat.