]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - parser.c
Merge branch 'master' into threading
[xonotic/gmqcc.git] / parser.c
index 82ce53b0a47a84deeb0b422fc32c1558c8412681..e6b7f612d9c40791fe7b05b425ca72387c688a10 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -23,6 +23,7 @@
  */
 #include <string.h>
 #include <math.h>
+#include <pthread.h>
 
 #include "parser.h"
 
@@ -6141,6 +6142,86 @@ void parser_cleanup(parser_t *parser)
     mem_d(parser);
 }
 
+static void function_finalize_worker_do(ast_function **list, size_t count, volatile uint32_t *counter, bool *failure)
+{
+    do {
+        uint32_t idx = util_atomic_xadd32(counter, 1);
+        if (idx >= count) {
+            *counter = count;
+            return;
+        }
+        if (!ir_function_finalize(list[idx]->ir_func)) {
+            con_out("failed to finalize function %s\n", list[idx]->name);
+            *failure = true;
+            return;
+        }
+    } while (true);
+}
+
+typedef struct {
+    ast_function     **list;
+    size_t             count;
+    volatile uint32_t *counter;
+    bool              *failure;
+} function_finalize_worker_data;
+static void* function_finalize_worker(void *_d) {
+    function_finalize_worker_data *d = (function_finalize_worker_data*)_d;
+    function_finalize_worker_do(d->list, d->count, d->counter, d->failure);
+    return NULL;
+}
+
+static bool function_finalize_all_threaded(ast_function **list, size_t count)
+{
+    volatile uint32_t counter = 0;
+    function_finalize_worker_data wd;
+
+    size_t poolsize = OPTS_OPTION_U32(OPTION_J);
+    bool   failure = false;
+    size_t i, j;
+
+    pthread_t *threads;
+
+    if (!list || !count)
+        return true;
+
+    wd.list    = list;
+    wd.count   = count;
+    wd.counter = &counter;
+    wd.failure = &failure;
+
+    threads = (pthread_t*)mem_a(poolsize*sizeof(pthread_t));
+
+    for (i = 0; i < poolsize; ++i) {
+        if (pthread_create(threads+i, NULL, &function_finalize_worker, &wd) != 0)
+            break;
+    }
+    if (i < poolsize) {
+        con_out("failed to spawn worker threads\n");
+        for (j = 0; j <= i; ++j)
+            pthread_join(threads[j], NULL);
+        return false;
+    }
+    for (i = 0; i < poolsize; ++i)
+        pthread_join(threads[i], NULL);
+    return !failure;
+}
+
+bool function_finalize_all(ast_function **list, size_t count);
+bool function_finalize_all(ast_function **list, size_t count)
+{
+    size_t i;
+    if (OPTS_OPTION_U32(OPTION_J) > 1)
+        return function_finalize_all_threaded(list, count);
+
+    for (i = 0; i < count; ++i) {
+        if (!ir_function_finalize(list[i]->ir_func)) {
+            con_out("failed to finalize function %s\n", list[i]->name);
+            return false;
+        }
+    }
+    return true;
+}
+
 bool parser_finish(parser_t *parser, const char *output)
 {
     size_t i;
@@ -6281,6 +6362,8 @@ bool parser_finish(parser_t *parser, const char *output)
 
     if (OPTS_OPTION_BOOL(OPTION_DUMP))
         ir_builder_dump(ir, con_out);
+
+#if 0
     for (i = 0; i < vec_size(parser->functions); ++i) {
         if (!ir_function_finalize(parser->functions[i]->ir_func)) {
             con_out("failed to finalize function %s\n", parser->functions[i]->name);
@@ -6288,6 +6371,14 @@ bool parser_finish(parser_t *parser, const char *output)
             return false;
         }
     }
+
+#else
+    if (!function_finalize_all(parser->functions, vec_size(parser->functions))) {
+        ir_builder_delete(ir);
+        return false;
+    }
+#endif
+
     parser_remove_ast(parser);
 
     if (compile_Werrors) {