From: Wolfgang Bumiller Date: Wed, 17 Apr 2013 14:04:07 +0000 (+0200) Subject: stupid simple threading test X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=76132adb20187f9f4ed7d465fa6129917284ca08;p=xonotic%2Fgmqcc.git stupid simple threading test --- diff --git a/Makefile b/Makefile index 20152c5..3a215f2 100644 --- 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 42e7714..41d036d 100644 --- 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 0a22b1b..be4eaef 100644 --- 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 e37ba73..c3d69aa 100644 --- 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) { diff --git a/opts.def b/opts.def index f7b5cf1..47f82ee 100644 --- a/opts.def +++ b/opts.def @@ -119,6 +119,7 @@ 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 */ diff --git a/parser.c b/parser.c index 5d4ea7d..db94289 100644 --- a/parser.c +++ b/parser.c @@ -24,6 +24,7 @@ #include #include #include +#include #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 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; +}