$(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
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)
--- /dev/null
+/* 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
+}
--- /dev/null
+/* 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