mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-13 07:32:23 -07:00
143 lines
6.1 KiB
C
143 lines
6.1 KiB
C
// Copyright (c) 2024 Epic Games Tools
|
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Main Layer Initialization
|
|
|
|
internal void
|
|
mtx_init(void)
|
|
{
|
|
Arena *arena = arena_alloc();
|
|
mtx_shared = push_array(arena, MTX_Shared, 1);
|
|
mtx_shared->arena = arena;
|
|
mtx_shared->slots_count = 256;
|
|
mtx_shared->stripes_count = Min(mtx_shared->slots_count, os_get_system_info()->logical_processor_count);
|
|
mtx_shared->slots = push_array(arena, MTX_Slot, mtx_shared->slots_count);
|
|
mtx_shared->stripes = push_array(arena, MTX_Stripe, mtx_shared->stripes_count);
|
|
for(U64 idx = 0; idx < mtx_shared->stripes_count; idx += 1)
|
|
{
|
|
mtx_shared->stripes[idx].arena = arena_alloc();
|
|
mtx_shared->stripes[idx].rw_mutex = os_rw_mutex_alloc();
|
|
}
|
|
mtx_shared->mut_threads_count = Min(os_get_system_info()->logical_processor_count, 4);
|
|
mtx_shared->mut_threads = push_array(arena, MTX_MutThread, mtx_shared->mut_threads_count);
|
|
for(U64 idx = 0; idx < mtx_shared->mut_threads_count; idx += 1)
|
|
{
|
|
mtx_shared->mut_threads[idx].ring_size = KB(64);
|
|
mtx_shared->mut_threads[idx].ring_base = push_array_no_zero(arena, U8, mtx_shared->mut_threads[idx].ring_size);
|
|
mtx_shared->mut_threads[idx].cv = os_condition_variable_alloc();
|
|
mtx_shared->mut_threads[idx].mutex = os_mutex_alloc();
|
|
mtx_shared->mut_threads[idx].thread = os_thread_launch(mtx_mut_thread__entry_point, &mtx_shared->mut_threads[idx], 0);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Buffer Operations
|
|
|
|
internal void
|
|
mtx_push_op(U128 buffer_key, MTX_Op op)
|
|
{
|
|
MTX_MutThread *thread = &mtx_shared->mut_threads[buffer_key.u64[1]%mtx_shared->mut_threads_count];
|
|
mtx_enqueue_op(thread, buffer_key, op);
|
|
}
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Mutation Threads
|
|
|
|
internal void
|
|
mtx_enqueue_op(MTX_MutThread *thread, U128 buffer_key, MTX_Op op)
|
|
{
|
|
// TODO(rjf): if op.replace is too big, need to split into multiple edits
|
|
OS_MutexScope(thread->mutex) for(;;)
|
|
{
|
|
U64 unconsumed_size = thread->ring_write_pos - thread->ring_read_pos;
|
|
U64 available_size = thread->ring_size - unconsumed_size;
|
|
if(available_size >= sizeof(buffer_key) + sizeof(op.range) + sizeof(op.replace.size) + op.replace.size)
|
|
{
|
|
thread->ring_write_pos += ring_write_struct(thread->ring_base, thread->ring_size, thread->ring_write_pos, &buffer_key);
|
|
thread->ring_write_pos += ring_write_struct(thread->ring_base, thread->ring_size, thread->ring_write_pos, &op.range);
|
|
thread->ring_write_pos += ring_write_struct(thread->ring_base, thread->ring_size, thread->ring_write_pos, &op.replace.size);
|
|
thread->ring_write_pos += ring_write(thread->ring_base, thread->ring_size, thread->ring_write_pos, op.replace.str, op.replace.size);
|
|
thread->ring_write_pos += 7;
|
|
thread->ring_write_pos -= thread->ring_write_pos%8;
|
|
break;
|
|
}
|
|
os_condition_variable_wait(thread->cv, thread->mutex, max_U64);
|
|
}
|
|
os_condition_variable_broadcast(thread->cv);
|
|
}
|
|
|
|
internal void
|
|
mtx_dequeue_op(Arena *arena, MTX_MutThread *thread, U128 *buffer_key_out, MTX_Op *op_out)
|
|
{
|
|
OS_MutexScope(thread->mutex) for(;;)
|
|
{
|
|
U64 unconsumed_size = thread->ring_write_pos - thread->ring_read_pos;
|
|
if(unconsumed_size >= sizeof(*buffer_key_out) + sizeof(op_out->range) + sizeof(op_out->replace.size))
|
|
{
|
|
thread->ring_read_pos += ring_read_struct(thread->ring_base, thread->ring_size, thread->ring_read_pos, buffer_key_out);
|
|
thread->ring_read_pos += ring_read_struct(thread->ring_base, thread->ring_size, thread->ring_read_pos, &op_out->range);
|
|
thread->ring_read_pos += ring_read_struct(thread->ring_base, thread->ring_size, thread->ring_read_pos, &op_out->replace.size);
|
|
op_out->replace.str = push_array_no_zero(arena, U8, op_out->replace.size);
|
|
thread->ring_read_pos += ring_read(thread->ring_base, thread->ring_size, thread->ring_read_pos, op_out->replace.str, op_out->replace.size);
|
|
thread->ring_read_pos += 7;
|
|
thread->ring_read_pos -= thread->ring_read_pos%8;
|
|
break;
|
|
}
|
|
os_condition_variable_wait(thread->cv, thread->mutex, max_U64);
|
|
}
|
|
os_condition_variable_broadcast(thread->cv);
|
|
}
|
|
|
|
internal void
|
|
mtx_mut_thread__entry_point(void *p)
|
|
{
|
|
MTX_MutThread *mut_thread = (MTX_MutThread *)p;
|
|
ThreadNameF("[mtx] mut thread #%I64u", (U64)(mut_thread - mtx_shared->mut_threads));
|
|
for(;;)
|
|
{
|
|
Temp scratch = scratch_begin(0, 0);
|
|
HS_Scope *hs_scope = hs_scope_open();
|
|
|
|
//- rjf: get next op
|
|
U128 buffer_key = {0};
|
|
MTX_Op op = {0};
|
|
mtx_dequeue_op(scratch.arena, mut_thread, &buffer_key, &op);
|
|
|
|
//- rjf: get buffer's current data
|
|
U128 hash = hs_hash_from_key(buffer_key, 0);
|
|
String8 data = hs_data_from_hash(hs_scope, hash);
|
|
|
|
//- rjf: clamp op by data
|
|
op.range.min = Min(op.range.min, data.size);
|
|
op.range.max = Min(op.range.max, data.size);
|
|
|
|
//- rjf: construct new buffer
|
|
if(op.range.max != op.range.min || op.replace.size != 0)
|
|
{
|
|
U64 new_data_size = data.size + op.replace.size - dim_1u64(op.range);
|
|
Arena *arena = arena_alloc(.commit_size = new_data_size + ARENA_HEADER_SIZE, .reserve_size = new_data_size + ARENA_HEADER_SIZE);
|
|
U8 *new_data_base = push_array_no_zero(arena, U8, new_data_size);
|
|
String8 pre_replace_data = str8_substr(data, r1u64(0, op.range.min));
|
|
String8 post_replace_data = str8_substr(data, r1u64(op.range.max, data.size));
|
|
if(pre_replace_data.size != 0)
|
|
{
|
|
MemoryCopy(new_data_base+0, pre_replace_data.str, pre_replace_data.size);
|
|
}
|
|
if(op.replace.size != 0)
|
|
{
|
|
MemoryCopy(new_data_base+pre_replace_data.size, op.replace.str, op.replace.size);
|
|
}
|
|
if(post_replace_data.size != 0)
|
|
{
|
|
MemoryCopy(new_data_base+pre_replace_data.size+op.replace.size, post_replace_data.str, post_replace_data.size);
|
|
}
|
|
String8 new_data = str8(new_data_base, new_data_size);
|
|
hs_submit_data(buffer_key, &arena, new_data);
|
|
}
|
|
|
|
hs_scope_close(hs_scope);
|
|
scratch_end(scratch);
|
|
}
|
|
}
|