From 513200cf76758de4668312c628d6362bdabfaf4b Mon Sep 17 00:00:00 2001 From: Alexander Kanavin Date: Thu, 25 May 2017 19:30:20 +0300 Subject: [PATCH 1/3] Run binary package creation via thread pools. Upstream-Status: Submitted [https://github.com/rpm-software-management/rpm/pull/226] Signed-off-by: Alexander Kanavin --- build/pack.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++----------- configure.ac | 3 +++ 2 files changed, 70 insertions(+), 14 deletions(-) diff --git a/build/pack.c b/build/pack.c index ccfd614cc..ed5b9ab4e 100644 --- a/build/pack.c +++ b/build/pack.c @@ -616,25 +616,78 @@ static rpmRC packageBinary(rpmSpec spec, Package pkg, const char *cookie, int ch return rc; } -rpmRC packageBinaries(rpmSpec spec, const char *cookie, int cheating) +struct binaryPackageTaskData { - rpmRC rc; Package pkg; + char *filename; + rpmRC result; + struct binaryPackageTaskData *next; +}; + +static struct binaryPackageTaskData* runBinaryPackageTasks(rpmSpec spec, const char *cookie, int cheating) +{ + struct binaryPackageTaskData *tasks = NULL; + struct binaryPackageTaskData *task = NULL; + struct binaryPackageTaskData *prev = NULL; + + for (Package pkg = spec->packages; pkg != NULL; pkg = pkg->next) { + task = rcalloc(1, sizeof(*task)); + task->pkg = pkg; + if (pkg == spec->packages) { + // the first package needs to be processed ahead of others, as they copy + // changelog data from it, and so otherwise data races would happen + task->result = packageBinary(spec, pkg, cookie, cheating, &(task->filename)); + rpmlog(RPMLOG_NOTICE, _("Finished binary package job, result %d, filename %s\n"), task->result, task->filename); + tasks = task; + } + if (prev != NULL) { + prev->next = task; + } + prev = task; + } + + #pragma omp parallel + #pragma omp single + // re-declaring task variable is necessary, or older gcc versions will produce code that segfaults + for (struct binaryPackageTaskData *task = tasks; task != NULL; task = task->next) { + if (task != tasks) + #pragma omp task + { + task->result = packageBinary(spec, task->pkg, cookie, cheating, &(task->filename)); + rpmlog(RPMLOG_NOTICE, _("Finished binary package job, result %d, filename %s\n"), task->result, task->filename); + } + } + + return tasks; +} + +static void freeBinaryPackageTasks(struct binaryPackageTaskData* tasks) +{ + while (tasks != NULL) { + struct binaryPackageTaskData* next = tasks->next; + rfree(tasks->filename); + rfree(tasks); + tasks = next; + } +} + +rpmRC packageBinaries(rpmSpec spec, const char *cookie, int cheating) +{ char *pkglist = NULL; - for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) { - char *fn = NULL; - rc = packageBinary(spec, pkg, cookie, cheating, &fn); - if (rc == RPMRC_OK) { - rstrcat(&pkglist, fn); - rstrcat(&pkglist, " "); - } - free(fn); - if (rc != RPMRC_OK) { - pkglist = _free(pkglist); - return rc; - } + struct binaryPackageTaskData *tasks = runBinaryPackageTasks(spec, cookie, cheating); + + for (struct binaryPackageTaskData *task = tasks; task != NULL; task = task->next) { + if (task->result == RPMRC_OK) { + rstrcat(&pkglist, task->filename); + rstrcat(&pkglist, " "); + } else { + _free(pkglist); + freeBinaryPackageTasks(tasks); + return RPMRC_FAIL; + } } + freeBinaryPackageTasks(tasks); /* Now check the package set if enabled */ if (pkglist != NULL) { diff --git a/configure.ac b/configure.ac index a506ec819..59fa0acaf 100644 --- a/configure.ac +++ b/configure.ac @@ -17,6 +17,9 @@ AC_DISABLE_STATIC PKG_PROG_PKG_CONFIG +AC_OPENMP +RPMCFLAGS="$OPENMP_CFLAGS $RPMCFLAGS" + dnl Checks for programs. AC_PROG_CXX AC_PROG_AWK -- 2.11.0