On Wed, 21 Nov 2001, Peter Hunnisett wrote:
So our current pthreads mutex implementation works in Linux by the skin of its teeth, becuase the first field in the mutex is reserved and initialized to 0 (in both the static and pthread_mutex_init cases), provided the version of LinuxThreads is new enough and a pointer is the same size as an int.
I know that...
Now I assume that this would mean it fails curiously for things that don't use LinuxThreads.
Which of those things may be of concern?
This would also seem to mean, since we need binary compatibility, that things could even fail if someone upgrades their libc :(
Doubtful, libc is typically backwards compatible.
BTW, our check is presently basically only on __GLIBC__. Flavour me ignorant, and lazy, but I would assume that this not a Linux only symbol.
Well, use whatever definition suits you, if you have any other systems with GNU libc that can run Wine.
Reader/Writer locks can be made to work the same way, as the mutex, since there are several fields which are initialized to NULL and we can then HeapAlloc our own structure off that field. We can then come up with weird and wonderful exceptions for the wonky cases that are sure to exist in some implementation of pthreads.
I don't expect Wine to run on *that* many flavors... "hijacking" pthreads is probably only *really* necessary on x86, on other architectures Wine may as well use the native pthreads, so that already limits us to the unix variants that run on x86...
rwlocks on the other hand are not so lucky as there's no unused bits:
From glibc-2.2.4
/* Read-write locks. */ typedef struct _pthread_rwlock_t { struct _pthread_fastlock __rw_lock; /* Lock to guarantee mutual exclusion */ int __rw_readers; /* Number of readers */ _pthread_descr __rw_writer; /* Identity of writer, or NULL if none */ _pthread_descr __rw_read_waiting; /* Threads waiting for reading */ _pthread_descr __rw_write_waiting; /* Threads waiting for writing */ int __rw_kind; /* Reader/Writer preference selection */ int __rw_pshared; /* Shared between processes or not */ } pthread_rwlock_t;
# define PTHREAD_RWLOCK_INITIALIZER \ { __LOCK_INITIALIZER, 0, NULL, NULL, NULL, \ PTHREAD_RWLOCK_DEFAULT_NP, PTHREAD_PROCESS_PRIVATE }
Have you checked what __LOCK_INITIALIZER is?
#define __LT_SPINLOCK_INIT 0 #define __LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT }
So you can indeed use a copy of wine_mutex on top of a linuxthreads rwlock too, since that overloaded pointer will still be initialized to 0 even if the app used linuxthreads's PTHREAD_RWLOCK_INITIALIZER.