101 lines
3.9 KiB
Plaintext
101 lines
3.9 KiB
Plaintext
|
Multithreading
|
||
|
==============
|
||
|
Libnfs supports multithreading using the pthread API.
|
||
|
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.
|
||
|
|
||
|
|
||
|
|
||
|
TODO
|
||
|
----
|
||
|
* [rpc|nfs]_[set|get]_error() needs to be changed to use threads local storage
|
||
|
or a different API.
|
||
|
* 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.
|