# HG changeset patch # Parent b44b3215a034e0a5850a332ef815f930ad090acb mlv_rec: add SRM buffer usage diff -r b44b3215a034 modules/mlv_rec/mlv_rec.c --- a/modules/mlv_rec/mlv_rec.c Tue Jul 01 10:42:28 2014 +0300 +++ b/modules/mlv_rec/mlv_rec.c Wed Jul 02 21:53:16 2014 +0200 @@ -79,6 +79,8 @@ #include "mlv.h" #include "mlv_rec.h" +extern void SRM_AllocateMemoryResourceFor1stJob(void (*callback)(uint32_t opaque, void* raw_buffer, uint32_t raw_buffer_size), uint32_t opaque); +extern void SRM_FreeMemoryResourceFor1stJob(void* raw_buffer, uint32_t unk1_zero, uint32_t unk2_zero); /* camera-specific tricks */ /* todo: maybe add generic functions like is_digic_v, is_5d2 or stuff like that? */ @@ -181,6 +183,7 @@ static uint64_t mlv_rec_dma_duration = 0; static struct memSuite * mem_suite = 0; /* memory suite for our buffers */ +static volatile job_alloc_t srm_memories[30]; /* job memory buffers */ static void * fullsize_buffers[2]; /* original image, before cropping, double-buffered */ static int32_t fullsize_buffer_pos = 0; /* which of the full size buffers (double buffering) is currently in use */ @@ -843,10 +846,140 @@ } } +void mlv_rec_jobcbr (uint32_t opaque, void *raw_buffer, uint32_t raw_buffer_size) +{ + job_alloc_t *buf = (job_alloc_t *)opaque; + + /* contains a "cheap" semaphore */ + buf->block_size = raw_buffer_size; + buf->block_ptr = raw_buffer; + buf->success = 1; + + trace_write(raw_rec_trace_ctx, "mlv_rec_jobcbr: 0x%08X, size: 0x%08X", raw_buffer, raw_buffer_size); +} + +static void mlv_rec_jobfree(volatile job_alloc_t *buf) +{ + trace_write(raw_rec_trace_ctx, "mlv_rec_jobfree: 0x%08X, size: 0x%08X", buf->block_ptr, buf->block_size); + SRM_FreeMemoryResourceFor1stJob(buf->block_ptr, 0, 0); + + buf->block_ptr = 0; + buf->block_size = 0; + buf->success = 0; +} + +static void mlv_rec_joballoc(volatile job_alloc_t *buf) +{ + buf->success = 0; + SRM_AllocateMemoryResourceFor1stJob(&mlv_rec_jobcbr, (uint32_t)buf); + + uint32_t loops = 0; + while(!buf->success && loops < 5) + { + loops++; + msleep(20); + } +} + +static void mlv_rec_free_srm() +{ + for(int pos = 0; pos < COUNT(srm_memories); pos++) + { + if(srm_memories[pos].success) + { + SRM_FreeMemoryResourceFor1stJob(srm_memories[pos].block_ptr, 0, 0); + srm_memories[pos].success = 0; + } + } +} + +static uint32_t mlv_rec_alloc_srm(uint32_t *total_size) +{ + /* buffers are static to make sure data is not on stack */ + static volatile job_alloc_t backup_memory; + uint32_t buffer_size = 0; + + /* clear status flags */ + for(int pos = 0; pos < COUNT(srm_memories); pos++) + { + srm_memories[pos].success = 0; + } + + /* allocate first buffer as backup to rescue hanging async calls */ + mlv_rec_joballoc(&backup_memory); + + /* interface available, so proceed */ + if(backup_memory.success) + { + uint32_t b_ptr = (uint32_t)backup_memory.block_ptr; + uint32_t b_size = backup_memory.block_size; + + trace_write(raw_rec_trace_ctx, "SRMBuf: 0x%08X, size: 0x%08X (backup)", b_ptr, b_size); + for(int pos = 0; pos < COUNT(srm_memories); pos++) + { + mlv_rec_joballoc(&srm_memories[pos]); + + /* failed! probably reached the maximum buffer count? */ + if(!srm_memories[pos].success) + { + trace_write(raw_rec_trace_ctx, "SRMBuf: alloc #%d failed", pos); + + /* so free the backup memory and wait for the last async call to finish */ + mlv_rec_jobfree(&backup_memory); + + /* dont wait forever */ + uint32_t loops = 0; + while(!srm_memories[pos].success && loops < 5) + { + loops++; + msleep(20); + } + + mlv_rec_joballoc(&srm_memories[pos]); + + /* failed too, so there is smth totally wrong */ + if(!srm_memories[pos].success) + { + trace_write(raw_rec_trace_ctx, "SRMBuf: delayed buffer failed to allocate, exiting"); + + mlv_rec_free_srm(); + return 0; + } + } + + /* retrieve memory address of job buffer */ + uint32_t ptr = (uint32_t)srm_memories[pos].block_ptr; + uint32_t size = srm_memories[pos].block_size; + + trace_write(raw_rec_trace_ctx, "SRMBuf: 0x%08X, size: 0x%08X", ptr, size); + + /* add some protection to detect overwrites */ + setup_prot(&ptr, &size); + check_prot(ptr, size, 0); + + setup_chunk(ptr, size); + buffer_size += size; + + if(!backup_memory.success) + { + break; + } + } + } + else + { + trace_write(raw_rec_trace_ctx, "SRMBuf: not available"); + } + + trace_write(raw_rec_trace_ctx, "SRMBuf: Allocated %d MiB", buffer_size / 1024 / 1024); + *total_size += buffer_size; + + return 1; +} static void free_buffers() { - if (mem_suite) + if(mem_suite) { struct memChunk * chunk = GetFirstChunkFromSuite(mem_suite); @@ -862,11 +995,15 @@ shoot_free_suite(mem_suite); } mem_suite = 0; + + mlv_rec_free_srm(); } static int32_t setup_buffers() { uint32_t total_size = 0; + uint32_t srm_size = 0; + uint32_t exmem_size = 0; slot_count = 0; slot_group_count = 0; @@ -935,6 +1072,11 @@ free_buffers(); return 0; } + + /* experimental: try to allocate from the new job memory */ +#if defined(I_AM_SURE_THAT_I_WANT_TO_TRY_THIS_AS_THIS_IS_TOTALLY_UNTESTED) + mlv_rec_alloc_srm(&srm_size); +#endif trace_write(raw_rec_trace_ctx, "frame size = 0x%X", frame_size); @@ -946,7 +1088,7 @@ uint32_t size = GetSizeOfMemoryChunk(chunk); uint32_t ptr = (uint32_t)GetMemoryAddressOfMemoryChunk(chunk); - trace_write(raw_rec_trace_ctx, "Chunk: 0x%08X, size: 0x%08X", ptr, size); + trace_write(raw_rec_trace_ctx, "Chunk: 0x%08X, size: 0x%08X", ptr, size); /* add some protection to detect overwrites */ setup_prot(&ptr, &size); @@ -960,7 +1102,7 @@ } setup_chunk(ptr, size); - total_size += size; + exmem_size += size; chunk = GetNextMemoryChunk(mem_suite, chunk); } @@ -1056,6 +1198,10 @@ trace_write(raw_rec_trace_ctx, "group: %d length: %d slot: %d", group, slot_groups[group].len, slot_groups[group].slot); } + total_size = srm_size + exmem_size; + + trace_write(raw_rec_trace_ctx, "Memory details: total %d MiB [exmem %d MiB, SRM %d MiB] in %d slots", total_size / 1024 / 1024, exmem_size / 1024 / 1024, srm_size / 1024 / 1024, slot_count); + if(create_dummy) { /* now allocate a dummy file that is going to be released when disk runs full */ diff -r b44b3215a034 modules/mlv_rec/mlv_rec.h --- a/modules/mlv_rec/mlv_rec.h Tue Jul 01 10:42:28 2014 +0300 +++ b/modules/mlv_rec/mlv_rec.h Wed Jul 02 21:53:16 2014 +0200 @@ -84,6 +84,14 @@ int32_t size; }; +/* this struct is for asynchronously allocating a memory block via job memories */ +typedef struct +{ + uint32_t success; + uint32_t block_size; + void *block_ptr; +} job_alloc_t; + /* this job type is Manager -> Writer for telling which blocks to write */ typedef struct {