<html>
<head>
<style>
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 10pt;
font-family:Verdana
}
</style>
</head>
<body class='hmmessage'>
This code is very likely buggy, due to compiler or processor reordering, in a multithread environment, which we have.<BR>
 <BR>
 <BR>
Prior to my change, it only required multiple threads to have a race condition.<BR>
 <BR>
 <BR>
We need some sort of "barriers", as they are called.<BR>
 <BR>
The writes to null_done must "divide" the code before it and the code after it.<BR>
While they appear to, in the source, this is not likely guaranteed by the compiler or processor.<BR>
It doesn't matter in a single threaded environment, but they don't generally exist.<BR>
 <BR>
Or maybe an ability to mark variables as "volatile".<BR>
 <BR>
In C, a fairly portable overkill fix is to sprinkle around volatile, but that generally makes the code more deoptimized than necessary. Volatile inhibits any reads or writes of the variable from being optimized away, and generally any reordering. However not all reads/writes need such treatment. Imagine a function that initialized a global on-demand, and then return that global plus itself -- the addition need only fetch the value once.<BR>
 <BR>
What to do?<BR>
 <BR>
 <BR>
VAR<BR>  null_done := FALSE;<BR>  null_stat: Ustat.struct_stat;<BR>  null_fd: INTEGER;<BR>
 <BR>
PROCEDURE IsDevNull(READONLY statbuf: Ustat.struct_stat): BOOLEAN RAISES {} =<BR>  VAR result: INTEGER;<BR>  BEGIN<BR>    IF NOT null_done THEN<BR>      null_fd := Unix.open(M3toC.FlatTtoS("/dev/null"), Unix.O_RDONLY, Unix.Mrwrwrw);<BR>      IF null_fd < 0 THEN;<BR>        null_done := TRUE;<BR>        RETURN FALSE<BR>      ELSE<BR>        result := Ustat.fstat(null_fd, ADR(null_stat));<BR>        EVAL Unix.close(null_fd);<BR>        IF result # 0 THEN<BR>          null_fd := -1<BR>        END<BR>      END;<BR>      null_done := TRUE;<BR>    END;<BR>    RETURN null_fd >= 0 AND statbuf.st_rdev = null_stat.st_rdev<BR>  END IsDevNull;<BR><BR><BR>
 - Jay<BR><BR><BR>> Date: Mon, 5 Jan 2009 05:37:13 +0000<BR>> To: m3commit@elegosoft.com<BR>> From: jkrell@elego.de<BR>> Subject: [M3commit] CVS Update: cm3<BR>> <BR>> CVSROOT: /usr/cvs<BR>> Changes by: jkrell@birch. 09/01/05 05:37:13<BR>> <BR>> Modified files:<BR>> cm3/m3-libs/libm3/src/os/POSIX/: FilePosix.m3 <BR>> <BR>> Log message:<BR>> reduce but don't eliminate race condition; before there was a race in a multithreaded code, now there is 'only' a race in multithreaded code under optimization that reorders writes (we need MemoryBarrier() for this kind of lock free on demand initialization of globals..)<BR>> <BR><BR></body>
</html>