Wine runs in one of two modes: either pthreads (posix threading) or kthreads (kernel threading). This section explains the differences between them. The one that is used is automatically selected on startup by a small test program which then execs the correct binary, either wine-kthread or wine-pthread. On NPTL-enabled systems pthreads will be used, and on older non-NPTL systems kthreads is selected.
Let's start with a bit of history. Back in the dark ages when Wines threading support was first implemented a problem was faced - Windows had much more capable threading APIs than Linux did. This presented a problem - Wine works either by reimplementing an API entirely or by mapping it onto the underlying systems equivalent. How could Win32 threading be implemented using a library which did not have all the neeed features? The answer, of course, was that it couldn't be.
On Linux the pthreads interface is used to start, stop and control threads. The pthreads library in turn is based on top of so-called "kernel threads" which are created using the clone(2) syscall. Pthreads provides a nicer (more portable) interface to this functionality and also provides APIs for controlling mutexes. There is a good tutorial on pthreads available if you want to learn more.
As pthreads did not provide the necessary semantics to implement Win32 threading, the decision was made to implement Win32 threading on top of the underlying kernel threads by using syscalls like clone directly. This provided maximum flexibility and allowed a correct implementation but caused some bad side effects. Most notably, all the userland Linux APIs assumed that the user was utilising the pthreads library. Some only enabled thread safety when they detected that pthreads was in use - this is true of glibc, for instance. Worse, pthreads and pure kernel threads had strange interactions when run in the same process yet some libraries used by Wine used pthreads internally. Throw in source code porting using WineLib - where you have both UNIX and Win32 code in the same process - and chaos was the result.
The solution was simple yet ingenius: Wine would provide its own implementation of the pthread library inside its own binary. Due to the semantics of ELF symbol scoping, this would cause Wines own implementations to override any implementation loaded later on (like the real libpthread.so). Therefore, any calls to the pthread APIs in external libraries would be linked to Wines instead of the systems pthreads library, and Wine implemented pthreads by using the standard Windows threading APIs it in turn implemented itself.
As a result, libraries that only became thread-safe in the presence of a loaded pthreads implementation would now do so, and any external code that used pthreads would actually end up creating Win32 threads that Wine was aware of and controlled. This worked quite nicely for a long time, even though it required doing some extremely un-kosher things like overriding internal libc structures and functions. That is, it worked until NPTL was developed at which point the underlying thread implementation on Linux changed dramatically.
The fake pthread implementation can be found in loader/kthread.c, which is used to produce to wine-kthread binary. In contrast, loader/pthread.c produces the wine-pthread binary which is used on newer NPTL systems.
NPTL is a new threading subsystem for Linux that hugely improves its performance and flexibility. By allowing threads to become much more scalable and adding new pthread APIs, NPTL made Linux competitive with Windows in the multi-threaded world. Unfortunately it also broke many assumptions made by Wine (as well as other applications such as the Sun JVM and RealPlayer) in the process.
There was, however, some good news. NPTL made Linux threading powerful enough that Win32 threads could now be implemented on top of pthreads like any other normal application. There would no longer be problems with mixing win32-kthreads and pthreads created by external libraries, and no need to override glibc internals. As you can see from the relative sizes of the loader/kthread.c and loader/pthread.c files, the difference in code complexity is considerable. NPTL also made several other semantic changes to things such as signal delivery so changes were required in many different places in Wine.
On non-Linux systems the threading interface is typically not powerful enough to replicate the semantics Win32 applications expect and so kthreads with the pthread overrides are used.