X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=deps%2Flightrec%2Frecompiler.c;h=1ccef7a067b25b7a10ff265ab3e9b208b9c570c1;hb=1f8c6be323aa8fad329e38682158197e822d27c1;hp=c764f11913a0333dcf3db8ae2ee04ee0513ebc76;hpb=f5ee77cadf78d389ce40f00988ee9bde1d567dc7;p=pcsx_rearmed.git diff --git a/deps/lightrec/recompiler.c b/deps/lightrec/recompiler.c index c764f119..1ccef7a0 100644 --- a/deps/lightrec/recompiler.c +++ b/deps/lightrec/recompiler.c @@ -23,6 +23,7 @@ struct block_rec { struct block *block; struct slist_elm slist; + unsigned int requests; bool compiling; }; @@ -37,7 +38,7 @@ struct recompiler { pthread_cond_t cond; pthread_cond_t cond2; pthread_mutex_t mutex; - bool stop, must_flush; + bool stop, pause, must_flush; struct slist_elm slist; pthread_mutex_t alloc_mutex; @@ -48,7 +49,7 @@ struct recompiler { static unsigned int get_processors_count(void) { - unsigned int nb = 1; + int nb = 1; #if defined(PTW32_VERSION) nb = pthread_num_processors_np(); @@ -58,25 +59,26 @@ static unsigned int get_processors_count(void) nb = sysctlbyname("hw.ncpu", &count, &size, NULL, 0) ? 1 : count; #elif defined(_SC_NPROCESSORS_ONLN) - nb = sysconf(_SC_NPROCESSORS_ONLN); + nb = (int)sysconf(_SC_NPROCESSORS_ONLN); #endif return nb < 1 ? 1 : nb; } -static struct slist_elm * lightrec_get_first_elm(struct slist_elm *head) +static struct block_rec * lightrec_get_best_elm(struct slist_elm *head) { - struct block_rec *block_rec; + struct block_rec *block_rec, *best = NULL; struct slist_elm *elm; for (elm = slist_first(head); elm; elm = elm->next) { block_rec = container_of(elm, struct block_rec, slist); - if (!block_rec->compiling) - return elm; + if (!block_rec->compiling + && (!best || block_rec->requests > best->requests)) + best = block_rec; } - return NULL; + return best; } static bool lightrec_cancel_block_rec(struct recompiler *rec, @@ -126,12 +128,11 @@ static void lightrec_compile_list(struct recompiler *rec, struct recompiler_thd *thd) { struct block_rec *block_rec; - struct slist_elm *next; struct block *block; int ret; - while (!!(next = lightrec_get_first_elm(&rec->slist))) { - block_rec = container_of(next, struct block_rec, slist); + while (!rec->pause && + !!(block_rec = lightrec_get_best_elm(&rec->slist))) { block_rec->compiling = true; block = block_rec->block; @@ -166,7 +167,7 @@ static void lightrec_compile_list(struct recompiler *rec, pthread_mutex_lock(&rec->mutex); - slist_remove(&rec->slist, next); + slist_remove(&rec->slist, &block_rec->slist); lightrec_free(rec->state, MEM_FOR_LIGHTREC, sizeof(*block_rec), block_rec); pthread_cond_broadcast(&rec->cond2); @@ -187,7 +188,7 @@ static void * lightrec_recompiler_thd(void *d) if (rec->stop) goto out_unlock; - } while (slist_empty(&rec->slist)); + } while (rec->pause || slist_empty(&rec->slist)); lightrec_compile_list(rec, thd); } @@ -228,6 +229,7 @@ struct recompiler *lightrec_recompiler_init(struct lightrec_state *state) rec->state = state; rec->stop = false; + rec->pause = false; rec->must_flush = false; rec->nb_recs = nb_recs; slist_init(&rec->slist); @@ -314,8 +316,9 @@ void lightrec_free_recompiler(struct recompiler *rec) int lightrec_recompiler_add(struct recompiler *rec, struct block *block) { - struct slist_elm *elm, *prev; + struct slist_elm *elm; struct block_rec *block_rec; + u32 pc1, pc2; int ret = 0; pthread_mutex_lock(&rec->mutex); @@ -331,20 +334,23 @@ int lightrec_recompiler_add(struct recompiler *rec, struct block *block) if (block_has_flag(block, BLOCK_IS_DEAD)) goto out_unlock; - for (elm = slist_first(&rec->slist), prev = NULL; elm; - prev = elm, elm = elm->next) { + for (elm = slist_first(&rec->slist); elm; elm = elm->next) { block_rec = container_of(elm, struct block_rec, slist); if (block_rec->block == block) { - /* The block to compile is already in the queue - bump - * it to the top of the list, unless the block is being - * recompiled. */ - if (prev && !block_rec->compiling && - !block_has_flag(block, BLOCK_SHOULD_RECOMPILE)) { - slist_remove_next(prev); - slist_append(&rec->slist, elm); - } + /* The block to compile is already in the queue - + * increment its counter to increase its priority */ + block_rec->requests++; + goto out_unlock; + } + pc1 = kunseg(block_rec->block->pc); + pc2 = kunseg(block->pc); + if (pc2 >= pc1 && pc2 < pc1 + block_rec->block->nb_ops * 4) { + /* The block we want to compile is already covered by + * another one in the queue - increment its counter to + * increase its priority */ + block_rec->requests++; goto out_unlock; } } @@ -365,14 +371,11 @@ int lightrec_recompiler_add(struct recompiler *rec, struct block *block) block_rec->block = block; block_rec->compiling = false; + block_rec->requests = 1; elm = &rec->slist; - /* If the block is being recompiled, push it to the end of the queue; - * otherwise push it to the front of the queue. */ - if (block_has_flag(block, BLOCK_SHOULD_RECOMPILE)) - for (; elm->next; elm = elm->next); - + /* Push the new entry to the front of the queue */ slist_append(elm, &block_rec->slist); /* Signal the thread */ @@ -485,3 +488,18 @@ void lightrec_code_alloc_unlock(struct lightrec_state *state) { pthread_mutex_unlock(&state->rec->alloc_mutex); } + +void lightrec_recompiler_pause(struct recompiler *rec) +{ + rec->pause = true; + + pthread_mutex_lock(&rec->mutex); + pthread_cond_broadcast(&rec->cond); + lightrec_cancel_list(rec); + pthread_mutex_unlock(&rec->mutex); +} + +void lightrec_recompiler_unpause(struct recompiler *rec) +{ + rec->pause = false; +}