Date: Thu, 20 Dec 2007 02:44:23 +1100 (EST) From: Bruce Evans <brde@optusnet.com.au> To: Bruce Evans <brde@optusnet.com.au> Cc: cvs-src@freebsd.org, src-committers@freebsd.org, Warner Losh <imp@freebsd.org>, cvs-all@freebsd.org Subject: Re: cvs commit: src/lib/libc/stdtime localtime.c Message-ID: <20071220021032.T37695@delplex.bde.org> In-Reply-To: <20071219210516.I37050@delplex.bde.org> References: <200712190430.lBJ4UB7M018392@repoman.freebsd.org> <20071219210516.I37050@delplex.bde.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, 19 Dec 2007, Bruce Evans wrote: > On Wed, 19 Dec 2007, Warner Losh wrote: > >> imp 2007-12-19 04:30:11 UTC >> >> FreeBSD src repository >> >> Modified files: >> lib/libc/stdtime localtime.c >> Log: >> Reduce lock contention for simple cases. >> >> # this really should be done with pthread_once, but I've debugged this >> code. >> >> Reviewed by: arch@ > > Reviewers weren't happy with this. I now think that the only bug in > it is that it unnecesarily depends i386 memory semantics (that writes > are not reordered). There should be a write barrier before the flag > is set, to ensure that the writes which initialize things occur before > the write that sets the flag. it also depends on the compiler not reordering writes. But gcc does, and I think is permitted to, reorder writes: %%% int x; int y; main() { x = 1; y = 2; x = 3; } %%% compiles to: %%% .file "z.c" .text .p2align 2,,3 .globl main .type main, @function main: pushl %ebp movl %esp, %ebp subl $8, %esp andl $-16, %esp movl $2, y movl $3, x leave ret .size main, .-main .comm x,4,4 .comm y,4,4 .ident "GCC: (GNU) 3.3.3 [FreeBSD] 20031106" %%% Moving the first assignment to x to after the assignment to y and then optimizing away the first assigment are is permitted since neither x nor y is volatile and their are no function calls that might access x or y. It is done since it is easy to see that it is valid -- there are obviously no function calls and no pointers to cause aliasing problems. C has a rule that writes that the program must operate as if writes are done at sequence points, and there is a sequence point on every semicolon in the above, so it takes some analysis to see that the transformation is valid. Writes may be reordered even across function calls, but usually aren't because the function is not visible or the analysis is too hard. Signal handlers also cannot access x or y, especially to read them and act on their value, since signal handlers are only permitted to assign (write) to variables of type sig_atomic_t. Similarly if x is only assigned to once. The same things that permit removing the first of the 2 assignments to x in the above permit doing the assignments in any order. With normal locking, this problem is handled magically by the implicit write barrier in mutex unlock. The write barrier first causes all writes to be flushed in some order. With i386 memory semantics, this order is the same as the compiler decided to use, which may be quite different from the program order, but any differences don't matter because the rendevous at the lock prevents anything else looking at any of the variables until they have all been written. Then the lock is released, and the write order doesn't matter because everything has been written before anything looks at the variables. Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20071220021032.T37695>