On Wed, Oct 26, 2005 at 11:01:51AM -0700, ssawai wrote:
Message body follows:
Marcus,
We have been using WINE for about a year to port the Windows version of our product to Red Hat AS 3.0. We have come up against some issues with threading and our developers have some questions which I am including below.
Please ask them on wine-devel@winehq.org ... I am just one of the developers ;) I am cc'ing the list.
- Wine version
According to winehq.org, Wine is still alpha software. Since we are not interested in Wine as a complete Windows simulator and we don't plan to run binaries compiled on Windows, what would be the best (development) Wine version to use?
2 days ago we released version 0.9, our first BETA version.
This is the version to use for now ;)
- Threading
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?
Umm. I do not know. It might be possible.
We provide a kind of barebones pthread implementation ourselves to help this mix.
Our tests show that Wine implements Win32 threads by creating new processes (via clone() syscall). This is a problem, because, pthreads spawned from Wine thread, cannot be interlocked with Wine/Win32 Mutex or CriticalSection. They also seem to be scheduled (by kernel) only within parent Wine thread. If parent Wine thread terminates early - we have a crash the moment when one of the orphan pthreads try to place a callback.
- Dynamic library loading
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?
dlopen() is possible from within a WINE context.
dlopen() a wine library from a non-WINE program will currently not work, you have to setup the wine context before.
Can you help with these? If not, can you suggest who may be able to give us some expert insight with our issues?
I hope some of the other developers on wine-devel@winehq.org can fill in here.
Ciao, Marcus
On 10/27/05, Marcus Meissner marcus@jet.franken.de wrote:
- Threading
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?
Umm. I do not know. It might be possible.
We provide a kind of barebones pthread implementation ourselves to help this mix.
It's safest if you can keep the Windows and Linux parts of your product in separate processes, and communicate via IPC (say, sockets). Would that be possible for you, ssawai?
Our tests show that Wine implements Win32 threads by creating new processes (via clone() syscall). This is a problem, because, pthreads spawned from Wine thread, cannot be interlocked with Wine/Win32 Mutex or CriticalSection. They also seem to be scheduled (by kernel) only within parent Wine thread. If parent Wine thread terminates early - we have a crash the moment when one of the orphan pthreads try to place a callback.
If you're talking about mixing pthreads and wine threads still, yeah, all bets are off. If you're talking about pure win32 stuff, please give more details.
Can you help with these? If not, can you suggest who may be able to give us some expert insight with our issues?
I hope some of the other developers on wine-devel@winehq.org can fill in here.
Don't forget - there's always the option of calling in the professionals. There are contractors who can help you if you are able to afford the fee. - Dan
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
On Thu, 27 Oct 2005 22:19, Marcus Meissner wrote:
dlopen() is possible from within a WINE context.
I don't believe this is true. LoadLibrary does a bunch of stuff dlopen won't - resolving imports, such as loading dependent DLLs and calling DLLEntry. While you can call dlopen, you must also call LoadLibrary either before or immediately after to make sure all this stuff is sorted out.
Le jeu 27/10/2005 à 20:02, Troy Rollo a écrit :
On Thu, 27 Oct 2005 22:19, Marcus Meissner wrote:
dlopen() is possible from within a WINE context.
I don't believe this is true. LoadLibrary does a bunch of stuff dlopen won't - resolving imports, such as loading dependent DLLs and calling DLLEntry. While you can call dlopen, you must also call LoadLibrary either before or immediately after to make sure all this stuff is sorted out.
Don't use dlopen() for Wine's dlls (or Windows native ones), use it for Linux native .so.
Vincent