diff options
author | Tom Tromey <tom@tromey.com> | 2023-09-05 19:05:40 -0600 |
---|---|---|
committer | Tom Tromey <tom@tromey.com> | 2023-11-07 17:47:16 -0700 |
commit | 1185b5b79a12ba67eb60bee3f75babf7a222fde0 (patch) | |
tree | 8bec5accb1289ea191ae245815adcbd6e7f0df8d /bfd/bfd.c | |
parent | c6d6a048f5a6f422e470c7c4bdb21a0c59d7c8fd (diff) | |
download | gdb-1185b5b79a12ba67eb60bee3f75babf7a222fde0.zip gdb-1185b5b79a12ba67eb60bee3f75babf7a222fde0.tar.gz gdb-1185b5b79a12ba67eb60bee3f75babf7a222fde0.tar.bz2 |
Add minimal thread-safety to BFD
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.
Diffstat (limited to 'bfd/bfd.c')
-rw-r--r-- | bfd/bfd.c | 131 |
1 files changed, 129 insertions, 2 deletions
@@ -1716,7 +1716,7 @@ bfd_set_assert_handler (bfd_assert_handler_type pnew) /* INODE -Initialization, Miscellaneous, Error reporting, BFD front end +Initialization, Threading, Error reporting, BFD front end FUNCTION bfd_init @@ -1749,9 +1749,136 @@ bfd_init (void) return BFD_INIT_MAGIC; } + +/* +INODE +Threading, Miscellaneous, Initialization, BFD front end + +SECTION + Threading + + BFD has limited support for thread-safety. Most BFD globals + are protected by locks, while the error-related globals are + thread-local. A given BFD cannot safely be used from two + threads at the same time; it is up to the application to do + any needed locking. However, it is ok for different threads + to work on different BFD objects at the same time. + +SUBSECTION + Thread functions. + +CODE_FRAGMENT +.typedef bool (*bfd_lock_unlock_fn_type) (void *); +*/ + +/* The lock and unlock functions, if set. */ +static bfd_lock_unlock_fn_type lock_fn; +static bfd_lock_unlock_fn_type unlock_fn; +static void *lock_data; + +/* +FUNCTION + bfd_thread_init + +SYNOPSIS + bool bfd_thread_init + (bfd_lock_unlock_fn_type lock, + bfd_lock_unlock_fn_type unlock, + void *data); + +DESCRIPTION + + Initialize BFD threading. The functions passed in will be + used to lock and unlock global data structures. This may only + be called a single time in a given process. Returns true on + success and false on error. DATA is passed verbatim to the + lock and unlock functions. The lock and unlock functions + should return true on success, or set the BFD error and return + false on failure. +*/ + +bool +bfd_thread_init (bfd_lock_unlock_fn_type lock, bfd_lock_unlock_fn_type unlock, + void *data) +{ + /* Both functions must be set, and this cannot have been called + before. */ + if (lock == NULL || unlock == NULL || unlock_fn != NULL) + { + bfd_set_error (bfd_error_invalid_operation); + return false; + } + + lock_fn = lock; + unlock_fn = unlock; + lock_data = data; + return true; +} + +/* +FUNCTION + bfd_thread_cleanup + +SYNOPSIS + void bfd_thread_cleanup (void); + +DESCRIPTION + Clean up any thread-local state. This should be called by a + thread that uses any BFD functions, before the thread exits. + It is fine to call this multiple times, or to call it and then + later call BFD functions on the same thread again. +*/ + +void +bfd_thread_cleanup (void) +{ + _bfd_clear_error_data (); +} + +/* +INTERNAL_FUNCTION + bfd_lock + +SYNOPSIS + bool bfd_lock (void); + +DESCRIPTION + Acquire the global BFD lock, if needed. Returns true on + success, false on error. +*/ + +bool +bfd_lock (void) +{ + if (lock_fn != NULL) + return lock_fn (lock_data); + return true; +} + +/* +INTERNAL_FUNCTION + bfd_unlock + +SYNOPSIS + bool bfd_unlock (void); + +DESCRIPTION + Release the global BFD lock, if needed. Returns true on + success, false on error. +*/ + +bool +bfd_unlock (void) +{ + if (unlock_fn != NULL) + return unlock_fn (lock_data); + return true; +} + + /* INODE -Miscellaneous, Memory Usage, Initialization, BFD front end +Miscellaneous, Memory Usage, Threading, BFD front end SECTION Miscellaneous |