Threading libsmbclient - a proposal.

Jeremy Allison jra at samba.org
Thu Apr 2 23:39:35 GMT 2009


Andreas & Derrell,

Just wanted to let you know I have a working design (and some
preliminary code) for starting the process of properly
threading libsmbclient.

It's based on the ideas in openssl, but a little simpler.

The idea is a caller desiring threads will have to initialize
the thread state and locks we need by firstly calling :

unsigned int SMBC_thread_num_locks()

which will return the number of "big gloabl locks" (see
below) we currently need and creating and initializing an
array of this number of pthread_mutex_t's.

Then they must call a set of functions :

SMBC_thread_set_log_function()
SMBC_thread_set_lock_function()
SMBC_thread_set_dynamic_lock_function()
SMBC_thread_set_dynamic_lock_create_function()
SMBC_thread_set_dynamic_lock_destroy_function()

which will be passed pointers to the callback functions
libsmbclient will use internally to do the thread locking calls.

Inside libsmbclient we'll start by adding "big
global locks" (which we'll use to determine the
number returned from SMBC_thread_num_locks()) and
lock/unlock them internally by adding code
like this to the internals of libsmbclient :

	SMBC_TLOCK(GLOBAL_LOCKID);
	... access resource ....
	SMBC_TUNLOCK(GLOBAL_LOCKID);

Where SMBC_TLOCK will be a macro that expands to:
	smbc_lock_(SMB_TUNLOCK,
			GLOBAL_LOCKID,
			__FILE__,
			__LINE__);

and SMBC_TUNLOCK will expand to:
	smbc_lock(SMB_TLOCK|SMB_TLOCK_WRITE,
			GLOBAL_LOCKID,
			__FILE__,
			__LINE__);

GLOBAL_LOCKID will be a #define to the specific
"big global lock" we're currently using. For example :

#define GLOBAL_LOCKID_LIBRARY_INITIALIZED 1
#define GLOBAL_LOCKID_NAMELOOKUP_CODE 2

etc. To start with we could just use one :-).

For areas where we need dynamic locks, we
create them inside libsmbclient by :

	void *plock = smbc_create_lock(const char *lockname, const char *file, int line);

lock using the macro's :

	SMBC_TDYNLOCK(plock);
	... access resource ...
	SMBC_TDYNUNLOCK(plock);

then delete using :

	smbc_destroy_lock(void *plock, const char *file, int line)

Note all these calls will be internal to libsmbclient
and attendent libraries. I'm using TLOCK and TDYNLOCK
prefixes so people don't get them confused with actual
SMB lock calls.

The really nice part of this design (from openssl)
is that if you never set the callback functions this
has *NO EFFECT* on existing code, and because we're
hiding the pthread_mutex_t types behind an int index
(for the global locks case) and a void pointer (in
the dynamic case) there are *no dependencies* on
any underlying threads library or primitives.

For people who want pthreads we supply a module
that provides a pthread sample implementation of
all the callback functions above, but it's only
linked in by people who want threading.

I haven't started on the thread specific data part
yet (which we'll need for the talloc_frame() calls),
so I'll email more when I've thought about that some
more.

Comments / Questions ?

Big thanks to Volker who got me looking at the
openssl code in the first place !

Jeremy.


More information about the samba-technical mailing list