From: Danny S. <dan...@cl...> - 2004-05-18 06:10:37
|
| -----Original Message----- | From: min...@li... | [mailto:min...@li...] On Behalf Of Wu Yongwei <snip> | Danny, which solution do you prefer? Look in /libjava/sysdep/i386/locks.h: // Atomically replace *addr by new_val if it was initially equal to old. // Return true if the comparison succeeded. // Assumed to have acquire semantics, i.e. later memory operations // cannot execute before the compare_and_swap finishes. inline static bool compare_and_swap(volatile obj_addr_t *addr, obj_addr_t old, obj_addr_t new_val) { char result; __asm__ __volatile__("lock; cmpxchgl %2, %0; setz %1" : "=m"(*addr), "=q"(result) : "r" (new_val), "a"(old), "m"(*addr) : "memory"); return (bool) result; } Couldn't this be used ? The code is licensed under the libgjc license which is essentially the same as gthr-win32..c (GPL with special library exception), so gettinhg approval for gthr-win32 shouldn't be problem. Danny. | | Best regards, | | Yongwei | | | | | ------------------------------------------------------- | This SF.Net email is sponsored by: SourceForge.net Broadband Sign-up now | for SourceForge Broadband and get the fastest 6.0/768 connection for | only $19.95/mo for the first 3 months! | http://ads.osdn.com/?ad_id=2562&alloc_id=6184&op=click | _______________________________________________ | MinGW-dvlpr mailing list | Min...@li... | https://lists.sourceforge.net/lists/listinfo/mingw-dvlpr |
From: Wu Y. <ad...@ne...> - 2004-05-18 09:52:00
|
On Tue, 2004-05-18 at 14:07, Danny Smith wrote: > > | Danny, which solution do you prefer? > > > Look in /libjava/sysdep/i386/locks.h: > > // Atomically replace *addr by new_val if it was initially equal to old. > // Return true if the comparison succeeded. > // Assumed to have acquire semantics, i.e. later memory operations > // cannot execute before the compare_and_swap finishes. > inline static bool > compare_and_swap(volatile obj_addr_t *addr, > obj_addr_t old, > obj_addr_t new_val) > { > char result; > __asm__ __volatile__("lock; cmpxchgl %2, %0; setz %1" > : "=m"(*addr), "=q"(result) > : "r" (new_val), "a"(old), "m"(*addr) > : "memory"); > return (bool) result; > } > > Couldn't this be used ? Basically it is like the Cygwin code. The special part is its `setz' operation, which makes it return a boolean value instead of an integer. This makes its interface different from InterlockedCompareExchange. I think the Cygwin code (although it really seems an `obvious implementation') is better suited for our purpose. Of course, we could use it if need be. And it seems you like the inline assembly way better? Best regards, Yongwei |
From: Danny S. <dan...@cl...> - 2004-05-18 10:34:17
|
----- Original Message ----- From: "Wu Yongwei" <ad...@ne...> To: <min...@li...> Sent: Tuesday, 18 May 2004 10:51 Subject: Re: [MinGW-dvlpr] Fw: [Mingw-users] InterlockedCompareExchange (Was:nosubject) | On Tue, 2004-05-18 at 14:07, Danny Smith wrote: | > | > | Danny, which solution do you prefer? | > | > | > Look in /libjava/sysdep/i386/locks.h: | > | > // Atomically replace *addr by new_val if it was initially equal to old. | > // Return true if the comparison succeeded. | > // Assumed to have acquire semantics, i.e. later memory operations | > // cannot execute before the compare_and_swap finishes. | > inline static bool | > compare_and_swap(volatile obj_addr_t *addr, | > obj_addr_t old, | > obj_addr_t new_val) | > { | > char result; | > __asm__ __volatile__("lock; cmpxchgl %2, %0; setz %1" | > : "=m"(*addr), "=q"(result) | > : "r" (new_val), "a"(old), "m"(*addr) | > : "memory"); | > return (bool) result; | > } | > | > Couldn't this be used ? | | Basically it is like the Cygwin code. The special part is its `setz' | operation, which makes it return a boolean value instead of an integer. | This makes its interface different from InterlockedCompareExchange. I | think the Cygwin code (although it really seems an `obvious | implementation') is better suited for our purpose. Of course, we could | use it if need be. | | And it seems you like the inline assembly way better? Yes. I tried to write my own assembly and came up with this: /* Atomically replace *destination by exchange if it was initially equal to comparand. Return initial value of *destination. */ /* A no-op version for i386 */ static __inline__ long __gthr_i386_InterlockedCompareExchange(long * destination, long exchange, long comparand) { return -1;} /* A version for cpu >= i486 */ static __inline__ long __gthr_i486_InterlockedCompareExchange(long * destination, long exchange, long comparand) { long res; __asm__ __volatile__ ( "lock; cmpxchgl %3,(%0)" :"=r" (destination), "=a" (res) :"0" (destination), "q" (exchange), "a" (comparand) : "memory" ); return res; } static __inline__ int __gthread_mutex_trylock (__gthread_mutex_t *mutex) { if (__gthread_active_p ()) return __gthr_i486_InterlockedCompareExchange((&mutex->counter, 1, 0); else return 0; } Really its just a rephrasing of the cygwin code for i486. So your right, it is obvious. There may be a way to do an i386 version with am InterlockedExchange spinlock, but I don't know if its worth it. Would this work? long __gthr_i386_InterlockedCompareExchange(long * destination, long exchange, long comparand) { static long sl = 0 ; long res ; while(InterlockedExchange(&sl, 1)) Sleep(0); res = *destination ; if (res == comparand) *destination = exchange ; sl = 0 ; return res; } ; Danny | Best regards, | | Yongwei | | | | ------------------------------------------------------- | This SF.Net email is sponsored by: SourceForge.net Broadband | Sign-up now for SourceForge Broadband and get the fastest | 6.0/768 connection for only $19.95/mo for the first 3 months! | http://ads.osdn.com/?ad_id=2562&alloc_id=6184&op=click | _______________________________________________ | MinGW-dvlpr mailing list | Min...@li... | https://lists.sourceforge.net/lists/listinfo/mingw-dvlpr |
From: Paul G. <pga...@at...> - 2004-05-18 17:06:04
|
Pre-Pentium (Intel) processors are, indeed, rare. Now might be a good time to re-evaluate which processors we want to continue to support...? With hyper-threading (32/64bit) now appearing on the scene, I think there will be less and less pre-pentium processors, especially when you can purchase a Pentium 4 (Intel) motherboard (cpu>=1GHZ) for less than 200 USD, something I am planning on doing as soon as I can afford to do so... Paul G. On 18 May 2004 at 22:26, Wu Yongwei wrote: > On Tue, 2004-05-18 at 18:31, Danny Smith wrote: > > > > Yes. I tried to write my own assembly and came up with this: > > > > /* Atomically replace *destination by exchange if it was initially > > equal to > > comparand. Return initial value of *destination. */ > > /* A no-op version for i386 */ > > static __inline__ long > > __gthr_i386_InterlockedCompareExchange(long * destination, > > long exchange, > > long comparand) > > { return -1;} > > > > /* A version for cpu >= i486 */ > > static __inline__ long > > __gthr_i486_InterlockedCompareExchange(long * destination, > > long exchange, > > long comparand) > > { > > long res; > > __asm__ __volatile__ ( > > "lock; cmpxchgl %3,(%0)" > > :"=r" (destination), "=a" (res) > > :"0" (destination), "q" (exchange), "a" (comparand) > > : "memory" ); > > return res; > > } > > > > static __inline__ int > > __gthread_mutex_trylock (__gthread_mutex_t *mutex) > > { > > if (__gthread_active_p ()) > > return __gthr_i486_InterlockedCompareExchange((&mutex->counter, > > 1, 0); > > else > > return 0; > > } > > > > Really its just a rephrasing of the cygwin code for i486. So your > > right, it is obvious. > > > > There may be a way to do an i386 version with am InterlockedExchange > > spinlock, but I don't know if its worth it. Would this work? > > > > long __gthr_i386_InterlockedCompareExchange(long * destination, > > long exchange, > > long comparand) > > { > > static long sl = 0 ; > > > > long res ; > > while(InterlockedExchange(&sl, 1)) > > Sleep(0); > > res = *destination ; > > if (res == comparand) > > *destination = exchange ; > > sl = 0 ; > > return res; > > } ; > > When all threads are using __gthr_win32_mutex_trylock, it works. > However, when some threads use __gthr_win32_mutex_lock and others use > __gthr_win32_mutex_trylock, problems will still occur. And I wonder > whether it will scale well when there are many mutexes. > > Do you really think it is needed? I mean, there might still be > Windows 95 boxes around (I myself have one), but are there really > anyone running 32-bit Windows on i386 boxes? I do not know any > running PCs with CPUs earlier than Pentium. > > Best regards, > > Yongwei > > > > > ------------------------------------------------------- > This SF.Net email is sponsored by: SourceForge.net Broadband > Sign-up now for SourceForge Broadband and get the fastest > 6.0/768 connection for only $19.95/mo for the first 3 months! > http://ads.osdn.com/?ad_id=2562&alloc_id=6184&op=click > _______________________________________________ > MinGW-dvlpr mailing list > Min...@li... > https://lists.sourceforge.net/lists/listinfo/mingw-dvlpr |
From: Wu Y. <ad...@sh...> - 2004-05-18 14:26:44
|
On Tue, 2004-05-18 at 18:31, Danny Smith wrote: > > Yes. I tried to write my own assembly and came up with this: > > /* Atomically replace *destination by exchange if it was initially equal to > comparand. Return initial value of *destination. */ > /* A no-op version for i386 */ > static __inline__ long > __gthr_i386_InterlockedCompareExchange(long * destination, > long exchange, > long comparand) > { return -1;} > > /* A version for cpu >= i486 */ > static __inline__ long > __gthr_i486_InterlockedCompareExchange(long * destination, > long exchange, > long comparand) > { > long res; > __asm__ __volatile__ ( > "lock; cmpxchgl %3,(%0)" > :"=r" (destination), "=a" (res) > :"0" (destination), "q" (exchange), "a" (comparand) > : "memory" ); > return res; > } > > static __inline__ int > __gthread_mutex_trylock (__gthread_mutex_t *mutex) > { > if (__gthread_active_p ()) > return __gthr_i486_InterlockedCompareExchange((&mutex->counter, 1, 0); > else > return 0; > } > > Really its just a rephrasing of the cygwin code for i486. So your right, it is obvious. > > There may be a way to do an i386 version with am InterlockedExchange spinlock, > but I don't know if its worth it. Would this work? > > long __gthr_i386_InterlockedCompareExchange(long * destination, > long exchange, > long comparand) > { > static long sl = 0 ; > > long res ; > while(InterlockedExchange(&sl, 1)) > Sleep(0); > res = *destination ; > if (res == comparand) > *destination = exchange ; > sl = 0 ; > return res; > } ; When all threads are using __gthr_win32_mutex_trylock, it works. However, when some threads use __gthr_win32_mutex_lock and others use __gthr_win32_mutex_trylock, problems will still occur. And I wonder whether it will scale well when there are many mutexes. Do you really think it is needed? I mean, there might still be Windows 95 boxes around (I myself have one), but are there really anyone running 32-bit Windows on i386 boxes? I do not know any running PCs with CPUs earlier than Pentium. Best regards, Yongwei |
From: Aaron W. L. <aar...@aa...> - 2004-05-18 20:31:49
|
Wu Yongwei wrote: >When all threads are using __gthr_win32_mutex_trylock, it works. >However, when some threads use __gthr_win32_mutex_lock and others use >__gthr_win32_mutex_trylock, problems will still occur. And I wonder >whether it will scale well when there are many mutexes. > > > Pardon my ignorance, but what is __gthr_win32_mutex used for? Exception handling, anything else? Are they ever intended to be held for more than a short period of time? Is there any particular reason normal spinlocks can't be used? Spinlocks can be relatively safe on Windows compared to other operating systems, and are almost certainly going to be faster than any other synchronization primative. This also avoids possibly far-fetched strange problems involving inability to allocate or manipulate a mutex, avoiding those suspicious almost-never-used error control paths. Aaron W. LaFramboise |
From: Wu Y. <ad...@ne...> - 2004-05-19 07:47:21
|
On Wed, 2004-05-19 at 04:31, Aaron W. LaFramboise wrote: > Wu Yongwei wrote: > > >When all threads are using __gthr_win32_mutex_trylock, it works. > >However, when some threads use __gthr_win32_mutex_lock and others use > >__gthr_win32_mutex_trylock, problems will still occur. And I wonder > >whether it will scale well when there are many mutexes. > > > > > > > Pardon my ignorance, but what is __gthr_win32_mutex used for? Exception > handling, anything else? Are they ever intended to be held for more > than a short period of time? Is there any particular reason normal > spinlocks can't be used? Spinlocks can be relatively safe on Windows > compared to other operating systems, and are almost certainly going to > be faster than any other synchronization primative. This also avoids > possibly far-fetched strange problems involving inability to allocate or > manipulate a mutex, avoiding those suspicious almost-never-used error > control paths. AFAIK, __gthr_mutex_... are required interfaces in order to support the concept of a cross-platform mutex. Libstdc++-v3 uses it to synchronize memory accesses. The idea is good, but the requirement of an unused __gthr_mutex_trylock is really a headache on Win32: Merely because of its existence (although it is not really used in GCC), Danny used Win32 MUTEXs instead of CRITICAL_SECTIONs to implement __gthr_mutex_... interfaces in order to work around the lack of TryEnterCriticalSection on Win9x platforms. My patch used a customized mutex implementation to accelerate the lock/unlock operations, but was not careful enough to make it work on Windows 95 boxes. Danny, I searched online and found that the system requirements for Windows 98 were 486DX/66MHz. So I doubt the possibility of implementing InterlockedCompareExchange on an i386 CPU. Best regards, Wu Yongwei |
From: Earnie B. <ea...@us...> - 2004-05-19 10:58:15
|
Wu Yongwei wrote: >Danny, I searched online and found that the system requirements for >Windows 98 were 486DX/66MHz. So I doubt the possibility of implementing >InterlockedCompareExchange on an i386 CPU. > > Let's move to say support for Win95 by MinGW is obsoleted. Anyone wanting to maintain Win95 support should make plans to use older development software and not upgrade. Earnie. -- http://www.mingw.org http://sourceforge.net/projects/mingw https://sourceforge.net/donate/index.php?user_id=15438 |
From: Wu Y. <ad...@sh...> - 2004-05-19 15:19:34
|
On Wed, 2004-05-19 at 18:58, Earnie Boyd wrote: > Wu Yongwei wrote: > > >Danny, I searched online and found that the system requirements for > >Windows 98 were 486DX/66MHz. So I doubt the possibility of implementing > >InterlockedCompareExchange on an i386 CPU. > > > > > Let's move to say support for Win95 by MinGW is obsoleted. Anyone > wanting to maintain Win95 support should make plans to use older > development software and not upgrade. > > Earnie. Hi, Earnie, thanks for speaking up. However, is it a little overkill to obsolete Windows 95 for a function not really used? Either solution in my e-mail on Monday should work (and makes no difference currently since not really used). Regards, Yongwei |
From: Danny S. <dan...@cl...> - 2004-05-19 20:40:19
|
----- Original Message ----- From: "Earnie Boyd" | Wu Yongwei wrote: | | >Danny, I searched online and found that the system requirements for | >Windows 98 were 486DX/66MHz. So I doubt the possibility of implementing | >InterlockedCompareExchange on an i386 CPU. | > | > | Let's move to say support for Win95 by MinGW is obsoleted. Anyone | wanting to maintain Win95 support should make plans to use older | development software and not upgrade. | Wow, we not just talking about the developer but about the end-user. Are you saying that the mingw toolset should not support building libstcdc++-dependent apps for W95 users. Before we do that, I would say just make the function we're talking about always return -1 (not implemented) Its not currently used in libstdc++ anyway. Danny | Earnie. | | -- | http://www.mingw.org | http://sourceforge.net/projects/mingw | https://sourceforge.net/donate/index.php?user_id=15438 | | | | ------------------------------------------------------- | This SF.Net email is sponsored by: SourceForge.net Broadband | Sign-up now for SourceForge Broadband and get the fastest | 6.0/768 connection for only $19.95/mo for the first 3 months! | http://ads.osdn.com/?ad_id=2562&alloc_id=6184&op=click | _______________________________________________ | MinGW-dvlpr mailing list | Min...@li... | https://lists.sourceforge.net/lists/listinfo/mingw-dvlpr |
From: Earnie B. <ea...@us...> - 2004-05-19 21:16:50
|
Danny Smith wrote: >----- Original Message ----- >From: "Earnie Boyd" >| Wu Yongwei wrote: >| >| >Danny, I searched online and found that the system requirements for >| >Windows 98 were 486DX/66MHz. So I doubt the possibility of implementing >| >InterlockedCompareExchange on an i386 CPU. >| > >| > >| Let's move to say support for Win95 by MinGW is obsoleted. Anyone >| wanting to maintain Win95 support should make plans to use older >| development software and not upgrade. >| >Wow, we not just talking about the developer but about the end-user. Are you saying that >the mingw toolset should not support building libstcdc++-dependent apps for W95 users. >Before we do that, I would say just make the function we're talking about always return -1 >(not implemented) Its not currently used in libstdc++ anyway. > > > Sorry, I probably spoke out of turn here. My first reaction is that W95 is old stuff and when old stuff is getting in the way I tend to obsolete the support. However, I like your method better. Earnie -- http://www.mingw.org http://sourceforge.net/projects/mingw https://sourceforge.net/donate/index.php?user_id=15438 |
From: Thomas P. <tp...@gm...> - 2004-05-19 21:07:00
|
Wu Yongwei wrote: > On Wed, 2004-05-19 at 04:31, Aaron W. LaFramboise wrote: > >>Wu Yongwei wrote: >> >> >>>When all threads are using __gthr_win32_mutex_trylock, it works. >>>However, when some threads use __gthr_win32_mutex_lock and others use >>>__gthr_win32_mutex_trylock, problems will still occur. And I wonder >>>whether it will scale well when there are many mutexes. >>> >>> >>> >> >>Pardon my ignorance, but what is __gthr_win32_mutex used for? Exception >>handling, anything else? Are they ever intended to be held for more >>than a short period of time? Is there any particular reason normal >>spinlocks can't be used? Spinlocks can be relatively safe on Windows >>compared to other operating systems, and are almost certainly going to >>be faster than any other synchronization primative. This also avoids >>possibly far-fetched strange problems involving inability to allocate or >>manipulate a mutex, avoiding those suspicious almost-never-used error >>control paths. > > > AFAIK, __gthr_mutex_... are required interfaces in order to support the > concept of a cross-platform mutex. Libstdc++-v3 uses it to synchronize > memory accesses. The idea is good, but the requirement of an unused > __gthr_mutex_trylock is really a headache on Win32: Merely because of > its existence (although it is not really used in GCC), Danny used Win32 > MUTEXs instead of CRITICAL_SECTIONs to implement __gthr_mutex_... > interfaces in order to work around the lack of TryEnterCriticalSection > on Win9x platforms. My patch used a customized mutex implementation to > accelerate the lock/unlock operations, but was not careful enough to > make it work on Windows 95 boxes. > > Danny, I searched online and found that the system requirements for > Windows 98 were 486DX/66MHz. So I doubt the possibility of implementing > InterlockedCompareExchange on an i386 CPU. > Just to add my 2 cents here. The new mutex implementation needs an xadd based InterlockedIncrement/Decrement too, otherwise you can not test reliable for a return value other than 0. To keep W95 running i vote for inline assembler versions of InterlockedIncrement/Decrement and CompareExchange based on xadd and cmpxchg. Better drop i386 than W95. And everyone here should be aware of the fact that the new mutex code will break binary compatibility for the w32sharedptr stuff for throwing exceptions over dll boundaries. Programs build with the new code will not work with older DLLs and vice versa. You can not have a shared ptr with 2 different mutex implementations. BTW, there was a mail in the cygwin ml regarding dwarf2 exceptions for cygwin gcc. Maybe a got time for new try ? Thomas |
From: Thomas P. <tp...@gm...> - 2004-05-19 21:26:51
|
Thomas Pfaff wrote: > BTW, there was a mail in the cygwin ml regarding dwarf2 exceptions for > cygwin gcc. Maybe a got time for new try ? good Thomas |
From: Danny S. <dan...@cl...> - 2004-05-19 21:32:39
|
----- Original Message ----- From: "Thomas Pfaff" | And everyone here should be aware of the fact that the new mutex code | will break binary compatibility for the w32sharedptr stuff for throwing | exceptions over dll boundaries. Programs build with the new code will | not work with older DLLs and vice versa. You can not have a shared ptr | with 2 different mutex implementations. The libstcd++ with gcc-3.4.0 has other ABI changes, so backwards compatability is probably already broken. | | BTW, there was a mail in the cygwin ml regarding dwarf2 exceptions for | cygwin gcc. Maybe a got time for new try ? | I believe that was about Dwarf debug info, not EH. I have been testing DW2 EH and still run into the ws2api callback problem. Danny | Thomas | | | ------------------------------------------------------- | This SF.Net email is sponsored by: SourceForge.net Broadband | Sign-up now for SourceForge Broadband and get the fastest | 6.0/768 connection for only $19.95/mo for the first 3 months! | http://ads.osdn.com/?ad_id=2562&alloc_id=6184&op=click | _______________________________________________ | MinGW-dvlpr mailing list | Min...@li... | https://lists.sourceforge.net/lists/listinfo/mingw-dvlpr |
From: Thomas P. <tp...@gm...> - 2004-05-19 21:55:27
|
Danny Smith wrote: > ----- Original Message ----- > From: "Thomas Pfaff" > | > | BTW, there was a mail in the cygwin ml regarding dwarf2 exceptions for > | cygwin gcc. Maybe a good time for new try ? > | > > I believe that was about Dwarf debug info, not EH. Sorry, you are right. Thomas |
From: Wu Y. <ad...@ne...> - 2004-05-20 08:41:02
|
On Thu, 2004-05-20 at 05:06, Thomas Pfaff wrote: > Wu Yongwei wrote: > > On Wed, 2004-05-19 at 04:31, Aaron W. LaFramboise wrote: > > > >>Wu Yongwei wrote: > >> > >> > >>>When all threads are using __gthr_win32_mutex_trylock, it works. > >>>However, when some threads use __gthr_win32_mutex_lock and others use > >>>__gthr_win32_mutex_trylock, problems will still occur. And I wonder > >>>whether it will scale well when there are many mutexes. > >>> > >>> > >>> > >> > >>Pardon my ignorance, but what is __gthr_win32_mutex used for? Exception > >>handling, anything else? Are they ever intended to be held for more > >>than a short period of time? Is there any particular reason normal > >>spinlocks can't be used? Spinlocks can be relatively safe on Windows > >>compared to other operating systems, and are almost certainly going to > >>be faster than any other synchronization primative. This also avoids > >>possibly far-fetched strange problems involving inability to allocate or > >>manipulate a mutex, avoiding those suspicious almost-never-used error > >>control paths. > > > > > > AFAIK, __gthr_mutex_... are required interfaces in order to support the > > concept of a cross-platform mutex. Libstdc++-v3 uses it to synchronize > > memory accesses. The idea is good, but the requirement of an unused > > __gthr_mutex_trylock is really a headache on Win32: Merely because of > > its existence (although it is not really used in GCC), Danny used Win32 > > MUTEXs instead of CRITICAL_SECTIONs to implement __gthr_mutex_... > > interfaces in order to work around the lack of TryEnterCriticalSection > > on Win9x platforms. My patch used a customized mutex implementation to > > accelerate the lock/unlock operations, but was not careful enough to > > make it work on Windows 95 boxes. > > > > Danny, I searched online and found that the system requirements for > > Windows 98 were 486DX/66MHz. So I doubt the possibility of implementing > > InterlockedCompareExchange on an i386 CPU. > > > > Just to add my 2 cents here. > > The new mutex implementation needs an xadd based > InterlockedIncrement/Decrement too, otherwise you can not test reliable > for a return value other than 0. > > To keep W95 running i vote for inline assembler versions of > InterlockedIncrement/Decrement and CompareExchange based on xadd and > cmpxchg. Better drop i386 than W95. Have we reached a consensus here? If so, could we just use Cygwin code, or do we have to rewrite the inline assembly versions without looking at existing code? It will be a pity if we have to re-invent wheels (albeit easy ones) every time, among Open Source communities. Chris, are you here? ;-) Best regards, Yongwei |
From: Wu Y. <ad...@sh...> - 2004-05-23 13:09:04
Attachments:
gthr-win32.diff
|
On Thu, 2004-05-20 at 05:06, Thomas Pfaff wrote: > Wu Yongwei wrote: > > On Wed, 2004-05-19 at 04:31, Aaron W. LaFramboise wrote: > > > >>Wu Yongwei wrote: > >> > >> > >>>When all threads are using __gthr_win32_mutex_trylock, it works. > >>>However, when some threads use __gthr_win32_mutex_lock and others use > >>>__gthr_win32_mutex_trylock, problems will still occur. And I wonder > >>>whether it will scale well when there are many mutexes. > >>> > >>> > >>> > >> > >>Pardon my ignorance, but what is __gthr_win32_mutex used for? Exception > >>handling, anything else? Are they ever intended to be held for more > >>than a short period of time? Is there any particular reason normal > >>spinlocks can't be used? Spinlocks can be relatively safe on Windows > >>compared to other operating systems, and are almost certainly going to > >>be faster than any other synchronization primative. This also avoids > >>possibly far-fetched strange problems involving inability to allocate or > >>manipulate a mutex, avoiding those suspicious almost-never-used error > >>control paths. > > > > > > AFAIK, __gthr_mutex_... are required interfaces in order to support the > > concept of a cross-platform mutex. Libstdc++-v3 uses it to synchronize > > memory accesses. The idea is good, but the requirement of an unused > > __gthr_mutex_trylock is really a headache on Win32: Merely because of > > its existence (although it is not really used in GCC), Danny used Win32 > > MUTEXs instead of CRITICAL_SECTIONs to implement __gthr_mutex_... > > interfaces in order to work around the lack of TryEnterCriticalSection > > on Win9x platforms. My patch used a customized mutex implementation to > > accelerate the lock/unlock operations, but was not careful enough to > > make it work on Windows 95 boxes. > > > > Danny, I searched online and found that the system requirements for > > Windows 98 were 486DX/66MHz. So I doubt the possibility of implementing > > InterlockedCompareExchange on an i386 CPU. > > > > Just to add my 2 cents here. > > The new mutex implementation needs an xadd based > InterlockedIncrement/Decrement too, otherwise you can not test reliable > for a return value other than 0. > > To keep W95 running i vote for inline assembler versions of > InterlockedIncrement/Decrement and CompareExchange based on xadd and > cmpxchg. Better drop i386 than W95. Thomas, I had already "re-invented the wheel" (written all the three functions in inline assembly so that I need not worry about licensing issues on this matter ever more) and finished the new patch based on them, but at last gave up, because they have worse performance than the system routines on uniprocessor systems. I guess the reason is that I have to use "lock" to ensure correctness on all systems, but the OS can know it is a uniprocessor system and use routines without "lock". So I adopted Aaron's opinion (thanks, Aaron) and used -1 as the initial counter value. The patch is attached for your review here. Danny, if you do not see any problems, I shall post it to gcc-patches. Best regards, Wu Yongwei |
From: Danny S. <dan...@cl...> - 2004-05-23 20:51:58
|
+inline long __gthr_i486_lock_cmp_xchg(long *dest, long xchg, long comperand) +{ + long result; + __asm__ __volatile__ ("\n\ + lock\n\ + cmpxchgl %4, (%1)\n" + : "=a" (result), "=r" (dest) + : "0" (comperand), "1" (dest), "r" (xchg) + : "memory"); + return result; +} + A couple of comments: Make static (we can't assume it won't always be used in C). Make -masm=intel compat: cmpxchg{l} {%4, (%1)|(%1), %4) \n" I don't like this in a public header: +#undef InterlockedCompareExchange +#define InterlockedCompareExchange __gthr_i486_lock_cmp_xchg What happens if windows.h is included after this file? Oh, "comperand" should probably be spelt "comparand" Have you tested the inline at different optimisation levels? I'm glad you didn't use the cygwin winbase.h inlines for increment and decrement. It turns out they are buggy. Try this at -O2: #include <windows.h> #include <stdio.h> /* copied from cygwin's winbase.h */ __inline__ long ilockincr (long *m) { register int __res; __asm__ __volatile__ ("\n\ movl $1,%0\n\ lock xadd %0,(%1)\n\ inc %0\n\ ": "=a" (__res), "=q" (m): "1" (m)); return __res; } void test1() { long x = 9; long y = ilockincr(&x); printf ("ilockincr: %ld\t%ld\n", x, y); } void test2() { long x = 9; long y =InterlockedIncrement(&x); printf ("InterlockedIncrement: %ld\t%ld\n", x, y); } int main() { test1(); test2(); return 0; } Danny |
From: Wu Y. <ad...@ne...> - 2004-05-24 06:56:17
|
On Mon, 2004-05-24 at 04:48, Danny Smith wrote: > +inline long __gthr_i486_lock_cmp_xchg(long *dest, long xchg, long comperand) > +{ > + long result; > + __asm__ __volatile__ ("\n\ > + lock\n\ > + cmpxchgl %4, (%1)\n" > + : "=a" (result), "=r" (dest) > + : "0" (comperand), "1" (dest), "r" (xchg) > + : "memory"); > + return result; > +} > + > > A couple of comments: > > Make static (we can't assume it won't always be used in C). OK. Although this could make several copies of the function when optimization is off. The naming is hardly to cause any conflicts. > Make -masm=intel compat: > cmpxchg{l} {%4, (%1)|(%1), %4) \n" Ah, I do not know it before. Thanks for spreading the knowledge. Locally done. > I don't like this in a public header: > > +#undef InterlockedCompareExchange > +#define InterlockedCompareExchange __gthr_i486_lock_cmp_xchg > > What happens if windows.h is included after this file? I know the consequences. But please note: 1) it is defined only when _GTHR_I486_INLINE_LOCK_PRIMITIVES is defined; 2) I want to ensure that people can run his code on Windows 95 if he calls __gthread_mutex_trylock with __GTHREAD_HIDE_WIN32API=0 and _GTHR_I486_INLINE_LOCK_PRIMITIVES defined. > Oh, "comperand" should probably be spelt "comparand" The parameter names are all from MSDN. I just followed the Microsoft way. Neither "comperand" nor "comparand" can be found in the online Merriam-Webster dictionary. Maybe I should look it up in my unabridged Webster's Third New International Dictionary. :-) > Have you tested the inline at different optimisation levels? I tested with and without -O2. > I'm glad you didn't use the cygwin winbase.h inlines for increment and decrement. It > turns out they are buggy. > > Try this at -O2: > > #include <windows.h> > #include <stdio.h> > > /* copied from cygwin's winbase.h */ > __inline__ long > ilockincr (long *m) > { > register int __res; > __asm__ __volatile__ ("\n\ > movl $1,%0\n\ > lock xadd %0,(%1)\n\ > inc %0\n\ > ": "=a" (__res), "=q" (m): "1" (m)); > return __res; > } > > > > void test1() > { > long x = 9; > long y = ilockincr(&x); > printf ("ilockincr: %ld\t%ld\n", x, y); > } > > void test2() > { > long x = 9; > long y =InterlockedIncrement(&x); > printf ("InterlockedIncrement: %ld\t%ld\n", x, y); > } > > int main() > { > test1(); > test2(); > return 0; > } Ah. I did not know but the reason is quite simple: they lack the "memory" clobber (which both your code and mine has). Should we CC to Chris reporting this? > Danny Regards, Yongwei |
From: Earnie B. <ea...@us...> - 2004-05-24 10:36:49
|
Wu Yongwei wrote: > Ah. I did not know but the reason is quite simple: they lack the > >"memory" clobber (which both your code and mine has). Should we CC to >Chris reporting this? > > Chris is a member of this list. Perhaps you should CC Corina though. Earnie -- http://www.mingw.org http://sourceforge.net/projects/mingw https://sourceforge.net/donate/index.php?user_id=15438 |
From: Christopher F. <cg...@al...> - 2004-05-24 12:19:43
|
On Mon, May 24, 2004 at 06:36:39AM -0400, Earnie Boyd wrote: >Wu Yongwei wrote: >>Ah. I did not know but the reason is quite simple: they lack the >> >>"memory" clobber (which both your code and mine has). Should we CC to >>Chris reporting this? >> >Chris is a member of this list. Perhaps you should CC Corina though. But I don't scan every message here looking for cygwin bug reports. The somewhat cryptic note to the cygwin list did alert me to the problem though. Thanks. Btw, shouldn't the inline asm also include a "cc" option? cgf |
From: Christopher F. <cg...@al...> - 2004-05-25 03:43:27
|
On Mon, May 24, 2004 at 02:55:34PM +0800, Wu Yongwei wrote: >Ah. I did not know but the reason is quite simple: they lack the >"memory" clobber (which both your code and mine has). Should we CC to >Chris reporting this? I don't understand why a memory clobber was needed in this case. Shouldn't it be something like this: __inline__ long ilockincr (long *m) { register int __res; __asm__ __volatile__ ("\n\ movl $1,%0\n\ lock xadd %0,%1\n\ inc %0\n\ ": "=a" (__res), "+m" (m)); return __res; } That doesn't work either, but I don't know why. Adding a "memory" has the desired result but my reading of why this is needed is that the instructions "can access memory in an unpredictable way". This isn't unpredicatable. We know that m is supposed to be clobbered. Why isn't specifying m as an output sufficient for that? cgf |
From: Danny S. <dan...@cl...> - 2004-05-25 04:17:16
|
----- Original Message ----- From: "Christopher Faylor" | On Mon, May 24, 2004 at 02:55:34PM +0800, Wu Yongwei wrote: | >Ah. I did not know but the reason is quite simple: they lack the | >"memory" clobber (which both your code and mine has). Should we CC to | >Chris reporting this? | | I don't understand why a memory clobber was needed in this case. Shouldn't | it be something like this: | | __inline__ long | ilockincr (long *m) | { | register int __res; | __asm__ __volatile__ ("\n\ | movl $1,%0\n\ | lock xadd %0,%1\n\ | inc %0\n\ | ": "=a" (__res), "+m" (m)); | return __res; | } | Have a look at config/i486/atomicity.h in 3.4.0 or trunk libstdc++ sources.. (m) is input and output. /* From libstdc++ i486/atomicity.h */ Atomically add __val to *__mem. Return intial value of *__mem. static __inline__ long __gthr_i486__exchange_and_add (volatile long * __mem, const int __val) { register long __sav_val; __asm__ __volatile__ ("lock; xadd{l} {%0,%1|%1,%0}" : "=r" (__save_val), "=m" (*__mem) : "0" (__val), "m" (*__mem)); return __save_val; } static __inline__ long __gthr_i486__InterlockedIncrement (volatile long* __mem) { return __gthr_i486__exchange_and_add (__mem, 1) + 1; } static __inline__ long __gthr_i486__InterlockedDecrement (volatile long * __mem) { return __gthr_i486__exchange_and_add (__mem, -1) - 1; } Danny | That doesn't work either, but I don't know why. Adding a "memory" has | the desired result but my reading of why this is needed is that the | instructions "can access memory in an unpredictable way". This isn't | unpredicatable. We know that m is supposed to be clobbered. Why isn't | specifying m as an output sufficient for that? | | cgf | |
From: Christopher F. <cg...@al...> - 2004-05-25 23:50:19
|
On Tue, May 25, 2004 at 05:14:00AM +0100, Danny Smith wrote: > >----- Original Message ----- >From: "Christopher Faylor" >| On Mon, May 24, 2004 at 02:55:34PM +0800, Wu Yongwei wrote: >| >Ah. I did not know but the reason is quite simple: they lack the >| >"memory" clobber (which both your code and mine has). Should we CC to >| >Chris reporting this? >| >| I don't understand why a memory clobber was needed in this case. Shouldn't >| it be something like this: >| >| __inline__ long >| ilockincr (long *m) >| { >| register int __res; >| __asm__ __volatile__ ("\n\ >| movl $1,%0\n\ >| lock xadd %0,%1\n\ >| inc %0\n\ >| ": "=a" (__res), "+m" (m)); >| return __res; >| } >| > >Have a look at config/i486/atomicity.h in 3.4.0 or trunk libstdc++ sources.. > >(m) is input and output. > >/* From libstdc++ i486/atomicity.h */ > >Atomically add __val to *__mem. Return intial value of *__mem. > >static __inline__ long >__gthr_i486__exchange_and_add (volatile long * __mem, const int __val) >{ > register long __sav_val; > __asm__ __volatile__ ("lock; xadd{l} {%0,%1|%1,%0}" > : "=r" (__save_val), "=m" (*__mem) ^ There's the clue. Pretty obvious when you think about it. Making that change seems to fix the problem with cygwin's versions of these routines. cgf |
From: Wu Y. <ad...@ne...> - 2004-05-25 11:58:26
Attachments:
x86_lock.h
|
On Tue, 2004-05-25 at 11:43, Christopher Faylor wrote: > On Mon, May 24, 2004 at 02:55:34PM +0800, Wu Yongwei wrote: > >Ah. I did not know but the reason is quite simple: they lack the > >"memory" clobber (which both your code and mine has). Should we CC to > >Chris reporting this? > > I don't understand why a memory clobber was needed in this case. Shouldn't > it be something like this: > > __inline__ long > ilockincr (long *m) > { > register int __res; > __asm__ __volatile__ ("\n\ > movl $1,%0\n\ > lock xadd %0,%1\n\ > inc %0\n\ > ": "=a" (__res), "+m" (m)); > return __res; > } > > That doesn't work either, but I don't know why. Adding a "memory" has > the desired result but my reading of why this is needed is that the > instructions "can access memory in an unpredictable way". This isn't > unpredicatable. We know that m is supposed to be clobbered. Why isn't > specifying m as an output sufficient for that? > > cgf Ha ha, it seems we have the same opinions simultaneously. I do not like "memory" either. In fact, I had finished the attached file for your review before reading your messages. The attached file is considered in the public domain. Anyone can do anything about it. Best regards, Wu Yongwei |