util/interval-tree: Access left/right/parent atomically
accel/tcg: Clear gen_tb on buffer overflow bsd-user: Specify host page alignment if none specified bsd-user: Allocate guest virtual address space target/ppc: Disable goto_tb with architectural singlestep target/s390x: Move trans_exc_code update to do_program_interrupt -----BEGIN PGP SIGNATURE----- iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmTIIQUdHHJpY2hhcmQu aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV87JAf/ZgJTq26oniJ4TLkS 2UVBEcxGnnA2L1n4zcXG1o0onT5dAqm/6YjSlVD7C+Ol8pzQMomJKcWLL/jrCEUp rQXPV9ibD5bCtO47MY3ZS3aW3pqOhXOeKUFer1+YHWRRyi9Y6kEx0d2No3MSGo18 S5A6zPwqduQvZPBPVualmtdIrpTasxhUdNfbqBW31pxYpCNg1wqIiwKoLcD5NJeX epVhaUi/7TwqljrK7SGXmmfDWiTHIXDtvPrJQcSYGgqpVNFzRuq6jTXRJObeWen0 DhOHqC0Z6OkZ2gU+eso/VRbcbawQNQohUHQzZ7c0643TxncPDKG82/MDRe2MTJnq /z+jpw== =Z8UY -----END PGP SIGNATURE----- Merge tag 'pull-tcg-20230731' of https://gitlab.com/rth7680/qemu into staging util/interval-tree: Access left/right/parent atomically accel/tcg: Clear gen_tb on buffer overflow bsd-user: Specify host page alignment if none specified bsd-user: Allocate guest virtual address space target/ppc: Disable goto_tb with architectural singlestep target/s390x: Move trans_exc_code update to do_program_interrupt # -----BEGIN PGP SIGNATURE----- # # iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmTIIQUdHHJpY2hhcmQu # aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV87JAf/ZgJTq26oniJ4TLkS # 2UVBEcxGnnA2L1n4zcXG1o0onT5dAqm/6YjSlVD7C+Ol8pzQMomJKcWLL/jrCEUp # rQXPV9ibD5bCtO47MY3ZS3aW3pqOhXOeKUFer1+YHWRRyi9Y6kEx0d2No3MSGo18 # S5A6zPwqduQvZPBPVualmtdIrpTasxhUdNfbqBW31pxYpCNg1wqIiwKoLcD5NJeX # epVhaUi/7TwqljrK7SGXmmfDWiTHIXDtvPrJQcSYGgqpVNFzRuq6jTXRJObeWen0 # DhOHqC0Z6OkZ2gU+eso/VRbcbawQNQohUHQzZ7c0643TxncPDKG82/MDRe2MTJnq # /z+jpw== # =Z8UY # -----END PGP SIGNATURE----- # gpg: Signature made Mon 31 Jul 2023 02:00:53 PM PDT # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [ultimate] * tag 'pull-tcg-20230731' of https://gitlab.com/rth7680/qemu: target/s390x: Move trans_exc_code update to do_program_interrupt linux-user/armeb: Fix __kernel_cmpxchg() for armeb target/ppc: Disable goto_tb with architectural singlestep bsd-user: Specify host page alignment if none specified bsd-user: Allocate guest virtual address space accel/tcg: Clear tcg_ctx->gen_tb on buffer overflow util/interval-tree: Use qatomic_read/set for rb_parent_color util/interval-tree: Introduce pc_parent util/interval-tree: Use qatomic_set_mb in rb_link_node util/interval-tree: Use qatomic_read for left/right while searching Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
802341823f
@ -374,6 +374,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
|||||||
"Restarting code generation for "
|
"Restarting code generation for "
|
||||||
"code_gen_buffer overflow\n");
|
"code_gen_buffer overflow\n");
|
||||||
tb_unlock_pages(tb);
|
tb_unlock_pages(tb);
|
||||||
|
tcg_ctx->gen_tb = NULL;
|
||||||
goto buffer_overflow;
|
goto buffer_overflow;
|
||||||
|
|
||||||
case -2:
|
case -2:
|
||||||
|
@ -473,10 +473,6 @@ int main(int argc, char **argv)
|
|||||||
target_environ = envlist_to_environ(envlist, NULL);
|
target_environ = envlist_to_environ(envlist, NULL);
|
||||||
envlist_free(envlist);
|
envlist_free(envlist);
|
||||||
|
|
||||||
if (reserved_va) {
|
|
||||||
mmap_next_start = reserved_va + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
if (seed_optarg != NULL) {
|
if (seed_optarg != NULL) {
|
||||||
@ -494,7 +490,49 @@ int main(int argc, char **argv)
|
|||||||
* Now that page sizes are configured we can do
|
* Now that page sizes are configured we can do
|
||||||
* proper page alignment for guest_base.
|
* proper page alignment for guest_base.
|
||||||
*/
|
*/
|
||||||
guest_base = HOST_PAGE_ALIGN(guest_base);
|
if (have_guest_base) {
|
||||||
|
if (guest_base & ~qemu_host_page_mask) {
|
||||||
|
error_report("Selected guest base not host page aligned");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If reserving host virtual address space, do so now.
|
||||||
|
* Combined with '-B', ensure that the chosen range is free.
|
||||||
|
*/
|
||||||
|
if (reserved_va) {
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
if (have_guest_base) {
|
||||||
|
p = mmap((void *)guest_base, reserved_va + 1, PROT_NONE,
|
||||||
|
MAP_ANON | MAP_PRIVATE | MAP_FIXED | MAP_EXCL, -1, 0);
|
||||||
|
} else {
|
||||||
|
p = mmap(NULL, reserved_va + 1, PROT_NONE,
|
||||||
|
MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||||
|
}
|
||||||
|
if (p == MAP_FAILED) {
|
||||||
|
const char *err = strerror(errno);
|
||||||
|
char *sz = size_to_str(reserved_va + 1);
|
||||||
|
|
||||||
|
if (have_guest_base) {
|
||||||
|
error_report("Cannot allocate %s bytes at -B %p for guest "
|
||||||
|
"address space: %s", sz, (void *)guest_base, err);
|
||||||
|
} else {
|
||||||
|
error_report("Cannot allocate %s bytes for guest "
|
||||||
|
"address space: %s", sz, err);
|
||||||
|
}
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
guest_base = (uintptr_t)p;
|
||||||
|
have_guest_base = true;
|
||||||
|
|
||||||
|
/* Ensure that mmap_next_start is within range. */
|
||||||
|
if (reserved_va <= mmap_next_start) {
|
||||||
|
mmap_next_start = (reserved_va / 4 * 3)
|
||||||
|
& TARGET_PAGE_MASK & qemu_host_page_mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (loader_exec(filename, argv + optind, target_environ, regs, info,
|
if (loader_exec(filename, argv + optind, target_environ, regs, info,
|
||||||
&bprm) != 0) {
|
&bprm) != 0) {
|
||||||
|
@ -260,7 +260,8 @@ static abi_ulong mmap_find_vma_aligned(abi_ulong start, abi_ulong size,
|
|||||||
|
|
||||||
if (reserved_va) {
|
if (reserved_va) {
|
||||||
return mmap_find_vma_reserved(start, size,
|
return mmap_find_vma_reserved(start, size,
|
||||||
(alignment != 0 ? 1 << alignment : 0));
|
(alignment != 0 ? 1 << alignment :
|
||||||
|
MAX(qemu_host_page_size, TARGET_PAGE_SIZE)));
|
||||||
}
|
}
|
||||||
|
|
||||||
addr = start;
|
addr = start;
|
||||||
|
@ -117,8 +117,9 @@ static void arm_kernel_cmpxchg32_helper(CPUARMState *env)
|
|||||||
{
|
{
|
||||||
uint32_t oldval, newval, val, addr, cpsr, *host_addr;
|
uint32_t oldval, newval, val, addr, cpsr, *host_addr;
|
||||||
|
|
||||||
oldval = env->regs[0];
|
/* Swap if host != guest endianness, for the host cmpxchg below */
|
||||||
newval = env->regs[1];
|
oldval = tswap32(env->regs[0]);
|
||||||
|
newval = tswap32(env->regs[1]);
|
||||||
addr = env->regs[2];
|
addr = env->regs[2];
|
||||||
|
|
||||||
mmap_lock();
|
mmap_lock();
|
||||||
@ -174,6 +175,10 @@ static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Swap if host != guest endianness, for the host cmpxchg below */
|
||||||
|
oldval = tswap64(oldval);
|
||||||
|
newval = tswap64(newval);
|
||||||
|
|
||||||
#ifdef CONFIG_ATOMIC64
|
#ifdef CONFIG_ATOMIC64
|
||||||
val = qatomic_cmpxchg__nocheck(host_addr, oldval, newval);
|
val = qatomic_cmpxchg__nocheck(host_addr, oldval, newval);
|
||||||
cpsr = (val == oldval) * CPSR_C;
|
cpsr = (val == oldval) * CPSR_C;
|
||||||
|
@ -4175,6 +4175,9 @@ static void pmu_count_insns(DisasContext *ctx)
|
|||||||
|
|
||||||
static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
|
static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
|
||||||
{
|
{
|
||||||
|
if (unlikely(ctx->singlestep_enabled)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return translator_use_goto_tb(&ctx->base, dest);
|
return translator_use_goto_tb(&ctx->base, dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,11 +190,6 @@ bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (excp != PGM_ADDRESSING) {
|
|
||||||
stq_phys(env_cpu(env)->as,
|
|
||||||
env->psa + offsetof(LowCore, trans_exc_code), tec);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For data accesses, ILEN will be filled in from the unwind info,
|
* For data accesses, ILEN will be filled in from the unwind info,
|
||||||
* within cpu_loop_exit_restore. For code accesses, retaddr == 0,
|
* within cpu_loop_exit_restore. For code accesses, retaddr == 0,
|
||||||
@ -211,20 +206,33 @@ static void do_program_interrupt(CPUS390XState *env)
|
|||||||
uint64_t mask, addr;
|
uint64_t mask, addr;
|
||||||
LowCore *lowcore;
|
LowCore *lowcore;
|
||||||
int ilen = env->int_pgm_ilen;
|
int ilen = env->int_pgm_ilen;
|
||||||
|
bool set_trans_exc_code = false;
|
||||||
|
bool advance = false;
|
||||||
|
|
||||||
assert((env->int_pgm_code == PGM_SPECIFICATION && ilen == 0) ||
|
assert((env->int_pgm_code == PGM_SPECIFICATION && ilen == 0) ||
|
||||||
ilen == 2 || ilen == 4 || ilen == 6);
|
ilen == 2 || ilen == 4 || ilen == 6);
|
||||||
|
|
||||||
switch (env->int_pgm_code) {
|
switch (env->int_pgm_code) {
|
||||||
case PGM_PER:
|
case PGM_PER:
|
||||||
if (env->per_perc_atmid & PER_CODE_EVENT_NULLIFICATION) {
|
advance = !(env->per_perc_atmid & PER_CODE_EVENT_NULLIFICATION);
|
||||||
break;
|
break;
|
||||||
}
|
case PGM_ASCE_TYPE:
|
||||||
/* FALL THROUGH */
|
case PGM_REG_FIRST_TRANS:
|
||||||
|
case PGM_REG_SEC_TRANS:
|
||||||
|
case PGM_REG_THIRD_TRANS:
|
||||||
|
case PGM_SEGMENT_TRANS:
|
||||||
|
case PGM_PAGE_TRANS:
|
||||||
|
assert(env->int_pgm_code == env->tlb_fill_exc);
|
||||||
|
set_trans_exc_code = true;
|
||||||
|
break;
|
||||||
|
case PGM_PROTECTION:
|
||||||
|
assert(env->int_pgm_code == env->tlb_fill_exc);
|
||||||
|
set_trans_exc_code = true;
|
||||||
|
advance = true;
|
||||||
|
break;
|
||||||
case PGM_OPERATION:
|
case PGM_OPERATION:
|
||||||
case PGM_PRIVILEGED:
|
case PGM_PRIVILEGED:
|
||||||
case PGM_EXECUTE:
|
case PGM_EXECUTE:
|
||||||
case PGM_PROTECTION:
|
|
||||||
case PGM_ADDRESSING:
|
case PGM_ADDRESSING:
|
||||||
case PGM_SPECIFICATION:
|
case PGM_SPECIFICATION:
|
||||||
case PGM_DATA:
|
case PGM_DATA:
|
||||||
@ -243,11 +251,15 @@ static void do_program_interrupt(CPUS390XState *env)
|
|||||||
case PGM_PC_TRANS_SPEC:
|
case PGM_PC_TRANS_SPEC:
|
||||||
case PGM_ALET_SPEC:
|
case PGM_ALET_SPEC:
|
||||||
case PGM_MONITOR:
|
case PGM_MONITOR:
|
||||||
/* advance the PSW if our exception is not nullifying */
|
advance = true;
|
||||||
env->psw.addr += ilen;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* advance the PSW if our exception is not nullifying */
|
||||||
|
if (advance) {
|
||||||
|
env->psw.addr += ilen;
|
||||||
|
}
|
||||||
|
|
||||||
qemu_log_mask(CPU_LOG_INT,
|
qemu_log_mask(CPU_LOG_INT,
|
||||||
"%s: code=0x%x ilen=%d psw: %" PRIx64 " %" PRIx64 "\n",
|
"%s: code=0x%x ilen=%d psw: %" PRIx64 " %" PRIx64 "\n",
|
||||||
__func__, env->int_pgm_code, ilen, env->psw.mask,
|
__func__, env->int_pgm_code, ilen, env->psw.mask,
|
||||||
@ -263,6 +275,10 @@ static void do_program_interrupt(CPUS390XState *env)
|
|||||||
env->per_perc_atmid = 0;
|
env->per_perc_atmid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (set_trans_exc_code) {
|
||||||
|
lowcore->trans_exc_code = cpu_to_be64(env->tlb_fill_tec);
|
||||||
|
}
|
||||||
|
|
||||||
lowcore->pgm_ilen = cpu_to_be16(ilen);
|
lowcore->pgm_ilen = cpu_to_be16(ilen);
|
||||||
lowcore->pgm_code = cpu_to_be16(env->int_pgm_code);
|
lowcore->pgm_code = cpu_to_be16(env->int_pgm_code);
|
||||||
lowcore->program_old_psw.mask = cpu_to_be64(s390_cpu_get_psw_mask(env));
|
lowcore->program_old_psw.mask = cpu_to_be64(s390_cpu_get_psw_mask(env));
|
||||||
|
@ -48,12 +48,6 @@
|
|||||||
*
|
*
|
||||||
* It also guarantees that if the lookup returns an element it is the 'correct'
|
* It also guarantees that if the lookup returns an element it is the 'correct'
|
||||||
* one. But not returning an element does _NOT_ mean it's not present.
|
* one. But not returning an element does _NOT_ mean it's not present.
|
||||||
*
|
|
||||||
* NOTE:
|
|
||||||
*
|
|
||||||
* Stores to __rb_parent_color are not important for simple lookups so those
|
|
||||||
* are left undone as of now. Nor did I check for loops involving parent
|
|
||||||
* pointers.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef enum RBColor
|
typedef enum RBColor
|
||||||
@ -68,14 +62,29 @@ typedef struct RBAugmentCallbacks {
|
|||||||
void (*rotate)(RBNode *old, RBNode *new);
|
void (*rotate)(RBNode *old, RBNode *new);
|
||||||
} RBAugmentCallbacks;
|
} RBAugmentCallbacks;
|
||||||
|
|
||||||
|
static inline uintptr_t rb_pc(const RBNode *n)
|
||||||
|
{
|
||||||
|
return qatomic_read(&n->rb_parent_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void rb_set_pc(RBNode *n, uintptr_t pc)
|
||||||
|
{
|
||||||
|
qatomic_set(&n->rb_parent_color, pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline RBNode *pc_parent(uintptr_t pc)
|
||||||
|
{
|
||||||
|
return (RBNode *)(pc & ~1);
|
||||||
|
}
|
||||||
|
|
||||||
static inline RBNode *rb_parent(const RBNode *n)
|
static inline RBNode *rb_parent(const RBNode *n)
|
||||||
{
|
{
|
||||||
return (RBNode *)(n->rb_parent_color & ~1);
|
return pc_parent(rb_pc(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline RBNode *rb_red_parent(const RBNode *n)
|
static inline RBNode *rb_red_parent(const RBNode *n)
|
||||||
{
|
{
|
||||||
return (RBNode *)n->rb_parent_color;
|
return (RBNode *)rb_pc(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline RBColor pc_color(uintptr_t pc)
|
static inline RBColor pc_color(uintptr_t pc)
|
||||||
@ -95,27 +104,27 @@ static inline bool pc_is_black(uintptr_t pc)
|
|||||||
|
|
||||||
static inline RBColor rb_color(const RBNode *n)
|
static inline RBColor rb_color(const RBNode *n)
|
||||||
{
|
{
|
||||||
return pc_color(n->rb_parent_color);
|
return pc_color(rb_pc(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool rb_is_red(const RBNode *n)
|
static inline bool rb_is_red(const RBNode *n)
|
||||||
{
|
{
|
||||||
return pc_is_red(n->rb_parent_color);
|
return pc_is_red(rb_pc(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool rb_is_black(const RBNode *n)
|
static inline bool rb_is_black(const RBNode *n)
|
||||||
{
|
{
|
||||||
return pc_is_black(n->rb_parent_color);
|
return pc_is_black(rb_pc(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void rb_set_black(RBNode *n)
|
static inline void rb_set_black(RBNode *n)
|
||||||
{
|
{
|
||||||
n->rb_parent_color |= RB_BLACK;
|
rb_set_pc(n, rb_pc(n) | RB_BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void rb_set_parent_color(RBNode *n, RBNode *p, RBColor color)
|
static inline void rb_set_parent_color(RBNode *n, RBNode *p, RBColor color)
|
||||||
{
|
{
|
||||||
n->rb_parent_color = (uintptr_t)p | color;
|
rb_set_pc(n, (uintptr_t)p | color);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void rb_set_parent(RBNode *n, RBNode *p)
|
static inline void rb_set_parent(RBNode *n, RBNode *p)
|
||||||
@ -128,7 +137,11 @@ static inline void rb_link_node(RBNode *node, RBNode *parent, RBNode **rb_link)
|
|||||||
node->rb_parent_color = (uintptr_t)parent;
|
node->rb_parent_color = (uintptr_t)parent;
|
||||||
node->rb_left = node->rb_right = NULL;
|
node->rb_left = node->rb_right = NULL;
|
||||||
|
|
||||||
qatomic_set(rb_link, node);
|
/*
|
||||||
|
* Ensure that node is initialized before insertion,
|
||||||
|
* as viewed by a concurrent search.
|
||||||
|
*/
|
||||||
|
qatomic_set_mb(rb_link, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RBNode *rb_next(RBNode *node)
|
static RBNode *rb_next(RBNode *node)
|
||||||
@ -177,9 +190,10 @@ static inline void rb_change_child(RBNode *old, RBNode *new,
|
|||||||
static inline void rb_rotate_set_parents(RBNode *old, RBNode *new,
|
static inline void rb_rotate_set_parents(RBNode *old, RBNode *new,
|
||||||
RBRoot *root, RBColor color)
|
RBRoot *root, RBColor color)
|
||||||
{
|
{
|
||||||
RBNode *parent = rb_parent(old);
|
uintptr_t pc = rb_pc(old);
|
||||||
|
RBNode *parent = pc_parent(pc);
|
||||||
|
|
||||||
new->rb_parent_color = old->rb_parent_color;
|
rb_set_pc(new, pc);
|
||||||
rb_set_parent_color(old, new, color);
|
rb_set_parent_color(old, new, color);
|
||||||
rb_change_child(old, new, parent, root);
|
rb_change_child(old, new, parent, root);
|
||||||
}
|
}
|
||||||
@ -527,11 +541,11 @@ static void rb_erase_augmented(RBNode *node, RBRoot *root,
|
|||||||
* and node must be black due to 4). We adjust colors locally
|
* and node must be black due to 4). We adjust colors locally
|
||||||
* so as to bypass rb_erase_color() later on.
|
* so as to bypass rb_erase_color() later on.
|
||||||
*/
|
*/
|
||||||
pc = node->rb_parent_color;
|
pc = rb_pc(node);
|
||||||
parent = rb_parent(node);
|
parent = pc_parent(pc);
|
||||||
rb_change_child(node, child, parent, root);
|
rb_change_child(node, child, parent, root);
|
||||||
if (child) {
|
if (child) {
|
||||||
child->rb_parent_color = pc;
|
rb_set_pc(child, pc);
|
||||||
rebalance = NULL;
|
rebalance = NULL;
|
||||||
} else {
|
} else {
|
||||||
rebalance = pc_is_black(pc) ? parent : NULL;
|
rebalance = pc_is_black(pc) ? parent : NULL;
|
||||||
@ -539,9 +553,9 @@ static void rb_erase_augmented(RBNode *node, RBRoot *root,
|
|||||||
tmp = parent;
|
tmp = parent;
|
||||||
} else if (!child) {
|
} else if (!child) {
|
||||||
/* Still case 1, but this time the child is node->rb_left */
|
/* Still case 1, but this time the child is node->rb_left */
|
||||||
pc = node->rb_parent_color;
|
pc = rb_pc(node);
|
||||||
parent = rb_parent(node);
|
parent = pc_parent(pc);
|
||||||
tmp->rb_parent_color = pc;
|
rb_set_pc(tmp, pc);
|
||||||
rb_change_child(node, tmp, parent, root);
|
rb_change_child(node, tmp, parent, root);
|
||||||
rebalance = NULL;
|
rebalance = NULL;
|
||||||
tmp = parent;
|
tmp = parent;
|
||||||
@ -595,8 +609,8 @@ static void rb_erase_augmented(RBNode *node, RBRoot *root,
|
|||||||
qatomic_set(&successor->rb_left, tmp);
|
qatomic_set(&successor->rb_left, tmp);
|
||||||
rb_set_parent(tmp, successor);
|
rb_set_parent(tmp, successor);
|
||||||
|
|
||||||
pc = node->rb_parent_color;
|
pc = rb_pc(node);
|
||||||
tmp = rb_parent(node);
|
tmp = pc_parent(pc);
|
||||||
rb_change_child(node, successor, tmp, root);
|
rb_change_child(node, successor, tmp, root);
|
||||||
|
|
||||||
if (child2) {
|
if (child2) {
|
||||||
@ -605,7 +619,7 @@ static void rb_erase_augmented(RBNode *node, RBRoot *root,
|
|||||||
} else {
|
} else {
|
||||||
rebalance = rb_is_black(successor) ? parent : NULL;
|
rebalance = rb_is_black(successor) ? parent : NULL;
|
||||||
}
|
}
|
||||||
successor->rb_parent_color = pc;
|
rb_set_pc(successor, pc);
|
||||||
tmp = successor;
|
tmp = successor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -745,8 +759,9 @@ static IntervalTreeNode *interval_tree_subtree_search(IntervalTreeNode *node,
|
|||||||
* Loop invariant: start <= node->subtree_last
|
* Loop invariant: start <= node->subtree_last
|
||||||
* (Cond2 is satisfied by one of the subtree nodes)
|
* (Cond2 is satisfied by one of the subtree nodes)
|
||||||
*/
|
*/
|
||||||
if (node->rb.rb_left) {
|
RBNode *tmp = qatomic_read(&node->rb.rb_left);
|
||||||
IntervalTreeNode *left = rb_to_itree(node->rb.rb_left);
|
if (tmp) {
|
||||||
|
IntervalTreeNode *left = rb_to_itree(tmp);
|
||||||
|
|
||||||
if (start <= left->subtree_last) {
|
if (start <= left->subtree_last) {
|
||||||
/*
|
/*
|
||||||
@ -765,8 +780,9 @@ static IntervalTreeNode *interval_tree_subtree_search(IntervalTreeNode *node,
|
|||||||
if (start <= node->last) { /* Cond2 */
|
if (start <= node->last) { /* Cond2 */
|
||||||
return node; /* node is leftmost match */
|
return node; /* node is leftmost match */
|
||||||
}
|
}
|
||||||
if (node->rb.rb_right) {
|
tmp = qatomic_read(&node->rb.rb_right);
|
||||||
node = rb_to_itree(node->rb.rb_right);
|
if (tmp) {
|
||||||
|
node = rb_to_itree(tmp);
|
||||||
if (start <= node->subtree_last) {
|
if (start <= node->subtree_last) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -814,8 +830,9 @@ IntervalTreeNode *interval_tree_iter_first(IntervalTreeRoot *root,
|
|||||||
IntervalTreeNode *interval_tree_iter_next(IntervalTreeNode *node,
|
IntervalTreeNode *interval_tree_iter_next(IntervalTreeNode *node,
|
||||||
uint64_t start, uint64_t last)
|
uint64_t start, uint64_t last)
|
||||||
{
|
{
|
||||||
RBNode *rb = node->rb.rb_right, *prev;
|
RBNode *rb, *prev;
|
||||||
|
|
||||||
|
rb = qatomic_read(&node->rb.rb_right);
|
||||||
while (true) {
|
while (true) {
|
||||||
/*
|
/*
|
||||||
* Loop invariants:
|
* Loop invariants:
|
||||||
@ -840,7 +857,7 @@ IntervalTreeNode *interval_tree_iter_next(IntervalTreeNode *node,
|
|||||||
}
|
}
|
||||||
prev = &node->rb;
|
prev = &node->rb;
|
||||||
node = rb_to_itree(rb);
|
node = rb_to_itree(rb);
|
||||||
rb = node->rb.rb_right;
|
rb = qatomic_read(&node->rb.rb_right);
|
||||||
} while (prev == rb);
|
} while (prev == rb);
|
||||||
|
|
||||||
/* Check if the node intersects [start;last] */
|
/* Check if the node intersects [start;last] */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user