Re: gcc2.95 and GHC
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
[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
> 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
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.