h48

A prototype for an optimal Rubik's cube solver, work in progress.
git clone https://git.tronto.net/h48
Download | Log | Files | Refs | README | LICENSE

commit 1272e304b6367c7dd94d25acf88b2843adabb93a
parent 6f338b97a222dee630c9b13896cf443254667dfb
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Sat,  5 Oct 2024 23:00:08 +0200

Fix rare data race

I had some misconception about how _Atomic and const worked.
This means the previous commit (expected distribution) could
be incorrect.

Diffstat:
Msrc/nissy.c | 2+-
Msrc/solvers/h48/gendata_cocsep.h | 5+++--
Msrc/solvers/h48/gendata_h48.h | 45++++++++++++++++++++++-----------------------
Msrc/solvers/h48/solve.h | 4++--
Msrc/solvers/h48/stats.h | 4++--
5 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/src/nissy.c b/src/nissy.c @@ -75,7 +75,7 @@ checkdata(const void *buf, const tableinfo_t *info) getdistribution_cocsep( (uint32_t *)((char *)buf + INFOSIZE), distr); } else if (!strncmp(info->solver, "h48", 3)) { - getdistribution_h48((uint8_t *)buf + INFOSIZE, distr, + getdistribution_h48((_Atomic uint8_t *)buf + INFOSIZE, distr, info->h48h, info->bits); } else { LOG("checkdata: unknown solver %s\n", info->solver); diff --git a/src/solvers/h48/gendata_cocsep.h b/src/solvers/h48/gendata_cocsep.h @@ -5,7 +5,8 @@ STATIC size_t gendata_cocsep(void *, uint64_t *, cube_t *); STATIC uint32_t gendata_cocsep_dfs(cocsep_dfs_arg_t *); STATIC void getdistribution_cocsep(const uint32_t *, uint64_t [static 21]); -STATIC_INLINE int8_t get_h48_cdata(cube_t, const uint32_t *, uint32_t *); +STATIC_INLINE int8_t get_h48_cdata( + cube_t, _Atomic const uint32_t *, uint32_t *); /* Each element of the cocsep table is a uint32_t used as follows: @@ -158,7 +159,7 @@ set_visited(uint8_t *a, int64_t i) } STATIC_INLINE int8_t -get_h48_cdata(cube_t cube, const uint32_t *cocsepdata, uint32_t *cdata) +get_h48_cdata(cube_t cube, _Atomic const uint32_t *cocsepdata, uint32_t *cdata) { int64_t coord; diff --git a/src/solvers/h48/gendata_h48.h b/src/solvers/h48/gendata_h48.h @@ -28,16 +28,16 @@ STATIC size_t gendata_h48k2_realcoord(gendata_h48_arg_t *); STATIC void gendata_h48k2_dfs(h48k2_dfs_arg_t *arg); STATIC void * gendata_h48k2_runthread(void *); STATIC tableinfo_t makeinfo_h48k2(gendata_h48_arg_t *); -STATIC void getdistribution_h48(const uint8_t *, +STATIC void getdistribution_h48(_Atomic const uint8_t *, uint64_t [static INFO_DISTRIBUTION_LEN], uint8_t, uint8_t); -STATIC const uint32_t *get_cocsepdata_constptr(const void *); -STATIC const uint8_t *get_h48data_constptr(const void *); +STATIC _Atomic const uint32_t *get_cocsepdata_constptr(const void *); +STATIC _Atomic const uint8_t *get_h48data_constptr(const void *); -STATIC_INLINE uint8_t get_h48_pval(const uint8_t *, int64_t, uint8_t); +STATIC_INLINE uint8_t get_h48_pval(_Atomic const uint8_t *, int64_t, uint8_t); STATIC_INLINE void set_h48_pval(_Atomic uint8_t *, int64_t, uint8_t, uint8_t); STATIC_INLINE uint8_t get_h48_bound( - cube_t, uint32_t, uint8_t, uint8_t, const uint8_t *); + cube_t, uint32_t, uint8_t, uint8_t, _Atomic const uint8_t *); size_t gendata_h48_derive(uint8_t, const void *, void *); @@ -196,7 +196,7 @@ gendata_h48h0k4(gendata_h48_arg_t *arg) pthread_join(thread[t], NULL); for (i = 0, cc = 0; i < h48max; i++) { - val = get_h48_pval((uint8_t *)table, i, 4); + val = get_h48_pval(table, i, 4); cc += val == d; } @@ -242,7 +242,7 @@ gendata_h48h0k4_runthread(void *arg) * Otherwise, scan all neighbors of unvisited coordinates. */ for (i = bfsarg->start; i < bfsarg->end; i++) { - c = get_h48_pval((uint8_t *)bfsarg->table, i, 4); + c = get_h48_pval(bfsarg->table, i, 4); if ((bfsarg->depth < breakpoint && c != bfsarg->depth - 1) || (bfsarg->depth >= breakpoint && c != 0xF)) @@ -252,7 +252,7 @@ gendata_h48h0k4_runthread(void *arg) for (m = 0; m < 18; m++) { moved = move(cube, m); j = coord_h48(moved, bfsarg->cocsepdata, 0); - c = get_h48_pval((uint8_t *)bfsarg->table, j, 4); + c = get_h48_pval(bfsarg->table, j, 4); if (bfsarg->depth < breakpoint) { if (c <= bfsarg->depth) continue; @@ -356,7 +356,7 @@ gendata_h48k2(gendata_h48_arg_t *arg) h48map_destroy(&shortcubes); for (j = 0; j < H48_COORDMAX(arg->h); j++) { - t = get_h48_pval((uint8_t *)table, j, 2); + t = get_h48_pval(table, j, 2); arg->info.distribution[t]++; } @@ -491,7 +491,7 @@ gendata_h48_mark(gendata_h48_mark_t *arg) FOREACH_H48SIM(arg->cube, arg->cocsepdata, arg->selfsim, coord = coord_h48(arg->cube, arg->cocsepdata, arg->h); - oldval = get_h48_pval((uint8_t *)arg->table, coord, arg->k); + oldval = get_h48_pval(arg->table, coord, arg->k); newval = (uint8_t)MAX(arg->depth, 0); if (newval < oldval) { mutex = H48_INDEX(coord, arg->k) % CHUNKS; @@ -515,7 +515,7 @@ gendata_h48k2_dfs_stop(cube_t cube, int8_t depth, h48k2_dfs_arg_t *arg) coord = coord_h48(cube, arg->cocsepdata, arg->h); mutex = H48_INDEX(coord, arg->k) % CHUNKS; pthread_mutex_lock(arg->table_mutex[mutex]); - oldval = get_h48_pval((uint8_t *)arg->table, coord, arg->k); + oldval = get_h48_pval(arg->table, coord, arg->k); pthread_mutex_unlock(arg->table_mutex[mutex]); return oldval <= depth; } else { @@ -570,7 +570,7 @@ makeinfo_h48k2(gendata_h48_arg_t *arg) STATIC void getdistribution_h48( - const uint8_t *table, + _Atomic const uint8_t *table, uint64_t distr[static INFO_DISTRIBUTION_LEN], uint8_t h, uint8_t k @@ -587,20 +587,20 @@ getdistribution_h48( } } -STATIC const uint32_t * +STATIC _Atomic const uint32_t * get_cocsepdata_constptr(const void *data) { - return (uint32_t *)((char *)data + INFOSIZE); + return (_Atomic uint32_t *)((char *)data + INFOSIZE); } -STATIC const uint8_t * +STATIC _Atomic const uint8_t * get_h48data_constptr(const void *data) { - return (uint8_t *)data + COCSEP_FULLSIZE + INFOSIZE; + return (_Atomic uint8_t *)data + COCSEP_FULLSIZE + INFOSIZE; } STATIC_INLINE uint8_t -get_h48_pval(const uint8_t *table, int64_t i, uint8_t k) +get_h48_pval(_Atomic const uint8_t *table, int64_t i, uint8_t k) { return (table[H48_INDEX(i, k)] & H48_MASK(i, k)) >> H48_SHIFT(i, k); } @@ -618,7 +618,7 @@ get_h48_bound( uint32_t cdata, uint8_t h, uint8_t k, - const uint8_t *table + _Atomic const uint8_t *table ) { int64_t coord; @@ -631,7 +631,7 @@ gendata_h48_derive(uint8_t h, const void *fulltable, void *buf) { size_t cocsepsize, h48size; uint8_t val_full, val_derive; - const uint8_t *h48full; + _Atomic const uint8_t *h48full; _Atomic uint8_t *h48derive; int64_t i, j, h48max; gendata_h48_arg_t arg; @@ -672,7 +672,7 @@ gendata_h48_derive(uint8_t h, const void *fulltable, void *buf) goto gendata_h48_derive_error; } - h48full = (const uint8_t *)fulltable + cocsepsize + INFOSIZE; + h48full = (_Atomic const uint8_t *)fulltable + cocsepsize + INFOSIZE; h48derive = (_Atomic uint8_t *)arg.h48buf + INFOSIZE; memset(h48derive, 0xFF, H48_TABLESIZE(h, arg.k)); memset(arg.info.distribution, 0, @@ -684,13 +684,12 @@ gendata_h48_derive(uint8_t h, const void *fulltable, void *buf) LOG("Processing %" PRId64 "th coordinate\n", i); j = i >> (int64_t)(fulltableinfo.h48h - h); val_full = get_h48_pval(h48full, i, arg.k); - val_derive = get_h48_pval((uint8_t *)h48derive, j, arg.k); + val_derive = get_h48_pval(h48derive, j, arg.k); set_h48_pval( h48derive, j, arg.k, MIN(val_full, val_derive)); } - getdistribution_h48( - (uint8_t *)h48derive, arg.info.distribution, h, arg.k); + getdistribution_h48(h48derive, arg.info.distribution, h, arg.k); if (!writetableinfo(&arg.info, arg.h48buf)) { LOG("gendata_h48_derive: could not write info for table\n"); diff --git a/src/solvers/h48/solve.h b/src/solvers/h48/solve.h @@ -8,8 +8,8 @@ typedef struct { int64_t maxsolutions; uint8_t h; uint8_t k; - const uint32_t *cocsepdata; - const uint8_t *h48data; + _Atomic const uint32_t *cocsepdata; + _Atomic const uint8_t *h48data; char **nextsol; uint8_t nissbranch; int8_t npremoves; diff --git a/src/solvers/h48/stats.h b/src/solvers/h48/stats.h @@ -10,8 +10,8 @@ typedef struct { int8_t nmoves; int8_t depth; uint8_t moves[MAXLEN]; - const uint32_t *cocsepdata; - const uint8_t *h48data; + _Atomic const uint32_t *cocsepdata; + _Atomic const uint8_t *h48data; char *s; } dfsarg_solveh48stats_t;