|
gfx_crit_sect_nesting bugs & no-asm in windows & whatever |
orz
Member #565
August 2000
|
Multiple things in this post: 1. Could anyone cluefull about Allegro internals take a glance at this thread: 2. Asm in src/win in Allegro: But anyway, the point: edit: added this code
Additional changes required: edit3: 3. gfx_crit_sect_nesting bugs First of all: _exit_gfx_critical is defined as #define _exit_gfx_critical() LeaveCriticalSection(&gfx_crit_sect); \ gfx_crit_sect_nesting-- This appears to be incorrect: a context switch can happen during the decrement of gfx_crit_sect_nesting (or alternatively, on a dual-CPU system, another thread can run concurrently with it). The new thread could decrement gfx_crit_sect_nesting after the first had read it and before it had written to it. Even if a INC instruction was used (which compilers rarely do), it could still happen on a multiCPU system. This could happen even in regular allegro programs, as the allegro thread calls _exit_gfx_critical() during WM_PAINT handling, and the main thread calls it during graphics operations. Now we come to the convergence of #1 and #2. In the thread I linked to in #1, I suggested displaying the value of gfx_crit_sect_nesting, on the theory that maybe there was a mismatch between locking and unlocking involved. Trying my own advice, I'm now displaying gfx_crit_sect_nesting in my own test project... and it's looks very very bad. As in, it starts properly at 0, but if I wave the window around it reaches -1 after a minute or so, then -2, then -3... I'm on a dual-core computer, that may be relevant. This can't be the bug I previously mentioned (I think) - the value is too low, not too high (besides, the previous one ought to be difficult to observe). I have reproduced this on an unmodified regular static build of Allegro. I'll start trying to figure out why now... others might want to check if Allegro does the same on their computer:
Requires a static build of allegro. I grab the title bar of the window and wave it around. After about a minute of that, it usually has a counted down to -3 or so. I'm building this as a console program, but I don't think it matters. edit4: Now I'm having a hard time getting more negative gfx_crit_sect_nesting events. I used to get about 1 every 20 seconds, but it's fallen off to about 1 every 5 minutes now. Sitting around waving the mouse around for 5 minutes is no fun. I have yet to get even a single such event if I make the decrement happen before the unlock, so perhaps I'm confused about that producing a high number instead of a low number. But, maybe not, because I didn't start trying until the rate fell. |
Peter Wang
Member #23
April 2000
|
2. The C-only code originally existed so that Allegro could be ported to non-intel machines, running some flavour of Unix. Nobody ever got around to making the C-only code work on Windows as well. It would be very nice if you sent in a patch, if you've got it working. 3. _exit_gfx_critical() does look wrong. Have you tried decrementing gfx_crit_sect_nesting before leaving the critical section? [edit: looks like it worked?]
|
orz
Member #565
August 2000
|
2. The code works as posted there (well, in all tests so far... haven't tried GDI mode yet...). I suppose I should try to make a patch... GNU and I generally don't get along well... 3. Yeah, I think _exit_gfx_critical fixed the negative counts there. I was initially thinking that the race would be two decrements happening at once under VERY rare circumstances, producing positive counts instead of negative counts. However, on further thought, the other thread can be inside the lock at that time, so it could be incrementing, resulting in positive values. And that's a FAR more likely case, since if the 2nd thread was blocking on the condition (a common scenario if the main thread is doing graphics when a WM_PAINT was recieved) then when in unlocks the first thread is decrementing at pretty much the same time that the second thread is incrementing, making either errors in either direction possible. edit: Also, should gfx_crit_sect_nesting be volatile? my understanding is that it should be, but there's some strange rumors around about the exact meaning of volatile. I don't think it really matters though. |
Evert
Member #794
November 2000
|
On Wednesday 28 February 2007 02:35, Peter Wang said:
2. The C-only code originally existed so that Allegro could be ported to
One of the reasons this wasn't done before now (I think it was discussed in (PS: The post-by-mail feature seems to be broken; is it supposed to still work?) |
orz
Member #565
August 2000
|
Compatibility: Source compatibility is a given of course. But two remaining levels of compatibility exist: compatibility between asm and non-asm dlls and libs, and compatibility between older and newer dlls and libs. The latter is not an issue for 4.3.*, but important for 4.2.x. Therefore, different solutions may be appropriate for 4.3 and 4.2. 4.0 & 4.2: 4.3: |
Peter Wang
Member #23
April 2000
|
Don't worry about ABI incompatibility between the asm and C versions. We'd only guarantee compatibility for the asm version anyway, as we do for x86 linux. We might want to make the C version result in a different DLL name, just so people don't inadvertently distribute incompatible DLLs. For 4.3: yes, we're planning to switch to C anyway. I think we can do it as soon as we have the patch for the Windows port
|
orz
Member #565
August 2000
|
Quote: Don't worry about ABI incompatibility between the asm and C versions. We'd only guarantee compatibility for the asm version anyway, as we do for x86 linux. We might want to make the C version result in a different DLL name, just so people don't inadvertently distribute incompatible DLLs. Well, that makes the code a lot easier for 4.2.1. Quote: For 4.3: yes, we're planning to switch to C anyway. I think we can do it as soon as we have the patch for the Windows port Well... my patch-making skills are less 1337 than my race-condition-finding skills. I have attempted to make a patch. It gives me errors when I try to apply it though. I probably screwed something up somehow, but possibly I'm screwing up applying the patch instead of making it. The text in the patch file looks right to me. Anyway, I've attached a zip to this post (asmlock.zip). The zip contains my non-working patch file, and my modified versions of every source file I modified, including the new source file I created. The zip was made using pkzip 4.0, and does not contain any directory information. The modifications are to 4.2.1 code. I'll check up on the 4.3.0 code to see if I had to do anything else different there, maybe post another zip for that. Also, I'm not sure, but client code using one of these builds MIGHT have to define the ALLEGRO_NO_ASM or ALLEGRO_USE_C symbols to get the header files to use the right bmp_write_line etc implementations. Also, you might prefer a different name for asmlock.c, say, wc_lock.c... the current name is an oxymoron, I've been using it because it's intuitive (asmlock.c is equivalent to asmlock.s, more or less) and because it makes the two files show up next to each other in alphabetical order in my IDE. edit: Oh yeah... I used 1-tab indentation in asmlock.c... I believe Allegro uses that gnuish standard of X spaces or X-Y spaces and 1 tab or X-Y-Z spaces and 1 tab if it's the first tab standard (not sure what the values of X,Y,&Z are) that never looks right unless your editor is set up just right. I'm not sure how to reproduce that indentation, sorry : ). |
Peter Wang
Member #23
April 2000
|
The patch applies fine. In the Allegro directory, use the command patch -p1 -i /path/to/patch You don't need to update the 4.3 code. Once this patch is committed in the 4.2 branch it should be trivial to merge the changes into the 4.3 branch. However, it requires a bit of work. I don't like the forward declarations in asmlock.c, which look like a maintenance nightmare. Allegro uses 3 space indents, with tabs (now deprecated) expanding to multiples of 8 (as is traditional). Nothing to do with GNU.
|
orz
Member #565
August 2000
|
Quote: However, it requires a bit of work. I don't like the forward declarations in asmlock.c, which look like a maintenance nightmare.
Yeah... many of the global symbols referred to only by asm code are not listed in any header file, at least for the asm code I looked at. I did not create header files for them, nor stick them into preexisting header files. The solutions that come to mind would be Not much effort required either way. You can do it or I can do it and attempt to make another patch file : ) Any preferences? Quote: Allegro uses 3 space indents, with tabs (now deprecated) expanding to multiples of 8 (as is traditional). Nothing to do with GNU. Somehow I thought the tradition involved the first tab having a different size than the others, dunno how I came up with that idea. |
Peter Wang
Member #23
April 2000
|
You do it Also, add some comments. Have you tested it with mingw? I very quickly tried to build it using a mingw cross-compiler in linux, but I think the makefiles are currently still pulling in the asm files even when I pass ALLEGRO_USE_C=1. Anyway, it shouldn't be too hard to sort out. Curiously, ALLEGRO_USE_C support was claimed to have been added to the mingw port in 2001. But this was before the merger of ALLEGRO_USE_C and ALLEGRO_NO_ASM (which I think actually meant: no asm calling conventions for bank switching routines). So it probably used to be possible to use C drawing routines but asm bank switching convention in the mingw port. We took a step backwards there.
|
orz
Member #565
August 2000
|
Quote: Any preferences?
Quote: You do it Also, add some comments. Heh. I was also referring to which header file scheme to use, the one more like the code already there or the one more like the normal C way of doing things. But I can just flip a coin on that issue I guess. Quote: Have you tested it with mingw? I very quickly tried to build it using a mingw cross-compiler in linux, but I think the makefiles are currently still pulling in the asm files even when I pass ALLEGRO_USE_C=1. Anyway, it shouldn't be too hard to sort out. MinGW isn't being nice to me at the moment; I can't even build unmodified Allegro with it atm. I can build Allegro with DJGPP, but that's not much help : ). I expect the makefiles may need some touch-up, but that should probably be done by some one other than me... /me is worse with makefiles than with patch/diff. |
|