From: Jeff D. <jd...@ka...> - 2001-07-23 03:52:31
|
The user-mode port of 2.4.7 is available. In a minor packaging breakthrogh, a .deb for UML is now available. The UML block driver now supports a read-write COW layer above a shared read-only filesystem. This allows multiple UMLs to boot off the same filesystem. See http://user-mode-linux.sourceforge.net/shared_fs.html for more information. The ppc port is now fully merged. The pid file and mconsole socket are now located in a directory defined by the UML umid. There is now IO memory emulation. This allows a host file to be mapped by a UML driver, which can provide whatever interface it wants to that file to UML processes. This is a first step towards doing hardware driver development under UML. gdbs are now killed properly. A nasty bug involving a misunderstanding with FASTCALL was fixed. Block devices and network devices are now pluggable from the mconsole - they can be added to and removed from a running system. See http://user-mode-linux.sourceforge.net/mconsole.html for more information. SIGHUP no longer causes UML to go crazy. The project's home page is http://user-mode-linux.sourceforge.net Downloads are available at http://sourceforge.net/project/showfiles.php?group_id=429 ftp://ftp.nl.linux.org/pub/uml/ http://uml-pub.ists.dartmouth.edu/uml/ Jeff |
From: Andrea A. <an...@su...> - 2001-07-23 15:56:12
|
On Mon, Jul 23, 2001 at 12:08:04AM -0500, Jeff Dike wrote: > The user-mode port of 2.4.7 is available. in my tree I did some further cleanup, here the ones that you can interested about: diff -urN uml-ref/arch/um/include/kern_util.h uml/arch/um/include/kern_util.h --- uml-ref/arch/um/include/kern_util.h Mon Jul 23 17:07:17 2001 +++ uml/arch/um/include/kern_util.h Mon Jul 23 17:08:33 2001 @@ -28,7 +28,6 @@ extern long execute_syscall(struct sys_pt_regs regs); extern void syscall_segv(int sig); extern int current_pid(void); -extern void do_bh(void); extern void set_init_pid(int pid); extern unsigned long alloc_stack(void); extern int do_signal(unsigned long *error, int *again_out); diff -urN uml-ref/arch/um/kernel/process_kern.c uml/arch/um/kernel/process_kern.c --- uml-ref/arch/um/kernel/process_kern.c Mon Jul 23 17:07:17 2001 +++ uml/arch/um/kernel/process_kern.c Mon Jul 23 17:09:54 2001 @@ -217,25 +217,12 @@ return(current->thread.request.u.cswitch.from); } -void do_bh(void) -{ -#ifndef CONFIG_SMP - if (softirq_pending(0)){ - do_softirq(); - unblock_signals(); - } -#else -#error Need to update do_bh -#endif -} - void ret_from_sys_call(void *t) { struct task_struct *task; task = t; if(task == NULL) task = current; - do_bh(); if(task->need_resched) schedule(); if(task->sigpending != 0) do_signal(NULL, NULL); } diff -urN uml-ref/arch/um/kernel/time.c uml/arch/um/kernel/time.c --- uml-ref/arch/um/kernel/time.c Mon Jul 23 17:07:17 2001 +++ uml/arch/um/kernel/time.c Mon Jul 23 17:08:36 2001 @@ -16,7 +16,7 @@ #include "user.h" #include "process.h" -extern struct timeval xtime; +extern volatile struct timeval xtime; void timer_handler(int sig, void *sc, int usermode) { this one for compiling uml with the gcc-3_0-branch of yesterday: --- 2.4.7aa1/include/asm-um/pgalloc.h.~1~ Mon Jul 23 05:13:13 2001 +++ 2.4.7aa1/include/asm-um/pgalloc.h Mon Jul 23 05:25:10 2001 @@ -21,7 +21,7 @@ * Allocate and free page tables. */ -extern __inline__ pgd_t *get_pgd_slow(void) +static __inline__ pgd_t *get_pgd_slow(void) { pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL); BTW, Linus the _below_ patches against mainline are needed to compile the x86 port with gcc-3_0-branch of yesterday, it is safe to include it in mainline: --- 2.4.7aa1/include/asm-i386/pgalloc.h.~1~ Mon Jul 23 04:34:24 2001 +++ 2.4.7aa1/include/asm-i386/pgalloc.h Mon Jul 23 04:50:44 2001 @@ -23,7 +23,7 @@ extern void *kmalloc(size_t, int); extern void kfree(const void *); -extern __inline__ pgd_t *get_pgd_slow(void) +static __inline__ pgd_t *get_pgd_slow(void) { int i; pgd_t *pgd = kmalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL); @@ -48,7 +48,7 @@ #else -extern __inline__ pgd_t *get_pgd_slow(void) +static __inline__ pgd_t *get_pgd_slow(void) { pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL); --- 2.4.7aa1/include/asm-i386/siginfo.h.~1~ Mon Jul 23 04:34:24 2001 +++ 2.4.7aa1/include/asm-i386/siginfo.h Mon Jul 23 04:51:30 2001 @@ -216,7 +216,7 @@ #ifdef __KERNEL__ #include <linux/string.h> -extern inline void copy_siginfo(siginfo_t *to, siginfo_t *from) +static inline void copy_siginfo(siginfo_t *to, siginfo_t *from) { if (from->si_code < 0) memcpy(to, from, sizeof(siginfo_t)); --- 2.4.7aa1/net/core/rtnetlink.c.~1~ Mon Feb 28 03:45:10 2000 +++ 2.4.7aa1/net/core/rtnetlink.c Mon Jul 23 04:52:13 2001 @@ -274,7 +274,7 @@ /* Process one rtnetlink message. */ -extern __inline__ int +static __inline__ int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) { struct rtnetlink_link *link; --- 2.4.6pre2aa1/include/linux/sched.h.~1~ Wed Jun 13 00:44:45 2001 +++ 2.4.6pre2aa1/include/linux/sched.h Wed Jun 13 00:47:23 2001 @@ -541,7 +541,7 @@ extern unsigned long volatile jiffies; extern unsigned long itimer_ticks; extern unsigned long itimer_next; -extern struct timeval xtime; +extern volatile struct timeval xtime; extern void do_timer(struct pt_regs *); extern unsigned int * prof_buffer; Andrea |
From: Andrea A. <an...@su...> - 2001-07-23 15:58:45
|
On Mon, Jul 23, 2001 at 05:56:35PM +0200, Andrea Arcangeli wrote: > BTW, Linus the _below_ patches against mainline are needed to compile > the x86 port with gcc-3_0-branch of yesterday, it is safe to include it > in mainline: here another one for reiserfs: --- 2.4.7aa1/include/linux/reiserfs_fs.h.~1~ Mon Jul 23 06:56:14 2001 +++ 2.4.7aa1/include/linux/reiserfs_fs.h Mon Jul 23 17:57:46 2001 @@ -828,7 +828,7 @@ /* compose directory item containing "." and ".." entries (entries are not aligned to 4 byte boundary) */ -extern inline void make_empty_dir_item_v1 (char * body, __u32 dirid, __u32 objid, +static inline void make_empty_dir_item_v1 (char * body, __u32 dirid, __u32 objid, __u32 par_dirid, __u32 par_objid) { struct reiserfs_de_head * deh; @@ -859,7 +859,7 @@ } /* compose directory item containing "." and ".." entries */ -extern inline void make_empty_dir_item (char * body, __u32 dirid, __u32 objid, +static inline void make_empty_dir_item (char * body, __u32 dirid, __u32 objid, __u32 par_dirid, __u32 par_objid) { struct reiserfs_de_head * deh; Andrea |
From: Andrea A. <an...@su...> - 2001-07-23 16:16:57
|
On Mon, Jul 23, 2001 at 05:59:07PM +0200, Andrea Arcangeli wrote: > On Mon, Jul 23, 2001 at 05:56:35PM +0200, Andrea Arcangeli wrote: > > BTW, Linus the _below_ patches against mainline are needed to compile > > the x86 port with gcc-3_0-branch of yesterday, it is safe to include it > > in mainline: > > here another one for reiserfs: here another one: --- 2.4.7aa1/net/ipv4/netfilter/ip_queue.c.~1~ Sat Jul 21 00:04:34 2001 +++ 2.4.7aa1/net/ipv4/netfilter/ip_queue.c Mon Jul 23 18:14:45 2001 @@ -492,7 +492,7 @@ #define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0); -extern __inline__ void netlink_receive_user_skb(struct sk_buff *skb) +static __inline__ void netlink_receive_user_skb(struct sk_buff *skb) { int status, type; struct nlmsghdr *nlh; Andrea |
From: Linus T. <tor...@tr...> - 2001-07-23 16:34:47
|
On Mon, 23 Jul 2001, Andrea Arcangeli wrote: > > in my tree I did some further cleanup, here the ones that you can > interested about: Andrea, please drop the "volatile" from xtime. It's bogus. There's no reason why gcc couldn't make one or many accesses to that variable, and volatile is an evil keyword that is badly specified and only makes the compiler generate worse code without ever fixing any real bugs. If you need a stable value, use a lock. Linus |
From: Andrea A. <an...@su...> - 2001-07-23 16:45:04
|
On Mon, Jul 23, 2001 at 09:33:28AM -0700, Linus Torvalds wrote: > > On Mon, 23 Jul 2001, Andrea Arcangeli wrote: > > > > in my tree I did some further cleanup, here the ones that you can > > interested about: > > Andrea, please drop the "volatile" from xtime. It's bogus. it's the other way around, it's needed and gcc trapped a kernel bug. If the contents of memory not declared volatile changes under GCC (like it can happen right now for xtime since it's declared non volatile), gcc has the full rights to crash the kernel at runtime. I know there are other bugs like this one in the kernel, but this is not a good reason to fix the known ones IMHO. Andrea |
From: Linus T. <tor...@tr...> - 2001-07-23 17:33:57
|
On Mon, 23 Jul 2001, Andrea Arcangeli wrote: > > it's the other way around, it's needed and gcc trapped a kernel bug. No it's not. > If the contents of memory not declared volatile changes under GCC (like > it can happen right now for xtime since it's declared non volatile), gcc > has the full rights to crash the kernel at runtime. Absolutely not. If we care abotu the thing always having the same value, we HAVE to use a lock. "volatile" is not the answer. Show me a place where we care. Linus |
From: Andrea A. <an...@su...> - 2001-07-23 17:50:32
|
On Mon, Jul 23, 2001 at 10:32:32AM -0700, Linus Torvalds wrote: > > On Mon, 23 Jul 2001, Andrea Arcangeli wrote: > > > > it's the other way around, it's needed and gcc trapped a kernel bug. > > No it's not. > > > If the contents of memory not declared volatile changes under GCC (like > > it can happen right now for xtime since it's declared non volatile), gcc > > has the full rights to crash the kernel at runtime. > > Absolutely not. > > If we care abotu the thing always having the same value, we HAVE to use a > lock. "volatile" is not the answer. > > Show me a place where we care. The problem is not at the source code level, of course all places where we read the xtime cannot crash the kernel as far as the kernel is concerned, but the problem is instead at the gcc level: and when the logic implemented by the asm generated by gcc chokes we can also get a dangling poitner and crash in the kernel. GCC internally is allowed to generate code that relies on the contents of the memory to stay constant, this because of the C standard, the usual example is a fast path jump table for the "case" statement. So in short having non volatile memory that changes under gcc gives gcc the full rights to crash the kernel at runtime anytime. Andrea |
From: Linus T. <tor...@tr...> - 2001-07-23 18:12:47
|
On Mon, 23 Jul 2001, Andrea Arcangeli wrote: > > GCC internally is allowed to generate code that relies on the contents > of the memory to stay constant, this because of the C standard, the > usual example is a fast path jump table for the "case" statement. Bah. If we have a case where we _really_ care about the value being stable, I _still_ claim that that is the one that we need to protect. Not waving some magic wand over the thing, and saying that "volatile" makes an unstable value ok. "volatile" (in the data sense, not the "asm volatile" sense) is almost always a sign of a bug. If you have an algorithm that depends on the (compiler-specifi) behaviour of "volatile", you need to change the algorithm, not try to hide the fact that you have a bug. Now, the change of algorithm might be something like /* * We need to get _one_ value here, because our * state machine .... */ unsigned long stable = *(volatile unsigned long *)ptr; switch (stable) { .... } where the volatile is in the place where we care, and the volatile is commented on WHY it actually is the correct thing to do. The C standard doesn't say crap about volatile. It leaves it up to the compiler to do something about it. This is _doubly_ true of multi-word data structures like "xtime". The meaning of "volatile" on the data structure is so unclear that it's not even funny. Linus |
From: Andrea A. <an...@su...> - 2001-07-23 18:27:09
|
On Mon, Jul 23, 2001 at 11:11:25AM -0700, Linus Torvalds wrote: > Now, the change of algorithm might be something like > > /* > * We need to get _one_ value here, because our > * state machine .... > */ gcc can assume 'state' stays constant in memory not just during the 'case'. > The C standard doesn't say crap about volatile. It leaves it up to the > compiler to do something about it. The C folks definitely say it is a kernel bug if you don't apply my patch and I agree with them. Ask Jan. Andrea |
From: Linus T. <tor...@tr...> - 2001-07-23 20:37:16
|
On Mon, 23 Jul 2001, Andrea Arcangeli wrote: > > gcc can assume 'state' stays constant in memory not just during the > 'case'. The point is that if the kernel has _any_ algorithm where it cares, it's a kernel bug. With volatile or without. SHOW ME THE CASE WHERE IT CARES. Let's fix it. Let's not just hide it with "volatile". Linus |
From: Jonathan L. <jlu...@po...> - 2001-07-23 20:15:32
|
At 1:00 PM -0700 2001-07-23, Linus Torvalds wrote: >On Mon, 23 Jul 2001, Andrea Arcangeli wrote: >> >> gcc can assume 'state' stays constant in memory not just during the >> 'case'. > >The point is that if the kernel has _any_ algorithm where it cares, it's a >kernel bug. With volatile or without. > >SHOW ME THE CASE WHERE IT CARES. Let's fix it. Let's not just hide it with >"volatile". in arch/i386/kernel/io_apic.c: >static int __init timer_irq_works(void) >{ > unsigned int t1 = jiffies; > > sti(); > /* Let ten ticks pass... */ > mdelay((10 * 1000) / HZ); > > /* > * Expect a few ticks at least, to be sure some possible > * glue logic does not lock up after one or two first > * ticks in a non-ExtINT mode. Also the local APIC > * might have cached one ExtINT interrupt. Finally, at > * least one tick may be lost due to delays. > */ > if (jiffies - t1 > 4) > return 1; > > return 0; >} If jiffies were not volatile, this initializing assignment and the test at the end could be optimized away, leaving an unconditional "return 0". A lock is of no help. -- /Jonathan Lundell. |
From: Linus T. <tor...@tr...> - 2001-07-23 22:53:13
|
On Mon, 23 Jul 2001, Jonathan Lundell wrote: > > If jiffies were not volatile, this initializing assignment and the > test at the end could be optimized away, leaving an unconditional > "return 0". A lock is of no help. Right. We want optimization barriers, and there's an explicit "barrier()" thing for Linux exactly for this reason. For historical reasons "jiffies" is actually marked volatile, but at least it has reasonably good semantics with a single-data item. Which is not to say I like it. But grep for "barrier()" to see how many times we make this explicit in the algorithms. And really, THAT is my whole point. Notice in the previous mail how I used "volatile" when it was part of the _algorithm_. You should not hide algorithmic choices in your data structures. You should make them explicit, so that when you read the code you _see_ what assumptions people make. For example, if you fix the code by adding an explicit barrier(), people see that (a) you're aware of the fact that you expect the values to change and (b) they see that it is taken care of. In contrast, if your data structure is marked volatile, how is anybody reading the code every going to be sure that the code is correct? You have to look at the header file defining all the data structures. That kind of thing is NOT GOOD. So make the algorithm be correct. Then you will notice that there is _never_ any reason (except for being lazy with tons of existing code) to add "volatile" to data structures. Ponder. Understand. Linus |
From: Jonathan L. <jlu...@po...> - 2001-07-24 03:49:27
|
At 3:51 PM -0700 2001-07-23, Linus Torvalds wrote: >On Mon, 23 Jul 2001, Jonathan Lundell wrote: >> >> If jiffies were not volatile, this initializing assignment and the >> test at the end could be optimized away, leaving an unconditional >> "return 0". A lock is of no help. > >Right. > >We want optimization barriers, and there's an explicit "barrier()" thing >for Linux exactly for this reason. > >For historical reasons "jiffies" is actually marked volatile, but at least >it has reasonably good semantics with a single-data item. Which is not to >say I like it. But grep for "barrier()" to see how many times we make this >explicit in the algorithms. > >And really, THAT is my whole point. Notice in the previous mail how I used >"volatile" when it was part of the _algorithm_. You should not hide >algorithmic choices in your data structures. You should make them >explicit, so that when you read the code you _see_ what assumptions people >make. OK, sure, that's fine. Better than barrier() in some respects, too. Namely, 1) volatile is portable C; barrier() isn't (not that that's much of an issue for compiling Linux), and 2) volatile can be specific to a variable, unlike the indiscriminate barrier(), which forces a reload of everything that might be cached (OK, not a big deal for IA32, but nontrivial for many-register architectures). One could imagine a more specific barrier(jiffies) syntax, I suppose, but the volatile cast is nice, restricting the effect not only to the single variable but to the single reference to a single variable. >For example, if you fix the code by adding an explicit barrier(), people >see that (a) you're aware of the fact that you expect the values to change >and (b) they see that it is taken care of. > >In contrast, if your data structure is marked volatile, how is anybody >reading the code every going to be sure that the code is correct? You have >to look at the header file defining all the data structures. That kind of >thing is NOT GOOD. -- /Jonathan Lundell. |
From: Davide L. <da...@xm...> - 2001-07-24 15:38:39
|
On 24-Jul-2001 Jonathan Lundell wrote: > At 3:51 PM -0700 2001-07-23, Linus Torvalds wrote: >>On Mon, 23 Jul 2001, Jonathan Lundell wrote: >>> >>> If jiffies were not volatile, this initializing assignment and the >>> test at the end could be optimized away, leaving an unconditional >>> "return 0". A lock is of no help. >> >>Right. >> >>We want optimization barriers, and there's an explicit "barrier()" thing >>for Linux exactly for this reason. >> >>For historical reasons "jiffies" is actually marked volatile, but at least >>it has reasonably good semantics with a single-data item. Which is not to >>say I like it. But grep for "barrier()" to see how many times we make this >>explicit in the algorithms. >> >>And really, THAT is my whole point. Notice in the previous mail how I used >>"volatile" when it was part of the _algorithm_. You should not hide >>algorithmic choices in your data structures. You should make them >>explicit, so that when you read the code you _see_ what assumptions people >>make. > > OK, sure, that's fine. Better than barrier() in some respects, too. > Namely, 1) volatile is portable C; barrier() isn't (not that that's > much of an issue for compiling Linux), and 2) volatile can be > specific to a variable, unlike the indiscriminate barrier(), which > forces a reload of everything that might be cached (OK, not a big > deal for IA32, but nontrivial for many-register architectures). One > could imagine a more specific barrier(jiffies) syntax, I suppose, but > the volatile cast is nice, restricting the effect not only to the > single variable but to the single reference to a single variable. One more thing, with volatile you specify it one time ( declaration time ), while with barrier() you've to spread inside the code tons of such macro everywhere you touch the variable. - Davide |
From: Alexander V. <vi...@ma...> - 2001-07-24 15:47:02
|
On Tue, 24 Jul 2001, Davide Libenzi wrote: > One more thing, with volatile you specify it one time ( declaration time ), > while with barrier() you've to spread inside the code tons of such macro > everywhere you touch the variable. That's the whole point, damnit. Syntax (or semantics) sugar is a Bad Thing(tm). If your algorithm depends on something in a nontrivial way - _spell_ _it_ _out_. |
From: Davide L. <da...@xm...> - 2001-07-24 15:58:10
|
On 24-Jul-2001 Alexander Viro wrote: > > > On Tue, 24 Jul 2001, Davide Libenzi wrote: > >> One more thing, with volatile you specify it one time ( declaration time ), >> while with barrier() you've to spread inside the code tons of such macro >> everywhere you touch the variable. > > That's the whole point, damnit. Syntax (or semantics) sugar is a Bad Thing(tm). > If your algorithm depends on something in a nontrivial way - _spell_ _it_ _out_. I would not call, to pretend the compiler to issue memory loads every time it access a variable, a nontrivial way. It sounds pretty clear to me. - Davide |
From: Alexander V. <vi...@ma...> - 2001-07-24 16:08:55
|
On Tue, 24 Jul 2001, Davide Libenzi wrote: > I would not call, to pretend the compiler to issue memory loads every time it access > a variable, a nontrivial way. > It sounds pretty clear to me. You know, one of the nice things about C is that unless you abuse preprocessor, reading code doesn't require doing far lookups. Most of it can be read and understood with very little context. "Do it once when you declare a variable" goes against that and that's not a good thing. |
From: Davide L. <da...@xm...> - 2001-07-24 16:49:13
|
On 24-Jul-2001 Alexander Viro wrote: > > > On Tue, 24 Jul 2001, Davide Libenzi wrote: > >> I would not call, to pretend the compiler to issue memory loads every time it access >> a variable, a nontrivial way. >> It sounds pretty clear to me. > > You know, one of the nice things about C is that unless you abuse > preprocessor, reading code doesn't require doing far lookups. Most > of it can be read and understood with very little context. "Do it > once when you declare a variable" goes against that and that's > not a good thing. Look, you're not going to request any kind of black magic over that variable. You're simply telling the compiler the way it has to ( not ) optimize the code. This is IMHO a declaration time issue. Looking at this code : while (jiffies < ...) { ... } the "natural" behaviour that a reader expects is that the "content" of the memory pointed by jiffied is loaded and compared. That content, not the content of a register loaded 100 asm instructions before the load. If you like this code more : for (;;) { barrier(); if (jiffies >= ...) break; ... } It's clear that a declaration like : __locked_access__ struct pio { int a, b, c; }; for (;;) { ++a; if (a > b && c < a) ... } sounds a "Bad Thing"(tm) even to me. - Davide |
From: Linus T. <tor...@tr...> - 2001-07-24 17:05:35
|
On Tue, 24 Jul 2001, Davide Libenzi wrote: > > Look, you're not going to request any kind of black magic over that variable. > You're simply telling the compiler the way it has to ( not ) optimize the code. Ehh. But it shouldn't optimize it that way _every_ time. You only want the specific optimizations in specific places. Which is why you use "barrier()" or volatile in the _code_, not the data declaration. For example, if you're holding a lock that protects it or you otherwise know that nothing is touching it at the same time, you do NOT want to have the compiler generate bad code. And trust me, "volatile" generates _bad_ code a lot more often than it generates correct code. Look at this: volatile int i; int j; int main() { i++; j++; } turning into this: main: movl i,%eax incl %eax movl %eax,i incl j ret Now, ask yourself why? The two _should_ be the same. Both do a read-modify-write cycle. But the fact is, that when you add "volatile" to the register, it really tells gcc "Be afraid. Be very afraid. This user expects some random behaviour that is not actually covered by any standard, so just don't ever use this variable for any optimizations, even if they are obviously correct. That way he can't complain". See? "volatile" is evil. It has _no_ standard semantics, which makes it really hard to implement sanely for the compiler. It also means that the compiler can change the semantics of what "volatile" means, without you really being able to complain. Also note how the "incl j" instruction is actually _better_ from a "atomicity" standpoint than the "load+inc+store" instruction. In this case, adding a "volatile" actually made the accesses to "i" be _less_ likely to be correct - you could have had an interrupt happen in between that also updated "i", and got lost when we wrote the value back. Moral of the story: don't use volatile. If you want to have a counter that is updated in interrupts etc, use "atomic_t" or locking. "volatile" makes things worse or better based on completely random criteria that don't necessarily have anything to do with what you _want_ to do. Linus |
From: Davide L. <da...@xm...> - 2001-07-24 17:28:30
|
On 24-Jul-2001 Linus Torvalds wrote: > But it shouldn't optimize it that way _every_ time. You only want the > specific optimizations in specific places. Which is why you use > "barrier()" or volatile in the _code_, not the data declaration. > > For example, if you're holding a lock that protects it or you otherwise > know that nothing is touching it at the same time, you do NOT want to have > the compiler generate bad code. > > And trust me, "volatile" generates _bad_ code a lot more often than it > generates correct code. > > Look at this: > > volatile int i; > int j; > > int main() > { > i++; > j++; > } > > turning into this: > > main: > movl i,%eax > incl %eax > movl %eax,i > incl j > ret > > Now, ask yourself why? The two _should_ be the same. Both do a > read-modify-write cycle. But the fact is, that when you add "volatile" to > the register, it really tells gcc "Be afraid. Be very afraid. This user > expects some random behaviour that is not actually covered by any > standard, so just don't ever use this variable for any optimizations, even > if they are obviously correct. That way he can't complain". This is a too simple case, this is maybe better : mov homer, %edx ... ... ... ... ( 101 asm ins ) loop: cmp %edx, ... ja out ... inc %edx ... jmp loop You're right, it might be optimized with a barrier() but it's all kind of how much times you're going to need one behaviour or the other. When I'll need most of my access to be "strict" I'd like to have a way that avoid me to spread the code with barries()s. > Also note how the "incl j" instruction is actually _better_ from a > "atomicity" standpoint than the "load+inc+store" instruction. In this > case, adding a "volatile" actually made the accesses to "i" be _less_ > likely to be correct - you could have had an interrupt happen in between > that also updated "i", and got lost when we wrote the value back. Not that much if you look at how incl is "decomposed" internally ( w/o LOCK ) by the CPU. If you really care about j you need an atomic op here, in any case. - Davide |
From: Linus T. <tor...@tr...> - 2001-07-24 17:40:59
|
On Tue, 24 Jul 2001, Davide Libenzi wrote: > > Not that much if you look at how incl is "decomposed" internally ( w/o LOCK ) > by the CPU. If you really care about j you need an atomic op here, in any case. Yes, but the "inc" is atomic at least on a UP system. So here "volatile" might actually _show_ bugs instead of hiding them. The real isssue, though, is that that is all volatile ever does. It can show or hide bugs, but it can't fix them. Of course, some people consider hidden bugs to _be_ fixed. I don't believe in that particulat philosophy myself. Linus |
From: Anton A. <ai...@ca...> - 2001-07-24 18:08:43
|
At 17:52 24/07/2001, Davide Libenzi wrote: >On 24-Jul-2001 Alexander Viro wrote: > > On Tue, 24 Jul 2001, Davide Libenzi wrote: >You're simply telling the compiler the way it has to ( not ) optimize the >code. >This is IMHO a declaration time issue. >Looking at this code : > >while (jiffies < ...) { > ... >} > >the "natural" behaviour that a reader expects is that the "content" of the >memory pointed by jiffied is loaded and compared. Well, that depends on your definition of "natural". In my definition, it would be absolutely normal in this example for the compiler to cache jiffies because it considers it as a non-changing variable if none of the code inside the while loop refers to jiffies again. But that's just me... >If you like this code more : > >for (;;) { > barrier(); > if (jiffies >= ...) > break; > ... >} Er, what is wrong with: while (barrier(), jiffies < ...) { ... } It is just as clean as the starting point but tells both the compiler at compile time and _me_ when reading the code that jiffies is expected to change under me. That is _way_ better than declaring it volatile in some obsure header file which, chances are, I have never looked at, or looked at and long forgotten about... Just my 2p. Anton -- "Nothing succeeds like success." - Alexandre Dumas -- Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @) Linux NTFS Maintainer / WWW: http://linux-ntfs.sf.net/ ICQ: 8561279 / WWW: http://www-stu.christs.cam.ac.uk/~aia21/ |
From: Chris F. <cfr...@no...> - 2001-07-23 20:45:15
|
Linus Torvalds wrote: > > On Mon, 23 Jul 2001, Andrea Arcangeli wrote: > > > > gcc can assume 'state' stays constant in memory not just during the > > 'case'. > > The point is that if the kernel has _any_ algorithm where it cares, it's a > kernel bug. With volatile or without. > > SHOW ME THE CASE WHERE IT CARES. Let's fix it. Let's not just hide it with > "volatile". If I understand correctly, xtime is updated asynchronously. If it isn't, then ignore this message totally. However, if it is, then *not* specifying it as volatile could easily cause problems in technically correct but poorly written code. Suppose I loop against xtime reaching a particular value. While this is definately not good practice, if xtime is not specified as volatile then since I never modify it within the loop the compiler is free to move the initial load out of the loop when optimizing. In this example the case where it is marked as volatile will run (though inefficiently), but the non-volatile case can hang totally. Do we want to get ourselves into something like this? Chris -- Chris Friesen | MailStop: 043/33/F10 Nortel Networks | work: (613) 765-0557 3500 Carling Avenue | fax: (613) 765-2986 Nepean, ON K2H 8E9 Canada | email: cfr...@no... |
From: Andrea A. <an...@su...> - 2001-07-23 21:11:19
|
On Mon, Jul 23, 2001 at 04:44:06PM -0400, Chris Friesen wrote: > Linus Torvalds wrote: > > > > On Mon, 23 Jul 2001, Andrea Arcangeli wrote: > > > > > > gcc can assume 'state' stays constant in memory not just during the > > > 'case'. > > > > The point is that if the kernel has _any_ algorithm where it cares, it's a > > kernel bug. With volatile or without. > > > > SHOW ME THE CASE WHERE IT CARES. Let's fix it. Let's not just hide it with > > "volatile". > > If I understand correctly, xtime is updated asynchronously. If it isn't, then > ignore this message totally. However, if it is, then *not* specifying it as > volatile could easily cause problems in technically correct but poorly written > code. > > Suppose I loop against xtime reaching a particular value. While this is > definately not good practice, if xtime is not specified as volatile then since I > never modify it within the loop the compiler is free to move the initial load > out of the loop when optimizing. In this example the case where it is marked as > volatile will run (though inefficiently), but the non-volatile case can hang > totally. > > Do we want to get ourselves into something like this? This is actually another issue, not really the problem I was talking about. The problem I was talking about was just about the C language and about writing correct C code (whith correct C code I mean something that cannot break by using a future release of gcc). Without my patch you never know. About the loop problem you mentioned you can know it won't break instead if you write it carefully. Of course I understand in most cases if the code breaks in the actual usages of xtime it is likely that gcc is doing something stupid in terms of performance. but GCC if it wants to is allowed to compile this code: printf("%lx\n", xtime.tv_sec); as: unsigned long sec = xtime.tv_sec; if (sec != xtime.tv_sec) BUG(); printf("%lx\n", sec); Andrea |