LIST_INLINE void rem_node(node *n) { node *z = n->prev; node *x = n->next; z->next = x; x->prev = z; } Using of this function may broke list.tail and list.head. Later call to function like add_head or add_tail may couse problem. -- Тамарский Максим Александрович Инженер-программист ООО Эн-Эс-Джи г.Москва, Кирпичная 39/41 оф.1302 Почтовый адрес: 105187 Россия, Москва ул.Вольная, д.35, оф.NSG Тел./факс: +7 495 727-19-59 Web-сайт: http://www.nsg.ru
I found that my trouble exists when compiling with -O2 option. In that case inline functions rem_node and add_head will merged into function (/nest/iface.c ifa_recalc_primary) and then will badly optimized by compiler, because the implicit use of pointers to the same data. If we call external function(like printf) between rem_node and add_head trouble gone away in any case. Now i use -O1. This works for 1.3.2 and 13.8. My compiler is: $ powerpc-nsg-linux-gcc -dumpversion 3.4.3 $ powerpc-nsg-linux-gcc -dumpmachine powerpc-nsg-linux -- RU: Тамарский Максим Александрович Инженер-программист ООО Эн-Эс-Джи г.Москва, Кирпичная 39/41 оф.1302 Почтовый адрес: 105187 Россия, Москва ул.Вольная, д.35, оф.NSG Тел./факс: +7 495 727-19-59 Web-сайт: http://www.nsg.ru EN: Maksim Tamarsky Software Engineer NSG Ltd. 35 Volnaya Street, 105187 Moscow, Russia +7 495 727-19-59 http://www.nsg.ru
gcc 3.4.3? -O2 is generally pretty safe. Your version of gcc sounds pretty old. I assume this isn't an issue with newer versions of gcc? ________________________________________ From: owner-bird-users@atrey.karlin.mff.cuni.cz [owner-bird-users@atrey.karlin.mff.cuni.cz] on behalf of Maksim Tamarsky [mtamarsky@nsg.net.ru] Sent: Thursday, January 10, 2013 9:47 AM To: bird-users@trubka.network.cz Subject: Re: BUG: /lib/lists.c.. Don`t use -O2 . Use -O1 I found that my trouble exists when compiling with -O2 option. In that case inline functions rem_node and add_head will merged into function (/nest/iface.c ifa_recalc_primary) and then will badly optimized by compiler, because the implicit use of pointers to the same data. If we call external function(like printf) between rem_node and add_head trouble gone away in any case. Now i use -O1. This works for 1.3.2 and 13.8. My compiler is: $ powerpc-nsg-linux-gcc -dumpversion 3.4.3 $ powerpc-nsg-linux-gcc -dumpmachine powerpc-nsg-linux -- RU: Тамарский Максим Александрович Инженер-программист ООО Эн-Эс-Джи г.Москва, Кирпичная 39/41 оф.1302 Почтовый адрес: 105187 Россия, Москва ул.Вольная, д.35, оф.NSG Тел./факс: +7 495 727-19-59 Web-сайт: http://www.nsg.ru EN: Maksim Tamarsky Software Engineer NSG Ltd. 35 Volnaya Street, 105187 Moscow, Russia +7 495 727-19-59 http://www.nsg.ru
10.01.2013 18:47, Maksim Tamarsky пишет:
$ powerpc-nsg-linux-gcc -dumpversion 3.4.3 sorry, really i use powerpc-nsg_rt-linux-gcc -dumpversion 4.5.3
-- RU: Тамарский Максим Александрович Инженер-программист ООО Эн-Эс-Джи г.Москва, Кирпичная 39/41 оф.1302 Почтовый адрес: 105187 Россия, Москва ул.Вольная, д.35, оф.NSG Тел./факс: +7 495 727-19-59 Web-сайт: http://www.nsg.ru EN: Maksim Tamarsky Software Engineer NSG Ltd. 35 Volnaya Street, 105187 Moscow, Russia +7 495 727-19-59 http://www.nsg.ru
On Thu, Jan 10, 2013 at 06:47:42PM +0400, Maksim Tamarsky wrote:
I found that my trouble exists when compiling with -O2 option. In that case inline functions rem_node and add_head will merged into function (/nest/iface.c ifa_recalc_primary) and then will badly optimized by compiler, because the implicit use of pointers to the same data. If we call external function(like printf) between rem_node and add_head trouble gone away in any case.
Now i use -O1. This works for 1.3.2 and 13.8.
Hello I thought that it might be something like that, but if i remember and understand correctly C language rules for pointer aliasing, then the code is OK, because although the memory is accessed through pointers to structures of two different types, the content is same (node ptr), so compiler cannot expect non-aliasing. So i would suppose it is a compiler bug, so workaround with -O1 is probably a good solution. There are probably some other potential pointer aliasing problems in BIRD (at least the ones that newer versions of GCC complainted) that should be addressed, but i think this one is OK. MJ, any comment on this list code and pointer aliasing? -- Elen sila lumenn' omentielvo Ondrej 'SanTiago' Zajicek (email: santiago@crfreenet.org) OpenPGP encrypted e-mails preferred (KeyID 0x11DEADC3, wwwkeys.pgp.net) "To err is human -- to blame it on a computer is even more so."
Hello!
MJ, any comment on this list code and pointer aliasing?
I have also convinced myself that the code is correct. However, as the years go, I more and more feel that saving a single pointer in the list head is not worth the trickiness it takes. My more recent programs mostly use a different implementation, based on circular doubly-linked lists. It requires 4 pointers in the list head (as opposed to 3 pointers in BIRD's lib/lists.c) and 2 pointers per list node. Its semantics is easier to follow and the list operations are easier and some of them even faster. Maybe BIRD could switch to these lists, soo. You can see them in action in LibUCW repository (git://git.ucw.cz/libucw.git, http://www.ucw.cz/gitweb/?p=libucw.git;a=summary), ucw/clists.h. (Some other bits of LibUCW might be interesting to BIRD, but beware, several LibUCW modules depend on GCC extensions.) Have a nice fortnight -- Martin `MJ' Mares <mj@ucw.cz> http://mj.ucw.cz/ Faculty of Math and Physics, Charles University, Prague, Czech Rep., Earth Outside of a dog, a book is man's best friend. Inside a dog, it's too dark to read.
Hello, On 01/10/2013 03:47 PM, Maksim Tamarsky wrote:
I found that my trouble exists when compiling with -O2 option. In that case inline functions rem_node and add_head will merged into function (/nest/iface.c ifa_recalc_primary) and then will badly optimized by compiler, because the implicit use of pointers to the same data. If we call external function(like printf) between rem_node and add_head trouble gone away in any case. Do you wanna say that adding a printf between rem_node and add_head makes bird run fine? I analysed the code generated for ARM with -O2 (see thread "bird6 1.3.7 hangs on start on a Raspberry Pi") and I cannot see anything wrong with the assembler code.
On the other hand, casting a pointer to the head member of a struct list to a node * is definitely broken. (This is done in add_head().) I'm pretty sure this code's behavior is undefined and so should be fixed. And I consider this to be more likely the cause of the bad behaviour that you, Fritz and Eric are seeing. Martin Mares already suggested an alternative implementation for doubly-linked lists. Another alternative is include/linux/lists.h from the Linux kernel. I guess an upside of the latter is that it is known to be working on several architectures. (But note I didn't even look at Martin's suggestion and so cannot really say how well it is tested.) Best regards Uwe
participants (6)
-
Lauro, John -
Maksim Tamarsky -
Martin Mares -
Ondrej Zajicek -
Uwe Kleine-König -
Тамарский Максим