More Related Content
Similar to Magic Ring Buffer
Similar to Magic Ring Buffer (20)
More from Takeshi Fujiwara
More from Takeshi Fujiwara (6)
Magic Ring Buffer
- 3. Documents
codezine
2008 : JPEGを散歩する(色の世界, 人間の特性を生かした色表現)
http://codezine.jp/article/detail/3749
slideshare
2009 : 身の回りの圧縮
2009 : 色を認識する仕組み&色空間
2009 : スケジューラから見たOSの話
http://www.slideshare.net/urakarin
社内 (BUG-LAPIN 左の社内ゼミメニュー)
H.264, JPEGほか
http://zeppeli.bug.co.jp/xoops/
- 11. First In First Out (FIFO)
Queue, Pipe
First In Last Out (FILO)
Stack
What is FIFO ?
- 12. First In First Out (FIFO)
Queue, Pipe
First In Last Out (FILO)
Stack
What is FIFO ?
- 46. iPhone5
0x0000 0000
0x0000 2000
0x2F00 4000
0x8000 2000 0x2F00 4000
0x4000 2000 0x0000 2000
... ...
仮想アドレス→物理アドレス変換
0xFFFF FFFF
0x0000 0000
0x4000 2000
0x8000 2000
Memory Management Unit
MMUの持つ機能のうちの
一つがアドレス変換
- 47. 0x8000 2000 0x2000 0000
... ...
0x8000 20000x8000 2000
0x8000 2000 0x2F00 4000
... ...
0x2000 0000
0x2F00 4000
別アプリから同じアドレスを指定されても混ざらない!
(他のアプリの仮想アドレス空間にはアクセスできない)
MMUのすごいところ 1
- 48. 0x4000 2000 0x0000 2000
... ...
0x4000 2000 0x0000 2000
... ...
同じ物理アドレスを指すことで共有ができる!
0x4000 2000 0x4000 2000
0x0000 2000
MMUのすごいところ 2
- 49. 0x4000 2000 0x0000 2000
... ...
0x4000 2000 0x0000 2000
... ...
同じ物理アドレスを指すことで共有ができる!
0x4000 2000 0x4000 2000
0x0000 2000
MMUのすごいところ 2
共有ライブラリ、共有メモリ
- 50. 0x8000 2000 0x2F00 4000
... ...
0x8000 2000 0x2F00 4000
... ...
MMUのすごいところ 3
0x8000 2000
0x2F00 4000
0x2000 00000x8000 2000 0x2000 0000
... ...
fork (プロセス複製) .. iOSではできないけど..
write
大きなメモリ領域をコピーするときに、コピーしたように
見せて、実は書込みがあるまでコピーしない。
= COW (Copy On Write)
仮想アドレスは用意されるが、実体
(物理メモリ)は確保されない
fork
k
write
- 51. MMUのすごいところ 4
0x8000 2000
0x2000 0000
callocしたときに0 fillしたように見せて実はしていない
k
0x1000 0000
仮想メモリ 物理メモリ
0x8000 3000
0x8000 4000
0x8000 5000
write
calloc直後
write
calloc(4, PAGE_SIZE)
0x8000 2000 0x1000 0000
0x8000 3000 0x1000 0000
0x8000 4000 0x1000 0000
0x8000 5000 0x1000 0000
0x8000 2000 0x2000 0000
0x8000 3000 0x1000 0000
0x8000 4000 0x1000 0000
0x8000 5000 0x1000 0000
あらかじめ用意された
0 fill済みの1 page (4KB)
- 53. MMUのすごいところ 5
Ring Buffer用にMirroring
k
仮想メモリ
0x8000 5000 memory_object4
0x8000 4000 memory_object3
0x8000 3000 memory_object2
0x8000 2000 memory_object1
0x8000 3000 memory_object2
0x8000 2000 memory_object1
0x8000 5000 memory_object2
0x8000 4000 memory_object1
0x8000 3000 memory_object2
0x8000 2000 memory_object1
物理メモリ
物理メモリの予約はとってあ
るが、未割当状態
0x8000 2000
0x8000 4000
? ? ?
- 55. buffer->length = round_page(length); // We need whole page sizes
vm_address_t bufferAddress;
kern_return_t result = vm_allocate(mach_task_self(),
&bufferAddress,
buffer->length * 2,
VM_FLAGS_ANYWHERE); // allocate anywhere it'll fit
result = vm_deallocate(mach_task_self(),
bufferAddress + buffer->length,
buffer->length);
vm_address_t virtualAddress = bufferAddress + buffer->length;
result = vm_remap(mach_task_self(),
&virtualAddress, // mirror target
buffer->length, // size of mirror
...
mach_task_self(), // same task
bufferAddress, // mirror source
... );
https://github.com/michaeltyson/TPCircularBuffer/blob/master/TPCircularBuffer.c
Darwinの場合
- 56. void *ptr = 0;
while (!ptr && num_retries-- != 0)
{
void * target_addr = VirtualAlloc(0, ring_size * 2, MEM_RESERVE, PAGE_NOACCESS);
if (target_addr) {
VirtualFree(target_addr, 0, MEM_RELEASE);
// is ring_size a multiple of 64k? if not, this won't ever work!
if ((ring_size & 0xffff) != 0)
return 0;
// try to allocate and map our space
size_t alloc_size = ring_size * 2;
HANDLE mapping;
if (!(mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE,
(unsigned long long)alloc_size >> 32,
alloc_size & 0xffffffffu, 0)) ||
!(ptr = (char *)MapViewOfFileEx(mapping, FILE_MAP_ALL_ACCESS, 0, 0,
ring_size, target_addr)) ||
!MapViewOfFileEx(mapping, FILE_MAP_ALL_ACCESS, 0, 0,
ring_size, (char *)target_addr + ring_size))
{
// something went wrong - clean up
... UnmapViewOfFile(), CloseHandle()
}
}
}
return ptr;
https://gist.github.com/rygorous/3158316
Windowsの場合
- 57. char path[] = "/dev/shm/ring-buffer-XXXXXX";
int file_descriptor;
void *address;
int status;
file_descriptor = mkstemp (path);
status = unlink (path);
buffer->count_bytes = 1UL << order;
buffer->write_offset_bytes = 0;
buffer->read_offset_bytes = 0;
status = ftruncate (file_descriptor, buffer->count_bytes);
buffer->address = mmap (NULL, buffer->count_bytes << 1, PROT_NONE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
address = mmap (buffer->address,
buffer->count_bytes, PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_SHARED, file_descriptor, 0);
address = mmap (buffer->address + buffer->count_bytes,
buffer->count_bytes, PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_SHARED, file_descriptor, 0);
status = close (file_descriptor);
http://en.wikipedia.org/wiki/Ringbuffer
Linuxの場合