This version differs by using INCLUDE_STRING instead of <string>. (+whitespace and year)
___ 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 -- 2.45.1