Message ID | crcqxt3yayuryht5nbi6odvouuamwnrfmtlxrkaqv4czj47khl@qm22lrqve4yy |
---|---|
State | New |
Headers | show |
Series | None | expand |
On Thu, 20 Jun 2024, Michal Jires wrote: > This version differs by using INCLUDE_STRING instead of <string>. > (+whitespace and year) OK (though I'm not happy to see more std::string use) Richard. > ___ > > This patch implements lockfile used for incremental LTO. > > Bootstrapped/regtested on x86_64-pc-linux-gnu > > gcc/ChangeLog: > > * Makefile.in: Add lockfile.o. > * lockfile.cc: New file. > * lockfile.h: New file. > --- > gcc/Makefile.in | 5 +- > gcc/lockfile.cc | 136 ++++++++++++++++++++++++++++++++++++++++++++++++ > gcc/lockfile.h | 78 +++++++++++++++++++++++++++ > 3 files changed, 217 insertions(+), 2 deletions(-) > create mode 100644 gcc/lockfile.cc > create mode 100644 gcc/lockfile.h > > diff --git a/gcc/Makefile.in b/gcc/Makefile.in > index f5adb647d3f..90ec59dca75 100644 > --- a/gcc/Makefile.in > +++ b/gcc/Makefile.in > @@ -1855,7 +1855,7 @@ ALL_HOST_BACKEND_OBJS = $(GCC_OBJS) $(OBJS) $(OBJS-libcommon) \ > $(OBJS-libcommon-target) main.o c-family/cppspec.o \ > $(COLLECT2_OBJS) $(EXTRA_GCC_OBJS) $(GCOV_OBJS) $(GCOV_DUMP_OBJS) \ > $(GCOV_TOOL_OBJS) $(GENGTYPE_OBJS) gcc-ar.o gcc-nm.o gcc-ranlib.o \ > - lto-wrapper.o collect-utils.o > + lto-wrapper.o collect-utils.o lockfile.o > > # for anything that is shared use the cc1plus profile data, as that > # is likely the most exercised during the build > @@ -2384,7 +2384,8 @@ collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS) > CFLAGS-collect2.o += -DTARGET_MACHINE=\"$(target_noncanonical)\" \ > @TARGET_SYSTEM_ROOT_DEFINE@ > > -LTO_WRAPPER_OBJS = lto-wrapper.o collect-utils.o ggc-none.o > +LTO_WRAPPER_OBJS = lto-wrapper.o collect-utils.o ggc-none.o lockfile.o > + > lto-wrapper$(exeext): $(LTO_WRAPPER_OBJS) libcommon-target.a $(LIBDEPS) > +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o T$@ \ > $(LTO_WRAPPER_OBJS) libcommon-target.a $(LIBS) > diff --git a/gcc/lockfile.cc b/gcc/lockfile.cc > new file mode 100644 > index 00000000000..8ecb4dc2848 > --- /dev/null > +++ b/gcc/lockfile.cc > @@ -0,0 +1,136 @@ > +/* File locking. > + Copyright (C) 2023-2024 Free Software Foundation, Inc. > + > +This file is part of GCC. > + > +GCC is free software; you can redistribute it and/or modify it under > +the terms of the GNU General Public License as published by the Free > +Software Foundation; either version 3, or (at your option) any later > +version. > + > +GCC is distributed in the hope that it will be useful, but WITHOUT ANY > +WARRANTY; without even the implied warranty of MERCHANTABILITY or > +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License > +for more details. > + > +You should have received a copy of the GNU General Public License > +along with GCC; see the file COPYING3. If not see > +<http://www.gnu.org/licenses/>. */ > + > +#define INCLUDE_STRING > +#include "config.h" > +#include "system.h" > +#include "lockfile.h" > + > + > +/* Unique write lock. No other lock can be held on this lockfile. > + Blocking call. */ > +int > +lockfile::lock_write () > +{ > + fd = open (filename.c_str (), O_RDWR | O_CREAT, 0666); > + if (fd < 0) > + return -1; > + > +#if HAVE_FCNTL_H > + struct flock s_flock; > + > + s_flock.l_whence = SEEK_SET; > + s_flock.l_start = 0; > + s_flock.l_len = 0; > + s_flock.l_pid = getpid (); > + s_flock.l_type = F_WRLCK; > + > + while (fcntl (fd, F_SETLKW, &s_flock) && errno == EINTR) > + continue; > +#endif > + return 0; > +} > + > +/* Unique write lock. No other lock can be held on this lockfile. > + Only locks if this filelock is not locked by any other process. > + Return whether locking was successful. */ > +int > +lockfile::try_lock_write () > +{ > + fd = open (filename.c_str (), O_RDWR | O_CREAT, 0666); > + if (fd < 0) > + return -1; > + > +#if HAVE_FCNTL_H > + struct flock s_flock; > + > + s_flock.l_whence = SEEK_SET; > + s_flock.l_start = 0; > + s_flock.l_len = 0; > + s_flock.l_pid = getpid (); > + s_flock.l_type = F_WRLCK; > + > + if (fcntl (fd, F_SETLK, &s_flock) == -1) > + { > + close (fd); > + fd = -1; > + return 1; > + } > +#endif > + return 0; > +} > + > +/* Shared read lock. Only read lock can be held concurrently. > + If write lock is already held by this process, it will be > + changed to read lock. > + Blocking call. */ > +int > +lockfile::lock_read () > +{ > + fd = open (filename.c_str (), O_RDWR | O_CREAT, 0666); > + if (fd < 0) > + return -1; > + > +#if HAVE_FCNTL_H > + struct flock s_flock; > + > + s_flock.l_whence = SEEK_SET; > + s_flock.l_start = 0; > + s_flock.l_len = 0; > + s_flock.l_pid = getpid (); > + s_flock.l_type = F_RDLCK; > + > + while (fcntl (fd, F_SETLKW, &s_flock) && errno == EINTR) > + continue; > +#endif > + return 0; > +} > + > +/* Unlock all previously placed locks. */ > +void > +lockfile::unlock () > +{ > + if (fd < 0) > + { > +#if HAVE_FCNTL_H > + struct flock s_flock; > + > + s_flock.l_whence = SEEK_SET; > + s_flock.l_start = 0; > + s_flock.l_len = 0; > + s_flock.l_pid = getpid (); > + s_flock.l_type = F_UNLCK; > + > + fcntl (fd, F_SETLK, &s_flock); > +#endif > + close (fd); > + fd = -1; > + } > +} > + > +/* Are lockfiles supported? */ > +bool > +lockfile::lockfile_supported () > +{ > +#if HAVE_FCNTL_H > + return true; > +#else > + return false; > +#endif > +} > diff --git a/gcc/lockfile.h b/gcc/lockfile.h > new file mode 100644 > index 00000000000..c222eb6d3b6 > --- /dev/null > +++ b/gcc/lockfile.h > @@ -0,0 +1,78 @@ > +/* File locking. > + Copyright (C) 2023-2024 Free Software Foundation, Inc. > + > +This file is part of GCC. > + > +GCC is free software; you can redistribute it and/or modify it under > +the terms of the GNU General Public License as published by the Free > +Software Foundation; either version 3, or (at your option) any later > +version. > + > +GCC is distributed in the hope that it will be useful, but WITHOUT ANY > +WARRANTY; without even the implied warranty of MERCHANTABILITY or > +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License > +for more details. > + > +You should have received a copy of the GNU General Public License > +along with GCC; see the file COPYING3. If not see > +<http://www.gnu.org/licenses/>. */ > + > +#ifndef LOCKFILE_H > +#define LOCKFILE_H > + > +/* Used to synchronize across multiple processes. */ > +class lockfile { > +public: > + /* Default constructor. */ > + lockfile (): fd (-1) > + {} > + /* Intended constructor for use. Filename should not be used for anything > + other than locking to prevent unintentional unlock. */ > + lockfile (std::string filename): lockfile () > + { > + this->filename = std::move (filename); > + } > + lockfile (lockfile const& o): lockfile (o.filename) > + {} > + > + void operator=(lockfile o) > + { > + unlock (); > + this->filename = o.filename; > + this->fd = o.fd; > + o.fd = -1; > + } > + > + /* Unique write lock. No other lock can be held on this lockfile. > + Blocking call. */ > + int lock_write (); > + > + /* Unique write lock. No other lock can be held on this lockfile. > + Only locks if this filelock is not locked by any other process. > + Return whether locking was successful. */ > + int try_lock_write (); > + > + /* Shared read lock. Only read lock can be held concurrently. > + If write lock is already held by this process, it will be > + changed to read lock. > + Blocking call. */ > + int lock_read (); > + > + /* Unlock all previously placed locks. */ > + void unlock (); > + > + /* Returns whether any lock is held. */ > + bool > + locked () > + { > + return fd < 0; > + } > + > + /* Are lockfiles supported? */ > + static bool lockfile_supported (); > +private: > + std::string filename; > + int fd; > +}; > + > +#endif >
diff --git a/gcc/Makefile.in b/gcc/Makefile.in index f5adb647d3f..90ec59dca75 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1855,7 +1855,7 @@ ALL_HOST_BACKEND_OBJS = $(GCC_OBJS) $(OBJS) $(OBJS-libcommon) \ $(OBJS-libcommon-target) main.o c-family/cppspec.o \ $(COLLECT2_OBJS) $(EXTRA_GCC_OBJS) $(GCOV_OBJS) $(GCOV_DUMP_OBJS) \ $(GCOV_TOOL_OBJS) $(GENGTYPE_OBJS) gcc-ar.o gcc-nm.o gcc-ranlib.o \ - lto-wrapper.o collect-utils.o + lto-wrapper.o collect-utils.o lockfile.o # for anything that is shared use the cc1plus profile data, as that # is likely the most exercised during the build @@ -2384,7 +2384,8 @@ collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS) CFLAGS-collect2.o += -DTARGET_MACHINE=\"$(target_noncanonical)\" \ @TARGET_SYSTEM_ROOT_DEFINE@ -LTO_WRAPPER_OBJS = lto-wrapper.o collect-utils.o ggc-none.o +LTO_WRAPPER_OBJS = lto-wrapper.o collect-utils.o ggc-none.o lockfile.o + lto-wrapper$(exeext): $(LTO_WRAPPER_OBJS) libcommon-target.a $(LIBDEPS) +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o T$@ \ $(LTO_WRAPPER_OBJS) libcommon-target.a $(LIBS) diff --git a/gcc/lockfile.cc b/gcc/lockfile.cc new file mode 100644 index 00000000000..8ecb4dc2848 --- /dev/null +++ b/gcc/lockfile.cc @@ -0,0 +1,136 @@ +/* File locking. + Copyright (C) 2023-2024 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#define INCLUDE_STRING +#include "config.h" +#include "system.h" +#include "lockfile.h" + + +/* Unique write lock. No other lock can be held on this lockfile. + Blocking call. */ +int +lockfile::lock_write () +{ + fd = open (filename.c_str (), O_RDWR | O_CREAT, 0666); + if (fd < 0) + return -1; + +#if HAVE_FCNTL_H + struct flock s_flock; + + s_flock.l_whence = SEEK_SET; + s_flock.l_start = 0; + s_flock.l_len = 0; + s_flock.l_pid = getpid (); + s_flock.l_type = F_WRLCK; + + while (fcntl (fd, F_SETLKW, &s_flock) && errno == EINTR) + continue; +#endif + return 0; +} + +/* Unique write lock. No other lock can be held on this lockfile. + Only locks if this filelock is not locked by any other process. + Return whether locking was successful. */ +int +lockfile::try_lock_write () +{ + fd = open (filename.c_str (), O_RDWR | O_CREAT, 0666); + if (fd < 0) + return -1; + +#if HAVE_FCNTL_H + struct flock s_flock; + + s_flock.l_whence = SEEK_SET; + s_flock.l_start = 0; + s_flock.l_len = 0; + s_flock.l_pid = getpid (); + s_flock.l_type = F_WRLCK; + + if (fcntl (fd, F_SETLK, &s_flock) == -1) + { + close (fd); + fd = -1; + return 1; + } +#endif + return 0; +} + +/* Shared read lock. Only read lock can be held concurrently. + If write lock is already held by this process, it will be + changed to read lock. + Blocking call. */ +int +lockfile::lock_read () +{ + fd = open (filename.c_str (), O_RDWR | O_CREAT, 0666); + if (fd < 0) + return -1; + +#if HAVE_FCNTL_H + struct flock s_flock; + + s_flock.l_whence = SEEK_SET; + s_flock.l_start = 0; + s_flock.l_len = 0; + s_flock.l_pid = getpid (); + s_flock.l_type = F_RDLCK; + + while (fcntl (fd, F_SETLKW, &s_flock) && errno == EINTR) + continue; +#endif + return 0; +} + +/* Unlock all previously placed locks. */ +void +lockfile::unlock () +{ + if (fd < 0) + { +#if HAVE_FCNTL_H + struct flock s_flock; + + s_flock.l_whence = SEEK_SET; + s_flock.l_start = 0; + s_flock.l_len = 0; + s_flock.l_pid = getpid (); + s_flock.l_type = F_UNLCK; + + fcntl (fd, F_SETLK, &s_flock); +#endif + close (fd); + fd = -1; + } +} + +/* Are lockfiles supported? */ +bool +lockfile::lockfile_supported () +{ +#if HAVE_FCNTL_H + return true; +#else + return false; +#endif +} diff --git a/gcc/lockfile.h b/gcc/lockfile.h new file mode 100644 index 00000000000..c222eb6d3b6 --- /dev/null +++ b/gcc/lockfile.h @@ -0,0 +1,78 @@ +/* File locking. + Copyright (C) 2023-2024 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#ifndef LOCKFILE_H +#define LOCKFILE_H + +/* Used to synchronize across multiple processes. */ +class lockfile { +public: + /* Default constructor. */ + lockfile (): fd (-1) + {} + /* Intended constructor for use. Filename should not be used for anything + other than locking to prevent unintentional unlock. */ + lockfile (std::string filename): lockfile () + { + this->filename = std::move (filename); + } + lockfile (lockfile const& o): lockfile (o.filename) + {} + + void operator=(lockfile o) + { + unlock (); + this->filename = o.filename; + this->fd = o.fd; + o.fd = -1; + } + + /* Unique write lock. No other lock can be held on this lockfile. + Blocking call. */ + int lock_write (); + + /* Unique write lock. No other lock can be held on this lockfile. + Only locks if this filelock is not locked by any other process. + Return whether locking was successful. */ + int try_lock_write (); + + /* Shared read lock. Only read lock can be held concurrently. + If write lock is already held by this process, it will be + changed to read lock. + Blocking call. */ + int lock_read (); + + /* Unlock all previously placed locks. */ + void unlock (); + + /* Returns whether any lock is held. */ + bool + locked () + { + return fd < 0; + } + + /* Are lockfiles supported? */ + static bool lockfile_supported (); +private: + std::string filename; + int fd; +}; + +#endif