Multithreading ============== Libnfs supports multithreading using the pthread API on linux/unix and using the native API for Windows. By default libnfs is beuilt without pthread support to avoid the overhead for locking, but pthread support, and thus support for multithreading, can be configured using --enable-pthread $ ./configure --prefix=/usr --enable-examples --enable-pthread It is not supported to mix the eventdriven ASYNC interface with multithreading thus once multithreading is enabled from the application you can not use the async interface any more and must only use the multithread safe SYNC API. The process to use multithreading from your application is: 1, nfs_init_context() to create an NFS context. This context defaults to not (yet) be multithreading aware. 2, nfs_mount(...) to mount the NFS share. IF the share mounted successfully we can now turn on multithreading for all I/O to the share: 3, nfs_mt_service_thread_start(nfs) this starts a dedicated thread to manage all socket I/O and queue management and also flags the context to be multithreading ready. If this returns successfully you can now start using this context from separate threads in your application. But remember, only the SYNC API is supported from this point. ... use the nfs context from all your threads ... Once the application is finished and ready to terminate, first close all other threads, or make sure that they will NOT perform any further I/O to the nfs context. Wait until all in-flight I/O has stopped. Then call nfs_mt_service_thread_stop(nfs) to terminate the service thread and disable the multithreading support. See examples/nfs-pthreads-example.c for an example utility that mounts a share, enables multithreading and then creates a number of worker threads that share the same nfs context. (In the example the threads just runs a busy loop calling nfs_stat64().) Porting ------- The multithreading support is abstracted out into two separate files to make it easier to add other threading APIs instead of pthreads. include/libnfs-multithreading.h and lib/multithreading.c Multithreading requires two separate defines to be present. The global one is HAVE_MULTITHREADING which will activate general multithreading support in the library and the second one that enables a specific implementation of threading. HAVE_PTHREAD is defined when you want to use libpthread. For other threading APIs you will need a new define HAVE_OTHER_API to select it. include/libnfs-multithreading.h ------------------------------- This file consists of two parts. The first part is creating typedefs for a tread, a mutex and a semaphore. When porting to a different threads API, add a new section that adds suitable typedefs for thread/mutex/semaphore. The second part is the wrapper API for the libnfs threading abstractions and should not need to be changed. lib/multithreading.c -------------------- This file contains the actual abstraction used for multithreading. When porting to a different threads API you will need to create replacement functions for : nfs_mt_service_thread() : This is the service thread that is responsible for performing all socket I/O. nfs_mt_service_thread_start() nfs_mt_service_thread_stop() : Functions to start/stop the service thread. nfs_mt_mutex_init() nfs_mt_mutex_destroy() nfs_mt_mutex_lock() nfs_mt_mutex_unlock() : Wrappers that implement the 4 basic mutex calls. nfs_mt_sem_init() nfs_mt_sem_destroy() nfs_mt_sem_post() nfs_mt_sem_wait() : Wrappers that implement the 4 basic semaphore calls. nfs_mt_get_tid() : Get an identifier for the current thread. TODO ---- * Optimization: have the service thread just read the PDU from the socket and add it to a new queue. Then have a pool of threads to read from this queue and unmarshall the pdu's in concurrently.