]> git.rm.cloudns.org Git - xonotic/gmqcc.git/commitdiff
stupid simple threading test
authorWolfgang Bumiller <wry.git@bumiller.com>
Wed, 17 Apr 2013 14:04:07 +0000 (16:04 +0200)
committerWolfgang Bumiller <wry.git@bumiller.com>
Wed, 17 Apr 2013 14:04:07 +0000 (16:04 +0200)
Makefile
gmqcc.h
main.c
opts.c
opts.def
parser.c
thread.c [new file with mode: 0644]

index 20152c5bf3f6cfa361066c45a33cf097d3917a73..3a215f298d06a0971a428c3a1459e34fd04b6836 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@ CYGWIN  = $(findstring CYGWIN,  $(UNAME))
 MINGW   = $(findstring MINGW32, $(UNAME))
 
 CC     ?= clang
-CFLAGS += -Wall -Wextra -Werror -I. -fno-strict-aliasing -fsigned-char $(OPTIONAL)
+CFLAGS += -Wall -Wextra -Werror -I. -fno-strict-aliasing -fsigned-char -pthread $(OPTIONAL)
 ifneq ($(shell git describe --always 2>/dev/null),)
     CFLAGS += -DGMQCC_GITINFO="\"$(shell git describe --always)\""
 endif
@@ -42,7 +42,7 @@ ifeq ($(track), no)
        CFLAGS += -DNOTRACK
 endif
 
-OBJ_D = util.o code.o ast.o ir.o conout.o ftepp.o opts.o fs.o utf8.o correct.o
+OBJ_D = util.o code.o ast.o ir.o thread.o conout.o ftepp.o opts.o fs.o utf8.o correct.o
 OBJ_P = util.o fs.o conout.o opts.o pak.o
 OBJ_T = test.o util.o conout.o fs.o
 OBJ_C = main.o lexer.o parser.o fs.o
@@ -177,7 +177,7 @@ $(QCVM): $(OBJ_X)
        $(CC) -o $@ $^ $(CFLAGS) -lm
 
 $(GMQCC): $(OBJ_C) $(OBJ_D)
-       $(CC) -o $@ $^ $(CFLAGS) -lm
+       $(CC) -o $@ $^ $(CFLAGS) -lm -pthread
 
 $(TESTSUITE): $(OBJ_T)
        $(CC) -o $@ $^ $(CFLAGS) -lm
diff --git a/gmqcc.h b/gmqcc.h
index 42e771459303cc7be78cb564abd28b7d5d73273e..41d036d9664bd93e0c00a04dd7a148007469116d 100644 (file)
--- a/gmqcc.h
+++ b/gmqcc.h
@@ -465,7 +465,12 @@ int         util_hsadd(hash_set_t *, void *);
 int         util_hshas(hash_set_t *, void *);
 int         util_hsrem(hash_set_t *, void *);
 void        util_hsdel(hash_set_t *);
+
+/*===================================================================*/
+/*=========================== thread.c ==============================*/
+/*===================================================================*/
+GMQCC_INLINE uint32_t util_atomic_xadd32(volatile uint32_t *x, uint32_t v);
+
 /*===================================================================*/
 /*============================ file.c ===============================*/
 /*===================================================================*/
diff --git a/main.c b/main.c
index 0a22b1bada1716cdf55a6d389f71dd9294a27701..be4eaef3b9e9a1337ddf42cebed4770ad911fcaf 100644 (file)
--- a/main.c
+++ b/main.c
@@ -212,6 +212,11 @@ static bool options_parse(int argc, char **argv) {
                 OPTS_OPTION_U16 (OPTION_FORCED_CRC) = strtol(argarg, NULL, 0);
                 continue;
             }
+            if (options_long_gcc("jobs", &argc, &argv, &argarg)) {
+
+                OPTS_OPTION_U32 (OPTION_J) = strtol(argarg, NULL, 0);
+                continue;
+            }
             if (options_long_gcc("redirout", &argc, &argv, &redirout)) {
                 con_change(redirout, redirerr);
                 continue;
@@ -459,6 +464,14 @@ static bool options_parse(int argc, char **argv) {
                     vec_push(items, item);
                     break;
 
+                case 'j':
+                    if (!options_witharg(&argc, &argv, &argarg)) {
+                        con_out("option -j requires a parameter\n");
+                        return false;
+                    }
+                    OPTS_OPTION_U32 (OPTION_J) = strtol(argarg, NULL, 0);
+                    break;
+
                 case '-':
                     if (!argv[0][2]) {
                         /* anything following -- is considered a non-option argument */
diff --git a/opts.c b/opts.c
index e37ba7356d78ad6bdace480b77113c1d75863b25..c3d69aa9a884579aa501edb6d6aa06c5acbd6f71 100644 (file)
--- a/opts.c
+++ b/opts.c
@@ -98,6 +98,7 @@ void opts_init(const char *output, int standard, size_t arraysize) {
     OPTS_OPTION_U32(OPTION_STANDARD)       = standard;
     OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE) = arraysize;
     OPTS_OPTION_U16(OPTION_MEMDUMPCOLS)    = 16;
+    OPTS_OPTION_U32(OPTION_J)              = 2;
 }
 
 static bool opts_setflag_all(const char *name, bool on, uint32_t *flags, const opts_flag_def *list, size_t listsize) {
index f7b5cf115ea90ee143bb713bd99d9920f1fefcab..47f82eeb36835e8c4b7bae2ebe4645ae00b1925d 100644 (file)
--- a/opts.def
+++ b/opts.def
     GMQCC_DEFINE_FLAG(MAX_ARRAY_SIZE)
     GMQCC_DEFINE_FLAG(ADD_INFO)
     GMQCC_DEFINE_FLAG(CORRECTION)
+    GMQCC_DEFINE_FLAG(J)
 #endif
 
 /* some cleanup so we don't have to */
index 5d4ea7d0650de50c505d809dd36cab0c7a52cf5c..db9428967441fa5854217f64059bc91a19c90d1b 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -24,6 +24,7 @@
 #include <stdio.h>
 #include <stdarg.h>
 #include <math.h>
+#include <pthread.h>
 
 #include "gmqcc.h"
 #include "lexer.h"
@@ -6100,6 +6101,84 @@ 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*)alloca(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)
+{
+    size_t i = 0;
+    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;
@@ -6255,6 +6334,7 @@ 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);
@@ -6262,6 +6342,12 @@ 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
 
     if (compile_Werrors) {
         con_out("*** there were warnings treated as errors\n");
diff --git a/thread.c b/thread.c
new file mode 100644 (file)
index 0000000..741ac0f
--- /dev/null
+++ b/thread.c
@@ -0,0 +1,13 @@
+#include "gmqcc.h"
+
+GMQCC_INLINE uint32_t util_atomic_xadd32(volatile uint32_t *x, uint32_t v)
+{
+    uint32_t r;
+    asm volatile (
+        "lock xadd %1, %0"
+        : "+m"(*x), "=r"(r)
+        : "1"(v)
+        : "memory", "cc"
+    );
+    return r;
+}