Marcus Meissner wrote:
On Wed, Oct 26, 2005 at 11:01:51AM -0700, ssawai wrote:
On several places we use third-party components that use native pthreads from which we receive callbacks in different pthreads.
Is it possible to use Wine/pthread mix? What would be the preferred way of doing things?
It's possible, and for us it worked pretty well. Our winelib application links against several native unix DLLs which create their own threads with the pthreads APIs. My knowledge is based on the state of wine about a year ago, so this stuff could have changed. I'm definitely not an expert on this stuff, but I've seen a lot of the threading code when trying to debug my own code.
Wine has two threading models on linux, the old kernel threads and the newer pthread interface. In the pthread model, windows threads and threading primitives are built on top of their pthread counterparts. In the kthread model, the pthread functions are built on top of wine's own implementation, which is built on top of clone.
I don't think we ever had problems with one native library using pthreads inside itself, or in combination with another native shared library. The tricky bit is allowing threads that aren't created by wine to call Windows API functions. Most of the Windows API functions rely on being able to get the Thread Environment Block for the current thread, and that's a windows-specific thing that won't exist if you just create the thread with a call to the native pthread_create function.
In the wine-kthread model (which I'm more familiar with), wine overrides most (all?) of the native pthreads functions, causing calls to pthread_mutex_init(), for example, to internally create a CriticalSection object. pthread_create() is also one of the functions that is overridden, and in that wine calls clone() to make the new thread, then creates a TEB for new thread before handing control off back to your native shared library. If you use a lot of the less-often-used parts of the pthread library, you might run into limitations in wine's emulation of the pthread functions.
On other platforms where the wine-kthread model isn't supported (Solaris, HP-UX, and possibly newer linux systems where wine-pthread is chosen?), this wouldn't work. On those systems, the pthread_create function goes directly to the system's pthread library, so wine doesn't have a chance to intercept it and create a TEB. To get around this, our main thread creates a helper thread that is wine-aware via CreateThread. This helper thread creates a pthread mutex/condition variable pair and uses the pthread functions to listen for requests from any threads created in native shared libraries. When it gets a request, it executes the windows API calls in its own wine-aware thread and then returns control to the calling native thread. It's a bit cumbersome, but there are not many places we need to make windows calls from native threads; usually it's just a call to PostMessage to notify the GUI that something happened.
On many places we use dynamic library loading (LoadLibrary() on Win32). Possibly we will need to load native libraries also. Is it possible to load shared libraries (.so) linked with Wine, with native dlopen(), since we don't need the Win32 DllMain mechanism. What would be the preferred/best way of doing things?
Using dlopen to load native shared libraries into a winelib application has always worked fine for me. If you're loading shared libraries that are linked with wine (winelib .dll.so) I think you must use LoadLibrary to do it. I think there was a time when you could dlopen a .dll.so directly, but I believe it stopped working a year or two ago, but I can't think of any good reason not to use LoadLibrary for those cases.
Eric