Skip to content

Commit

Permalink
Revert "Allow numbers other than 1 for MOLD_JOBS"
Browse files Browse the repository at this point in the history
This reverts commit 8638930 because
it's unstable.
  • Loading branch information
rui314 committed Jul 11, 2024
1 parent 162bcca commit 8426310
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 147 deletions.
6 changes: 0 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -277,12 +277,6 @@ if(NOT APPLE AND NOT MSVC)
target_link_options(mold PRIVATE -pthread)
endif()

# shm_open needs -lrt
find_library(LIBRT rt)
if(LIBRT)
target_link_libraries(mold PRIVATE rt)
endif()

check_symbol_exists(madvise sys/mman.h HAVE_MADVISE)

# Create a .cc file containing the current git hash for `mold --version`.
Expand Down
128 changes: 11 additions & 117 deletions common/jobs-unix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,149 +8,43 @@
// This file implements a feature that limits the number of concurrent
// mold processes to just 1 for each user. It is intended to be used as
// `MOLD_JOBS=1 ninja` or `MOLD_JOBS=1 make -j$(nproc)`.
//
// We can't use POSIX semaphores because the counter will not be
// decremented automatically when a process exits abnormally. That would
// results in a deadlock. Therefore, we use lockf-based regional file
// locking instead. Unlike POSIX semaphores, the lock will automatically
// released on process termination.
//
// To wake processes that may be waiting on the lock file, we use a
// pthread condition variable. On normal exit, mold sends notifications to
// all waiting processes. In case of abnormal exit, we use
// pthread_cond_timedwait so that waiters will not wait forever.

#include "common.h"

#include <atomic>
#include <fcntl.h>
#include <pthread.h>
#include <pwd.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

namespace mold {

static constexpr i64 MAX_JOBS = 128;

struct SharedData {
std::atomic_bool initialized;
pthread_mutex_t mu;
pthread_cond_t cond;
};

static int num_jobs = -1;
static int lock_fd = -1;
static SharedData *shared_data = nullptr;

static i64 get_mold_jobs() {
char *env = getenv("MOLD_JOBS");
if (!env)
return 0;

i64 jobs = std::stol(env);
if (jobs < 0)
return 0;
return std::min(jobs, MAX_JOBS);
}

static bool do_lock() {
for (i64 i = 0; i < num_jobs; i++) {
lseek(lock_fd, i, SEEK_SET);
if (lockf(lock_fd, F_TLOCK, 1) == 0)
return true;
}
return false;
}

static SharedData *get_shared_data() {
// Create a shared memory object and mmap it
std::string name = "/mold-signal-" + std::to_string(getuid());
i64 size = sizeof(SharedData);

int shm_fd = shm_open(name.c_str(), O_CREAT | O_RDWR, 0600);
if (shm_fd == -1) {
perror("shm_open");
exit(1);
}

if (ftruncate(shm_fd, size) == -1) {
perror("ftruncate");
exit(1);
}

SharedData *data = (SharedData *)mmap(0, size, PROT_READ | PROT_WRITE,
MAP_SHARED, shm_fd, 0);
close(shm_fd);

if (data->initialized.exchange(true) == false) {
pthread_mutexattr_t mu_attr;
pthread_mutexattr_init(&mu_attr);
pthread_mutexattr_setpshared(&mu_attr, PTHREAD_PROCESS_SHARED);

#ifndef __APPLE__
pthread_mutexattr_setrobust(&mu_attr, PTHREAD_MUTEX_ROBUST);
#endif

pthread_mutex_init(&data->mu, &mu_attr);

pthread_condattr_t cond_attr;
pthread_condattr_init(&cond_attr);
pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED);
pthread_cond_init(&data->cond, &cond_attr);
}
return data;
}

void acquire_global_lock() {
num_jobs = get_mold_jobs();
if (num_jobs == 0)
char *jobs = getenv("MOLD_JOBS");
if (!jobs || jobs != "1"s)
return;

shared_data = get_shared_data();

std::string path;
if (char *dir = getenv("XDG_RUNTIME_DIR"))
path = dir + "/mold.lock"s;
path = dir + "/mold-lock"s;
else
path = "/tmp/mold-" + std::to_string(getuid()) + ".lock";
path = "/tmp/mold-lock-"s + getpwuid(getuid())->pw_name;

lock_fd = open(path.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, 0600);
if (lock_fd == -1 || do_lock())
int fd = open(path.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, 0600);
if (fd == -1)
return;

pthread_mutex_t *mu = &shared_data->mu;
pthread_cond_t *cond = &shared_data->cond;
int r = pthread_mutex_lock(mu);

#ifndef __APPLE__
// If the previous process got killed while holding the mutex, the
// mutex has became inconsistent. We need to fix it in that case.
if (r == EOWNERDEAD)
pthread_mutex_consistent(mu);
#endif

for (;;) {
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += 1;

int r = pthread_cond_timedwait(cond, mu, &ts);
if (do_lock() || r != ETIMEDOUT)
break;
}

pthread_mutex_unlock(mu);
if (lockf(fd, F_LOCK, 0) == -1)
return;
lock_fd = fd;
}

void release_global_lock() {
if (lock_fd == -1)
return;
close(lock_fd);
pthread_cond_broadcast(&shared_data->cond);
if (lock_fd != -1)
close(lock_fd);
}

} // namespace mold
4 changes: 3 additions & 1 deletion docs/mold.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ but as `-o magic`.
functions and replaces `argv[0]` with itself if it is `ld`, `ld.gold`, or
`ld.lld`.

* `--separate-debug-file`, `--separate-debug-file=_file_`
* `--separate-debug-file`, `--separate-debug-file=_file_`:
Bundle debug info sections into a separate file instead of embedding them in
an output executable or a shared library. mold creates a debug info file in
the background by default, so that you can start running your executable as
Expand Down Expand Up @@ -854,6 +854,8 @@ but as `-o magic`.
consider setting this environment variable to `1` to see if it addresses the
OOM issue.

Currently, any value other than `1` is silently ignored.

* `MOLD_DEBUG`:
If this variable is set to a non-empty string, `mold` embeds its
command-line options in the output file's `.comment` section.
Expand Down
23 changes: 0 additions & 23 deletions test/elf/mold-jobs.sh

This file was deleted.

0 comments on commit 8426310

Please sign in to comment.