File parallelbinaries2.patch of Package rpm

diff --git a/build/files.c b/build/files.c
index 26013b138..d7d6d5ba2 100644
--- a/build/files.c
+++ b/build/files.c
@@ -11,6 +11,7 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <regex.h>
+#include <omp.h>
 #if WITH_CAP
 #include <sys/capability.h>
 #endif
@@ -3025,7 +3026,7 @@ static void addPackageDeps(Package from, Package to, enum rpmTag_e tag)
 
 static rpmRC processBinary(rpmSpec spec, Package pkg, rpmBuildPkgFlags pkgFlags,
             int didInstall, int test, Package maindbg, char *buildroot, Package dbgsrcpkg,
-            char *uniquearch)
+            char *uniquearch, omp_lock_t *debuginfolock)
 {
     Package deplink = NULL;     /* create requires to this package */
 
@@ -3036,6 +3037,7 @@ static rpmRC processBinary(rpmSpec spec, Package pkg, rpmBuildPkgFlags pkgFlags,
     int arch_color;
 
     if (pkg == maindbg) {
+        omp_set_lock(debuginfolock);
         /* if there is just one debuginfo package, we put our extra stuff
          * in it. Otherwise we put it in the main debug package */
         Package extradbg = !maindbg->fileList && maindbg->next && !maindbg->next->next ?
@@ -3047,6 +3049,7 @@ static rpmRC processBinary(rpmSpec spec, Package pkg, rpmBuildPkgFlags pkgFlags,
         if (dbgsrcpkg != NULL)
         addPackageDeps(extradbg, dbgsrcpkg, RPMTAG_RECOMMENDNAME);
         maindbg = NULL; /* all normal packages processed */
+        omp_unset_lock(debuginfolock);
     }
 
     if (pkg->fileList == NULL)
@@ -3055,7 +3058,7 @@ static rpmRC processBinary(rpmSpec spec, Package pkg, rpmBuildPkgFlags pkgFlags,
     headerPutString(pkg->header, RPMTAG_SOURCERPM, spec->sourceRpmName);
 
     nvr = headerGetAsString(pkg->header, RPMTAG_NVRA);
-    rpmlog(RPMLOG_NOTICE, _("Processing files: %s\n"), nvr);
+    rpmlog(RPMLOG_NOTICE, _("Processing files: %s: 0x%X\n"), nvr, pkg);
     free(nvr);
 
     if ((rc = processPackageFiles(spec, pkgFlags, pkg, didInstall, test)) != RPMRC_OK)
@@ -3093,6 +3096,69 @@ exit:
     return rc;
 }
 
+struct processBinaryTaskData
+{
+    Package pkg;
+    rpmRC result;
+    struct processBinaryTaskData *next;
+};
+
+static struct processBinaryTaskData* runProcessBinaryTasks(rpmSpec spec, rpmBuildPkgFlags pkgFlags,
+            int didInstall, int test, Package maindbg, char *buildroot, Package dbgsrcpkg,
+            char *uniquearch)
+{
+    struct processBinaryTaskData *tasks = NULL;
+    struct processBinaryTaskData *task = NULL;
+    struct processBinaryTaskData *prev = NULL;
+
+    omp_lock_t debuginfolock;
+
+    omp_init_lock(&debuginfolock);
+
+    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 = processBinary(spec, pkg, pkgFlags, didInstall, test, maindbg, buildroot, dbgsrcpkg, uniquearch, &debuginfolock);
+            //! Todo - Does this need printing
+            rpmlog(RPMLOG_NOTICE, _("Finished binary package job, result %d, filename 0x%X\n"), task->result, task);
+            task->result = RPMRC_FAIL;
+            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 processBinaryTaskData *task = tasks; task != NULL; task = task->next) {
+        if (task != tasks)
+        #pragma omp task
+        {
+            task->result = processBinary(spec, task->pkg, pkgFlags, didInstall, test, maindbg, buildroot, dbgsrcpkg, uniquearch, &debuginfolock);
+            //! Todo - does this need printing
+            rpmlog(RPMLOG_NOTICE, _("Finished binary package job, result %d, filename 0x%X\n"), task->result, task);
+        }
+    }
+    omp_destroy_lock(&debuginfolock);
+    return tasks;
+}
+static void freeProcessBinaryTasks(struct processBinaryTaskData* tasks)
+{
+    while (tasks != NULL) {
+        struct processBinaryTaskData* next = tasks->next;
+        //! todo, do I need to add this back?
+        // rfree(tasks->filename);
+        rfree(tasks);
+        tasks = next;
+    }
+}
+
 rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags,
 			int didInstall, int test)
 {
@@ -3104,6 +3170,7 @@ rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags,
     /* The debugsource package, if it exists, that the debuginfo package(s)
        should Recommend.  */
     Package dbgsrcpkg = findDebugsourcePackage(spec);
+    struct processBinaryTaskData *tasks = NULL;
     
 #if HAVE_LIBDW
     elf_version (EV_CURRENT);
@@ -3142,11 +3209,21 @@ rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags,
 	    addPackageDeps(dbgpkg, dbgsrcpkg, RPMTAG_RECOMMENDNAME);
     }
 
-    for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
-       if ((rc = processBinary(spec, pkg, pkgFlags, didInstall, test, maindbg, buildroot, dbgsrcpkg, uniquearch)) != RPMRC_OK)
-       goto exit;
+    tasks = runProcessBinaryTasks(spec, pkgFlags, didInstall, test, maindbg, buildroot, dbgsrcpkg, uniquearch);
+    
+    for (struct processBinaryTaskData *task = tasks; task != NULL; task = task->next) {
+        if (task->result == RPMRC_OK) {
+            //! Todo - need this
+            // rstrcat(&pkglist, task->filename);
+            // rstrcat(&pkglist, " ");
+        } else {
+            // _free(pkglist);
+            freeProcessBinaryTasks(tasks);
+            rc = RPMRC_FAIL;
+            goto exit;
+        }
     }
-
+    freeProcessBinaryTasks(tasks);
     /* Now we have in fileList list of files from all packages.
      * We pass it to a script which does the work of finding missing
      * and duplicated files.
diff --git a/configure.ac b/configure.ac
index 484d22fec..4035f0b52 100644
--- a/configure.ac
+++ b/configure.ac
@@ -992,6 +992,9 @@ AS_IF([test "$enable_plugins" != no],[
 ])
 AM_CONDITIONAL(DBUS, [test "$with_dbus" = yes])
 
+#AX_OPENMP([CFLAGS="$CFLAGS $OPENMP_CFLAGS",
+#           LIBS="$LIBS $OPENMP_LIBS"])
+
 AS_IF([test "$enable_plugins" != no],[
   AC_CHECK_FUNCS(lsetxattr, [], [], [#include <sys/xattr.h>])
 ])