From patchwork Fri Nov 3 23:43:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 161481 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:8f47:0:b0:403:3b70:6f57 with SMTP id j7csp1373434vqu; Fri, 3 Nov 2023 16:45:24 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHQTd5PoByrWFDm+ynBexUk29cm2VDux4+gE3fp4snuRNYXDkHZ78nXLxlkoy/pRHQ/5vqv X-Received: by 2002:a05:6214:5009:b0:670:5242:a6a1 with SMTP id jo9-20020a056214500900b006705242a6a1mr7608604qvb.31.1699055123976; Fri, 03 Nov 2023 16:45:23 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1699055123; cv=pass; d=google.com; s=arc-20160816; b=cCmvvkHixOxyZzPw/D0Eq5+gj1nE6XAwi3H4iNgGhEYby32laar6i4B1DoHk3gvb9l j3OiYyPUxdAM/BTByYPm+WGjxpQP8JHpkYmz9m7lZ8FJrWRcc4FEiB1PVUfTorXJToqC cN22rlAGGEfO9HtMIqEl2QkHfB3xF1gxnrh3s3Z7uBjeGs1LOaKOF6ZH6b/4gboc27s9 DwDFyrz6ZfySZ0SI8lH2DDXFUrbEea3+cFW5edoWld3D88ecOL8+weL9kzCcgh9vPFGr W0q3QvwuyIsDbxiMWUTGwWnbHsxGib1gyjmOSWp06hvAG+oKGaNKxTZhLN/jTjwDx7x1 aPhg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=GOxbjZmt6DXor+3LVEDiFbos9Wb5vCBeZAr//Y2M+R8=; fh=PTZv/fEnntkVjZjJeDKIkUWVkECXkQyaIllNGCyO/VM=; b=kUN2z3RkW2rfLY+Op5EZJBg3Ci/eqYXXyyHI5HsF9RdcCNuwR+4Pdo8+Qys3Zt41dG O8Htf2XeKkdxZY7xu/vHPCoU58fsJP4SnUtUc3y0dwox7ZjzPjeVjfHUr7JoCCZuAk+h AERegSbOesLYlBZcAkUpdIqv3dMwGDx4oDI9qW22XfiQfHb8nMAZCM1drjPGi9Owy9Eq dSO65qvH4sNOhldURUrS1WvvjPQ9op97OzW9z2a5bSl5kZP9+D6CYrBH1suLdOUMoBHt 6WXKblx5fB6XNP8fD8+1pQhMSHoG2bmUwwO+AVrj+g8oFVfvg3d9i1QzXgp5Kw9A7GYY DFAA== ARC-Authentication-Results: i=2; mx.google.com; dkim=fail header.i=@tromey.com header.s=default header.b=ZaX0mVH7; arc=pass (i=1); spf=pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="binutils-bounces+ouuuleilei=gmail.com@sourceware.org" Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id u5-20020a05620a0c4500b007757f6ff384si2384023qki.610.2023.11.03.16.45.23 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Nov 2023 16:45:23 -0700 (PDT) Received-SPF: pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=fail header.i=@tromey.com header.s=default header.b=ZaX0mVH7; arc=pass (i=1); spf=pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="binutils-bounces+ouuuleilei=gmail.com@sourceware.org" Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B3E013858401 for ; Fri, 3 Nov 2023 23:45:23 +0000 (GMT) X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from omta36.uswest2.a.cloudfilter.net (omta36.uswest2.a.cloudfilter.net [35.89.44.35]) by sourceware.org (Postfix) with ESMTPS id C1D963858CD1 for ; Fri, 3 Nov 2023 23:44:40 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C1D963858CD1 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=tromey.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tromey.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org C1D963858CD1 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=35.89.44.35 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699055083; cv=none; b=tAJeG23RLJPieFx5pk+Wd8EtvfVJcI5rdydeyfK5nD6zQVQtTMUKpqT8lwZrC+fUq0g1b9u0x8F+oC/aGr9mZ4XtJYpqK87pJLsSRRXxf/95NqrgPTza2/fHASgc8t+D2muBGIWzqMmlooXaw7oxEMNuqq8wtfryzsEfDkbhD14= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699055083; c=relaxed/simple; bh=NgHoHG6uF+g8XtKvGt88pi9T7WPy166kba2uMFeBumQ=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=PTZkQ32F+yoKKLOjoO0qr9XT30GTf6QL1jrPP0yinknqKsnhOTe/7oRkuDKbYp35oKgnbj8fzpFUVeTZBKe5JwgXGbG3hVxgrgEtw5Imu5Mb08UD/C3axuNFchI4KvbfToAL83aTYjzwvyYlDfYgcFrQs5Ij8N7QzjARfCR21aM= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from eig-obgw-5008a.ext.cloudfilter.net ([10.0.29.246]) by cmsmtp with ESMTPS id yzrrqOkr7hqFdz3qBqLa9P; Fri, 03 Nov 2023 23:44:40 +0000 Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with ESMTPS id z3qAqHmYjpPpmz3qBqkHEf; Fri, 03 Nov 2023 23:44:39 +0000 X-Authority-Analysis: v=2.4 cv=MJVzJeVl c=1 sm=1 tr=0 ts=654585e7 a=ApxJNpeYhEAb1aAlGBBbmA==:117 a=ApxJNpeYhEAb1aAlGBBbmA==:17 a=OWjo9vPv0XrRhIrVQ50Ab3nP57M=:19 a=dLZJa+xiwSxG16/P+YVxDGlgEgI=:19 a=BNY50KLci1gA:10 a=Qbun_eYptAEA:10 a=sX9FPDgsynvPuWcd8a0A:9 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tromey.com; s=default; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=GOxbjZmt6DXor+3LVEDiFbos9Wb5vCBeZAr//Y2M+R8=; b=ZaX0mVH7k7v/rQ6tSXX9lq4IxQ pPd8YKLdxAcmxSzj6Mex2WMzbIdI/+BnZ5wxDPuZlqoGLyZyFgSkxyxLfjj/pxIQOU1dTiUvk+vjp egJS820TNdosrorqnPDyj+wOT; Received: from [161.98.8.3] (port=34612 helo=prentzel.ci.boulder.co.us) by box5379.bluehost.com with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96.2) (envelope-from ) id 1qz3qA-003zS0-20; Fri, 03 Nov 2023 17:44:38 -0600 From: Tom Tromey To: binutils@sourceware.org Cc: Tom Tromey Subject: [PATCH v2 3/3] Add minimal thread-safety to BFD Date: Fri, 3 Nov 2023 17:43:27 -0600 Message-ID: <20231103234355.2012158-4-tom@tromey.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20231103234355.2012158-1-tom@tromey.com> References: <20231103234355.2012158-1-tom@tromey.com> MIME-Version: 1.0 X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - box5379.bluehost.com X-AntiAbuse: Original Domain - sourceware.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - tromey.com X-BWhitelist: no X-Source-IP: 161.98.8.3 X-Source-L: No X-Exim-ID: 1qz3qA-003zS0-20 X-Source: X-Source-Args: X-Source-Dir: X-Source-Sender: (prentzel.ci.boulder.co.us) [161.98.8.3]:34612 X-Source-Auth: tom+tromey.com X-Email-Count: 6 X-Org: HG=bhshared;ORG=bluehost; X-Source-Cap: ZWx5bnJvYmk7ZWx5bnJvYmk7Ym94NTM3OS5ibHVlaG9zdC5jb20= X-Local-Domain: yes X-CMAE-Envelope: MS4xfOsAunSjUGkj+f2XIfnIwWFLOEfSdWH3v83qL85AGerwVsxcsICpqK/KVZmr3taMaPbD5JYk25cTWM92BDqwnbiuJYlNXUnQY/Hg4p7ZeTx/+xmTkURM Lq9MSRNjK/KzoD4xCKesYXbOOYEhu2sIHqV2WrItaBDJ2d+VL1jIw/zgUxRErLwBTUUpSZbqiZnq6Xl+QAOnlTY1NA7FAvsNXx4= X-Spam-Status: No, score=-3024.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, JMQ_SPF_NEUTRAL, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces+ouuuleilei=gmail.com@sourceware.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1781588425266729222 X-GMAIL-MSGID: 1781588425266729222 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. --- bfd/bfd-in2.h | 8 ++ bfd/bfd.c | 131 +++++++++++++++++++++++++++++++- bfd/cache.c | 193 +++++++++++++++++++++++++++++++++++------------ bfd/doc/bfd.texi | 1 + bfd/libbfd.h | 4 + bfd/opncls.c | 7 ++ bfd/po/bfd.pot | 10 +-- 7 files changed, 299 insertions(+), 55 deletions(-) diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index e26bc40a9e1..278ba7af851 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -2572,6 +2572,14 @@ unsigned int bfd_init (void); /* Value returned by bfd_init. */ #define BFD_INIT_MAGIC (sizeof (struct bfd_section)) +typedef bool (*bfd_lock_unlock_fn_type) (void *); +bool bfd_thread_init + (bfd_lock_unlock_fn_type lock, + bfd_lock_unlock_fn_type unlock, + void *data); + +void bfd_thread_cleanup (void); + long bfd_get_reloc_upper_bound (bfd *abfd, asection *sect); long bfd_canonicalize_reloc diff --git a/bfd/bfd.c b/bfd/bfd.c index 2cf8361caa2..99189e0b5ac 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -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 diff --git a/bfd/cache.c b/bfd/cache.c index 3d26bee0773..a392bd28e18 100644 --- a/bfd/cache.c +++ b/bfd/cache.c @@ -49,6 +49,8 @@ SUBSECTION #include #endif +static FILE *_bfd_open_file_unlocked (bfd *abfd); + /* In some cases we can optimize cache operation when reopening files. For instance, a flush is entirely unnecessary if the file is already closed, so a flush would use CACHE_NO_OPEN. Similarly, a seek using @@ -259,7 +261,7 @@ bfd_cache_lookup_worker (bfd *abfd, enum cache_flag flag) if (flag & CACHE_NO_OPEN) return NULL; - if (bfd_open_file (abfd) == NULL) + if (_bfd_open_file_unlocked (abfd) == NULL) ; else if (!(flag & CACHE_NO_SEEK) && _bfd_real_fseek ((FILE *) abfd->iostream, @@ -278,19 +280,36 @@ bfd_cache_lookup_worker (bfd *abfd, enum cache_flag flag) static file_ptr cache_btell (struct bfd *abfd) { + if (!bfd_lock ()) + return -1; FILE *f = bfd_cache_lookup (abfd, CACHE_NO_OPEN); if (f == NULL) - return abfd->where; - return _bfd_real_ftell (f); + { + if (!bfd_unlock ()) + return -1; + return abfd->where; + } + file_ptr result = _bfd_real_ftell (f); + if (!bfd_unlock ()) + return -1; + return result; } static int cache_bseek (struct bfd *abfd, file_ptr offset, int whence) { + if (!bfd_lock ()) + return -1; FILE *f = bfd_cache_lookup (abfd, whence != SEEK_CUR ? CACHE_NO_SEEK : CACHE_NORMAL); if (f == NULL) + { + bfd_unlock (); + return -1; + } + int result = _bfd_real_fseek (f, offset, whence); + if (!bfd_unlock ()) return -1; - return _bfd_real_fseek (f, offset, whence); + return result; } /* Note that archive entries don't have streams; they share their parent's. @@ -338,12 +357,17 @@ cache_bread_1 (FILE *f, void *buf, file_ptr nbytes) static file_ptr cache_bread (struct bfd *abfd, void *buf, file_ptr nbytes) { + if (!bfd_lock ()) + return -1; file_ptr nread = 0; FILE *f; f = bfd_cache_lookup (abfd, CACHE_NORMAL); if (f == NULL) - return -1; + { + bfd_unlock (); + return -1; + } /* Some filesystems are unable to handle reads that are too large (for instance, NetApp shares with oplocks turned off). To avoid @@ -374,57 +398,84 @@ cache_bread (struct bfd *abfd, void *buf, file_ptr nbytes) break; } + if (!bfd_unlock ()) + return -1; return nread; } static file_ptr cache_bwrite (struct bfd *abfd, const void *from, file_ptr nbytes) { + if (!bfd_lock ()) + return -1; file_ptr nwrite; FILE *f = bfd_cache_lookup (abfd, CACHE_NORMAL); if (f == NULL) - return 0; + { + if (!bfd_unlock ()) + return -1; + return 0; + } nwrite = fwrite (from, 1, nbytes, f); if (nwrite < nbytes && ferror (f)) { bfd_set_error (bfd_error_system_call); + bfd_unlock (); return -1; } + if (!bfd_unlock ()) + return -1; return nwrite; } static int cache_bclose (struct bfd *abfd) { + /* No locking needed here, it's handled by the callee. */ return bfd_cache_close (abfd) - 1; } static int cache_bflush (struct bfd *abfd) { + if (!bfd_lock ()) + return -1; int sts; FILE *f = bfd_cache_lookup (abfd, CACHE_NO_OPEN); if (f == NULL) - return 0; + { + if (!bfd_unlock ()) + return -1; + return 0; + } sts = fflush (f); if (sts < 0) bfd_set_error (bfd_error_system_call); + if (!bfd_unlock ()) + return -1; return sts; } static int cache_bstat (struct bfd *abfd, struct stat *sb) { + if (!bfd_lock ()) + return -1; int sts; FILE *f = bfd_cache_lookup (abfd, CACHE_NO_SEEK_ERROR); if (f == NULL) - return -1; + { + bfd_unlock (); + return -1; + } sts = fstat (fileno (f), sb); if (sts < 0) bfd_set_error (bfd_error_system_call); + if (!bfd_unlock ()) + return -1; return sts; } @@ -440,6 +491,8 @@ cache_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED, { void *ret = (void *) -1; + if (!bfd_lock ()) + return ret; if ((abfd->flags & BFD_IN_MEMORY) != 0) abort (); #ifdef HAVE_MMAP @@ -452,7 +505,10 @@ cache_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED, f = bfd_cache_lookup (abfd, CACHE_NO_SEEK_ERROR); if (f == NULL) - return ret; + { + bfd_unlock (); + return ret; + } if (pagesize_m1 == 0) pagesize_m1 = getpagesize () - 1; @@ -473,6 +529,8 @@ cache_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED, } #endif + if (!bfd_unlock ()) + return (void *) -1; return ret; } @@ -482,6 +540,22 @@ static const struct bfd_iovec cache_iovec = &cache_bclose, &cache_bflush, &cache_bstat, &cache_bmmap }; +static bool +_bfd_cache_init_unlocked (bfd *abfd) +{ + BFD_ASSERT (abfd->iostream != NULL); + if (open_files >= bfd_cache_max_open ()) + { + if (! close_one ()) + return false; + } + abfd->iovec = &cache_iovec; + insert (abfd); + abfd->flags &= ~BFD_CLOSED_BY_CACHE; + ++open_files; + return true; +} + /* INTERNAL_FUNCTION bfd_cache_init @@ -496,17 +570,28 @@ DESCRIPTION bool bfd_cache_init (bfd *abfd) { - BFD_ASSERT (abfd->iostream != NULL); - if (open_files >= bfd_cache_max_open ()) - { - if (! close_one ()) - return false; - } - abfd->iovec = &cache_iovec; - insert (abfd); - abfd->flags &= ~BFD_CLOSED_BY_CACHE; - ++open_files; - return true; + if (!bfd_lock ()) + return false; + bool result = _bfd_cache_init_unlocked (abfd); + if (!bfd_unlock ()) + return false; + return result; +} + +static bool +_bfd_cache_close_unlocked (bfd *abfd) +{ + /* Don't remove this test. bfd_reinit depends on it. */ + if (abfd->iovec != &cache_iovec) + return true; + + if (abfd->iostream == NULL) + /* Previously closed. */ + return true; + + /* Note: no locking needed in this function, as it is handled by + bfd_cache_delete. */ + return bfd_cache_delete (abfd); } /* @@ -527,15 +612,12 @@ DESCRIPTION bool bfd_cache_close (bfd *abfd) { - /* Don't remove this test. bfd_reinit depends on it. */ - if (abfd->iovec != &cache_iovec) - return true; - - if (abfd->iostream == NULL) - /* Previously closed. */ - return true; - - return bfd_cache_delete (abfd); + if (!bfd_lock ()) + return false; + bool result = _bfd_cache_close_unlocked (abfd); + if (!bfd_unlock ()) + return false; + return result; } /* @@ -560,11 +642,13 @@ bfd_cache_close_all (void) { bool ret = true; + if (!bfd_lock ()) + return false; while (bfd_last_cache != NULL) { bfd *prev_bfd_last_cache = bfd_last_cache; - ret &= bfd_cache_close (bfd_last_cache); + ret &= _bfd_cache_close_unlocked (bfd_last_cache); /* Stop a potential infinite loop should bfd_cache_close() not update bfd_last_cache. */ @@ -572,6 +656,8 @@ bfd_cache_close_all (void) break; } + if (!bfd_unlock ()) + return false; return ret; } @@ -592,23 +678,8 @@ bfd_cache_size (void) return open_files; } -/* -INTERNAL_FUNCTION - bfd_open_file - -SYNOPSIS - FILE* bfd_open_file (bfd *abfd); - -DESCRIPTION - Call the OS to open a file for @var{abfd}. Return the <> - (possibly <>) that results from this operation. Set up the - BFD so that future accesses know the file is open. If the <> - returned is <>, then it won't have been put in the - cache, so it won't have to be removed from it. -*/ - -FILE * -bfd_open_file (bfd *abfd) +static FILE * +_bfd_open_file_unlocked (bfd *abfd) { abfd->cacheable = true; /* Allow it to be closed later. */ @@ -673,9 +744,35 @@ bfd_open_file (bfd *abfd) bfd_set_error (bfd_error_system_call); else { - if (! bfd_cache_init (abfd)) + if (! _bfd_cache_init_unlocked (abfd)) return NULL; } return (FILE *) abfd->iostream; } + +/* +INTERNAL_FUNCTION + bfd_open_file + +SYNOPSIS + FILE* bfd_open_file (bfd *abfd); + +DESCRIPTION + Call the OS to open a file for @var{abfd}. Return the <> + (possibly <>) that results from this operation. Set up the + BFD so that future accesses know the file is open. If the <> + returned is <>, then it won't have been put in the + cache, so it won't have to be removed from it. +*/ + +FILE * +bfd_open_file (bfd *abfd) +{ + if (!bfd_lock ()) + return NULL; + FILE *result = _bfd_open_file_unlocked (abfd); + if (!bfd_unlock ()) + return NULL; + return result; +} diff --git a/bfd/doc/bfd.texi b/bfd/doc/bfd.texi index f348710845f..3f70cb73a1d 100644 --- a/bfd/doc/bfd.texi +++ b/bfd/doc/bfd.texi @@ -199,6 +199,7 @@ IEEE-695. * typedef bfd:: * Error reporting:: * Initialization:: +* Threading:: * Miscellaneous:: * Memory Usage:: * Sections:: diff --git a/bfd/libbfd.h b/bfd/libbfd.h index fea00b6ee45..87c6690a4d5 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -937,6 +937,10 @@ bfd_error_handler_type _bfd_set_error_handler_caching (bfd *) ATTRIBUTE_HIDDEN; const char *_bfd_get_error_program_name (void) ATTRIBUTE_HIDDEN; +bool bfd_lock (void) ATTRIBUTE_HIDDEN; + +bool bfd_unlock (void) ATTRIBUTE_HIDDEN; + /* Extracted from bfdio.c. */ struct bfd_iovec { diff --git a/bfd/opncls.c b/bfd/opncls.c index cddfd7ec1fb..5a77562744c 100644 --- a/bfd/opncls.c +++ b/bfd/opncls.c @@ -81,6 +81,8 @@ _bfd_new_bfd (void) if (nbfd == NULL) return NULL; + if (!bfd_lock ()) + return NULL; if (bfd_use_reserved_id) { nbfd->id = --bfd_reserved_id_counter; @@ -88,6 +90,11 @@ _bfd_new_bfd (void) } else nbfd->id = bfd_id_counter++; + if (!bfd_unlock ()) + { + free (nbfd); + return NULL; + } nbfd->memory = objalloc_create (); if (nbfd->memory == NULL) diff --git a/bfd/po/bfd.pot b/bfd/po/bfd.pot index 9aa34703883..cf05eabd6fe 100644 --- a/bfd/po/bfd.pot +++ b/bfd/po/bfd.pot @@ -231,22 +231,22 @@ msgstr "" msgid "#" msgstr "" -#: bfd.c:1892 +#: bfd.c:2019 #, c-format msgid "BFD %s assertion fail %s:%d" msgstr "" -#: bfd.c:1905 +#: bfd.c:2032 #, c-format msgid "BFD %s internal error, aborting at %s:%d in %s\n" msgstr "" -#: bfd.c:1910 +#: bfd.c:2037 #, c-format msgid "BFD %s internal error, aborting at %s:%d\n" msgstr "" -#: bfd.c:1912 +#: bfd.c:2039 msgid "Please report this bug.\n" msgstr "" @@ -265,7 +265,7 @@ msgstr "" msgid "warning: writing section `%pA' at huge (ie negative) file offset" msgstr "" -#: cache.c:273 +#: cache.c:275 #, c-format msgid "reopening %pB: %s" msgstr ""