blob: d10041c2e14de452c80db9e066a3c8fa86474152 [file] [log] [blame]
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001From 513200cf76758de4668312c628d6362bdabfaf4b Mon Sep 17 00:00:00 2001
2From: Alexander Kanavin <alex.kanavin@gmail.com>
3Date: Thu, 25 May 2017 19:30:20 +0300
4Subject: [PATCH 1/3] Run binary package creation via thread pools.
5
6Upstream-Status: Submitted [https://github.com/rpm-software-management/rpm/pull/226]
7Signed-off-by: Alexander Kanavin <alex.kanavin@gmail.com>
8
9---
10 build/pack.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++-----------
11 configure.ac | 3 +++
12 2 files changed, 70 insertions(+), 14 deletions(-)
13
14diff --git a/build/pack.c b/build/pack.c
15index ccfd614cc..ed5b9ab4e 100644
16--- a/build/pack.c
17+++ b/build/pack.c
18@@ -616,25 +616,78 @@ static rpmRC packageBinary(rpmSpec spec, Package pkg, const char *cookie, int ch
19 return rc;
20 }
21
22-rpmRC packageBinaries(rpmSpec spec, const char *cookie, int cheating)
23+struct binaryPackageTaskData
24 {
25- rpmRC rc;
26 Package pkg;
27+ char *filename;
28+ rpmRC result;
29+ struct binaryPackageTaskData *next;
30+};
31+
32+static struct binaryPackageTaskData* runBinaryPackageTasks(rpmSpec spec, const char *cookie, int cheating)
33+{
34+ struct binaryPackageTaskData *tasks = NULL;
35+ struct binaryPackageTaskData *task = NULL;
36+ struct binaryPackageTaskData *prev = NULL;
37+
38+ for (Package pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
39+ task = rcalloc(1, sizeof(*task));
40+ task->pkg = pkg;
41+ if (pkg == spec->packages) {
42+ // the first package needs to be processed ahead of others, as they copy
43+ // changelog data from it, and so otherwise data races would happen
44+ task->result = packageBinary(spec, pkg, cookie, cheating, &(task->filename));
45+ rpmlog(RPMLOG_NOTICE, _("Finished binary package job, result %d, filename %s\n"), task->result, task->filename);
46+ tasks = task;
47+ }
48+ if (prev != NULL) {
49+ prev->next = task;
50+ }
51+ prev = task;
52+ }
53+
54+ #pragma omp parallel
55+ #pragma omp single
56+ // re-declaring task variable is necessary, or older gcc versions will produce code that segfaults
57+ for (struct binaryPackageTaskData *task = tasks; task != NULL; task = task->next) {
58+ if (task != tasks)
59+ #pragma omp task
60+ {
61+ task->result = packageBinary(spec, task->pkg, cookie, cheating, &(task->filename));
62+ rpmlog(RPMLOG_NOTICE, _("Finished binary package job, result %d, filename %s\n"), task->result, task->filename);
63+ }
64+ }
65+
66+ return tasks;
67+}
68+
69+static void freeBinaryPackageTasks(struct binaryPackageTaskData* tasks)
70+{
71+ while (tasks != NULL) {
72+ struct binaryPackageTaskData* next = tasks->next;
73+ rfree(tasks->filename);
74+ rfree(tasks);
75+ tasks = next;
76+ }
77+}
78+
79+rpmRC packageBinaries(rpmSpec spec, const char *cookie, int cheating)
80+{
81 char *pkglist = NULL;
82
83- for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
84- char *fn = NULL;
85- rc = packageBinary(spec, pkg, cookie, cheating, &fn);
86- if (rc == RPMRC_OK) {
87- rstrcat(&pkglist, fn);
88- rstrcat(&pkglist, " ");
89- }
90- free(fn);
91- if (rc != RPMRC_OK) {
92- pkglist = _free(pkglist);
93- return rc;
94- }
95+ struct binaryPackageTaskData *tasks = runBinaryPackageTasks(spec, cookie, cheating);
96+
97+ for (struct binaryPackageTaskData *task = tasks; task != NULL; task = task->next) {
98+ if (task->result == RPMRC_OK) {
99+ rstrcat(&pkglist, task->filename);
100+ rstrcat(&pkglist, " ");
101+ } else {
102+ _free(pkglist);
103+ freeBinaryPackageTasks(tasks);
104+ return RPMRC_FAIL;
105+ }
106 }
107+ freeBinaryPackageTasks(tasks);
108
109 /* Now check the package set if enabled */
110 if (pkglist != NULL) {
111diff --git a/configure.ac b/configure.ac
112index a506ec819..59fa0acaf 100644
113--- a/configure.ac
114+++ b/configure.ac
115@@ -17,6 +17,9 @@ AC_DISABLE_STATIC
116
117 PKG_PROG_PKG_CONFIG
118
119+AC_OPENMP
120+RPMCFLAGS="$OPENMP_CFLAGS $RPMCFLAGS"
121+
122 dnl Checks for programs.
123 AC_PROG_CXX
124 AC_PROG_AWK
125--
1262.11.0
127