[PATCH 3/3] Add minimal thread-safety to BFD
Nick Clifton
nickc@redhat.com
Wed Nov 1 12:45:41 GMT 2023
Hi Tom,
> This patch provides some minimal thread-safety to BFD.
>
> The BFD client can request thread-safety by providing a lock and
> unlock function. The globals used during BFD creation (e.g.,
> bfd_id_counter) are then locked, and the file descriptor cache is also
> locked. A function to clean up any thread-local data is now provided
> for BFD clients.
>
> * bfd-in2.h: Regenerate.
> * bfd.c (lock_fn, unlock_fn): New globals.
> (bfd_thread_init, bfd_thread_cleanup, bfd_lock, bfd_unlock): New
> functions.
> * cache.c (bfd_cache_lookup_worker): Use _bfd_open_file_unlocked.
> (cache_btell, cache_bseek, cache_bread, cache_bwrite): Lock
> and unlock.
> (cache_bclose): Add comment.
> (cache_bflush, cache_bstat, cache_bmmap): Lock and unlock.
> (_bfd_cache_init_unlocked): New function.
> (bfd_cache_init): Use it. Lock and unlock.
> (_bfd_cache_close_unlocked): New function.
> (bfd_cache_close, bfd_cache_close_all): Use it. Lock and unlock.
> (_bfd_open_file_unlocked): New function.
> (bfd_open_file): Use it. Lock and unlock.
> * doc/bfd.texi (BFD front end): Add Threading menu item.
> * libbfd.h: Regenerate.
> * opncls.c (_bfd_new_bfd): Lock and unlock.
> * po/bfd.pot: Regenerate.
I have one concern about this patch:
> +typedef void (*bfd_lock_unlock_fn_type) (void);
Given that we are dealing with client provided locking and unlocking
functions, I feel that the client might want to be able to reference
a data structure of their own performing these actions. (I am not
hugely familiar with locking and unlocking functions, so maybe I am
mistaken here). I also wonder if the functions might be interested
in the BFD being locked. Thus I think that the typedef might be
better specified as:
typedef void (* bfd_lock_unlock_fn_type) (bfd *, void *);
I also wonder if the functions should be allowed to fail, in which
case the typedef would be:
typedef bool (* bfd_lock_unlock_fn_type) (bfd *, void *);
Given all of that the init function would have to be extended to take
a data pointer:
> +void
> +bfd_thread_init (bfd_lock_unlock_fn_type lock,
bfd_lock_unlock_fn_type unlock,
void * data)
> +{
> + lock_fn = lock;
> + unlock_fn = unlock;
lock_data = data;
> +}
Also - should this function let the caller know if a previous set
of lock/unlock functions had been registered, or if there was a problem
registering them ? (For example is it OK to have a lock function but
not an unlock function ?) ie:
bool
bfd_thread_init (bfd_lock_unlock_fn_type lock,
bfd_lock_unlock_fn_type unlock,
void * data)
{
bool ret = lock_fn == NULL && unlock_fn == NULL;
lock_fn = lock;
unlock_fn = unlock;
lock_data = data;
ret &= (lock_fn != NULL && unlock_fn != NULL) || (lock_fn == NULL && unlock_fn == NULL);
return ret;
}
And of course the bfd_lock and bfd_unlock would need to be updated as well, eg:
> +bool
> +bfd_lock (bfd * abfd)
> +{
> + if (lock_fn != NULL)
> + return lock_fn (abfd, lock_data);
return true;
> +}
What do you think ?
Cheers
Nick
More information about the Binutils
mailing list