summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/rpm/files/0002-Run-binary-package-creation-via-thread-pools.patch
blob: d10041c2e14de452c80db9e066a3c8fa86474152 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
From 513200cf76758de4668312c628d6362bdabfaf4b Mon Sep 17 00:00:00 2001
From: Alexander Kanavin <alex.kanavin@gmail.com>
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 <alex.kanavin@gmail.com>

---
 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