1 // descriptors.cc -- manage file descriptors for gold 2 3 // Copyright 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. 4 // Written by Ian Lance Taylor <iant@google.com>. 5 6 // This file is part of gold. 7 8 // This program is free software; you can redistribute it and/or modify 9 // it under the terms of the GNU General Public License as published by 10 // the Free Software Foundation; either version 3 of the License, or 11 // (at your option) any later version. 12 13 // This program is distributed in the hope that it will be useful, 14 // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 // GNU General Public License for more details. 17 18 // You should have received a copy of the GNU General Public License 19 // along with this program; if not, write to the Free Software 20 // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 21 // MA 02110-1301, USA. 22 23 #include "gold.h" 24 25 #include <cerrno> 26 #include <cstdio> 27 #include <cstring> 28 #include <fcntl.h> 29 #include <unistd.h> 30 31 #include "parameters.h" 32 #include "options.h" 33 #include "gold-threads.h" 34 #include "descriptors.h" 35 #include "binary-io.h" 36 37 // O_CLOEXEC is only available on newer systems. 38 #ifndef O_CLOEXEC 39 #define O_CLOEXEC 0 40 #endif 41 42 // Very old systems may not define FD_CLOEXEC. 43 #ifndef FD_CLOEXEC 44 #define FD_CLOEXEC 1 45 #endif 46 47 static inline void 48 set_close_on_exec(int fd ATTRIBUTE_UNUSED) 49 { 50 // Mingw does not define F_SETFD. 51 #ifdef F_SETFD 52 fcntl(fd, F_SETFD, FD_CLOEXEC); 53 #endif 54 } 55 56 namespace gold 57 { 58 59 // Class Descriptors. 60 61 // The default for limit_ is meant to simply be large. It gets 62 // adjusted downward if we run out of file descriptors. 63 64 Descriptors::Descriptors() 65 : lock_(NULL), initialize_lock_(&this->lock_), open_descriptors_(), 66 stack_top_(-1), current_(0), limit_(8192 - 16) 67 { 68 this->open_descriptors_.reserve(128); 69 } 70 71 // Open a file. 72 73 int 74 Descriptors::open(int descriptor, const char* name, int flags, int mode) 75 { 76 // We don't initialize this until we are called, because we can't 77 // initialize a Lock until we have parsed the options to find out 78 // whether we are running with threads. We can be called before 79 // options are valid when reading a linker script. 80 bool lock_initialized = this->initialize_lock_.initialize(); 81 82 gold_assert(lock_initialized || descriptor < 0); 83 84 if (descriptor >= 0) 85 { 86 Hold_lock hl(*this->lock_); 87 88 gold_assert(static_cast<size_t>(descriptor) 89 < this->open_descriptors_.size()); 90 Open_descriptor* pod = &this->open_descriptors_[descriptor]; 91 if (pod->name == name 92 || (pod->name != NULL && strcmp(pod->name, name) == 0)) 93 { 94 gold_assert(!pod->inuse); 95 pod->inuse = true; 96 if (descriptor == this->stack_top_) 97 { 98 this->stack_top_ = pod->stack_next; 99 pod->stack_next = -1; 100 pod->is_on_stack = false; 101 } 102 return descriptor; 103 } 104 } 105 106 while (true) 107 { 108 // We always want to set the close-on-exec flag; we don't 109 // require callers to pass it. 110 flags |= O_CLOEXEC; 111 112 // Always open the file as a binary file. 113 flags |= O_BINARY; 114 115 int new_descriptor = ::open(name, flags, mode); 116 if (new_descriptor < 0 117 && errno != ENFILE 118 && errno != EMFILE) 119 { 120 if (descriptor >= 0 && errno == ENOENT) 121 { 122 { 123 Hold_lock hl(*this->lock_); 124 125 gold_error(_("file %s was removed during the link"), name); 126 } 127 128 errno = ENOENT; 129 } 130 131 return new_descriptor; 132 } 133 134 if (new_descriptor >= 0) 135 { 136 // If we have any plugins, we really do need to set the 137 // close-on-exec flag, even if O_CLOEXEC is not defined. 138 // FIXME: In some cases O_CLOEXEC may be defined in the 139 // header file but not supported by the kernel. 140 // Unfortunately there doesn't seem to be any obvious way to 141 // detect that, as unknown flags passed to open are ignored. 142 if (O_CLOEXEC == 0 143 && parameters->options_valid() 144 && parameters->options().has_plugins()) 145 set_close_on_exec(new_descriptor); 146 147 { 148 Hold_optional_lock hl(this->lock_); 149 150 if (static_cast<size_t>(new_descriptor) 151 >= this->open_descriptors_.size()) 152 this->open_descriptors_.resize(new_descriptor + 64); 153 154 Open_descriptor* pod = &this->open_descriptors_[new_descriptor]; 155 pod->name = name; 156 pod->stack_next = -1; 157 pod->inuse = true; 158 pod->is_write = (flags & O_ACCMODE) != O_RDONLY; 159 pod->is_on_stack = false; 160 161 ++this->current_; 162 if (this->current_ >= this->limit_) 163 this->close_some_descriptor(); 164 165 return new_descriptor; 166 } 167 } 168 169 // We ran out of file descriptors. 170 { 171 Hold_optional_lock hl(this->lock_); 172 173 this->limit_ = this->current_ - 16; 174 if (this->limit_ < 8) 175 this->limit_ = 8; 176 if (!this->close_some_descriptor()) 177 gold_fatal(_("out of file descriptors and couldn't close any")); 178 } 179 } 180 } 181 182 // Release a descriptor. 183 184 void 185 Descriptors::release(int descriptor, bool permanent) 186 { 187 Hold_optional_lock hl(this->lock_); 188 189 gold_assert(descriptor >= 0 190 && (static_cast<size_t>(descriptor) 191 < this->open_descriptors_.size())); 192 Open_descriptor* pod = &this->open_descriptors_[descriptor]; 193 194 if (permanent 195 || (this->current_ > this->limit_ && !pod->is_write)) 196 { 197 if (::close(descriptor) < 0) 198 gold_warning(_("while closing %s: %s"), pod->name, strerror(errno)); 199 pod->name = NULL; 200 --this->current_; 201 } 202 else 203 { 204 pod->inuse = false; 205 if (!pod->is_write && !pod->is_on_stack) 206 { 207 pod->stack_next = this->stack_top_; 208 this->stack_top_ = descriptor; 209 pod->is_on_stack = true; 210 } 211 } 212 } 213 214 // Close some descriptor. The lock is held when this is called. We 215 // close the descriptor on the top of the free stack. Note that this 216 // is the opposite of an LRU algorithm--we close the most recently 217 // used descriptor. That is because the linker tends to cycle through 218 // all the files; after we release a file, we are unlikely to need it 219 // again until we have looked at all the other files. Return true if 220 // we closed a descriptor. 221 222 bool 223 Descriptors::close_some_descriptor() 224 { 225 int last = -1; 226 int i = this->stack_top_; 227 while (i >= 0) 228 { 229 gold_assert(static_cast<size_t>(i) < this->open_descriptors_.size()); 230 Open_descriptor* pod = &this->open_descriptors_[i]; 231 if (!pod->inuse && !pod->is_write) 232 { 233 if (::close(i) < 0) 234 gold_warning(_("while closing %s: %s"), pod->name, strerror(errno)); 235 --this->current_; 236 pod->name = NULL; 237 if (last < 0) 238 this->stack_top_ = pod->stack_next; 239 else 240 this->open_descriptors_[last].stack_next = pod->stack_next; 241 pod->stack_next = -1; 242 pod->is_on_stack = false; 243 return true; 244 } 245 last = i; 246 i = pod->stack_next; 247 } 248 249 // We couldn't find any descriptors to close. This is weird but not 250 // necessarily an error. 251 return false; 252 } 253 254 // The single global variable which manages descriptors. 255 256 Descriptors descriptors; 257 258 } // End namespace gold. 259