slab + nft[slab.objects] + object[slab.objects]
구조로 구성됩니다.
[PNG image (5.99 KB)] |
[PNG image (26.24 KB)] |
/* Copyright (C) JAEHYUK CHO All rights reserved. Code by JaeHyuk Cho <mailto:minzkn@minzkn.com> */ /* object index의 단위를 나타내는 변수형입니다. object수가 65536이상인 경우 이것은 좀 키워야 겠죠. */ typedef unsigned short int __mzslab_index_t; #define mzslab_index_t __mzslab_index_t #pragma pack(push,8) typedef struct mzslab_ts { /* object 의 크기를 나타냅니다. */ size_t object_size; /* object 수를 나타냅니다. */ size_t objects; /* 첫 object 의 포인터입니다. 이 또한 런타임에 계산 가능하지만 미리... */ unsigned char *entry; /* 첫번째 해제된 Object 의 index를 저장합니다. 만약 이 값이 objects보다 같거나 크게 되면 할당가능한 object가 없게 됩니다. */ mzslab_index_t f; }__mzslab_t; #define mzslab_t __mzslab_t #pragma pack(pop)
mzslab_t * mzslab_init(void *s_page, size_t s_page_size, size_t s_object_size) { size_t s_index; mzslab_t *s_slab; mzslab_index_t *s_nft; /* next free table */ /* page의 첫 선두부분을 slab구조저장영역으로 사용합니다. */ s_slab = (mzslab_t *)s_page; /* 하나의 object가 가지는 유닛의 크기를 저장해둡니다. */ s_slab->object_size = s_object_size; /* 여러가지 page의 크기에 따른 적절한 object수를 산출하기 위해서 slab index영역을 고려한 산출loop를 사용합니다. */ s_slab->objects = (s_page_size - sizeof(mzslab_t)) / s_object_size; while((s_slab->objects > ((size_t)0)) && ((s_page_size - sizeof(mzslab_t)) < ((s_slab->objects * s_object_size) + (s_slab->objects * sizeof(mzslab_index_t))))) { s_slab->objects--; } if(s_slab->objects <= ((size_t)0)) { /* object를 담기에 불가능한 크기인 경우 slab은 초기화 할수 없습니다. */ return((mzslab_t *)0); } /* 첫 object를 가르키는 포인터를 저장해둡니다. */ s_slab->entry = ((unsigned char *)(&s_slab[1])) + (s_slab->objects * sizeof(mzslab_index_t)); /* 할당되지 않은 object의 첫번째 index를 저장합니다. */ s_slab->f = (mzslab_index_t)0u; /* 해제된 메모리로 표현하기 위하여 index를 초기화 합니다. */ s_nft = (mzslab_index_t *)(&s_slab[1]); for(s_index = ((size_t)0u);s_index < s_slab->objects;s_index++) { s_nft[s_index] = s_index + ((size_t)1u); } return(s_slab); }가장 먼저 Free object block index (s_slab->f)를 0으로 초기화 하고 Slab index table (s_nftn = n + 1)을 순차적으로 그 다음값으로 초기화 하여 Slab을 사용하기 위한 초기화 동작을 완료합니다.
void * mzslab_alloc(mzslab_t *s_slab) { mzslab_index_t *s_nft = (mzslab_index_t *)(&s_slab[1]); void *s_result; if(s_slab->f >= s_slab->objects) { /* 이 경우 메모리에 할당가능한 object가 없다고 판단하면 되겠습니다. */ s_result = (void *)0; } else { /* 할당가능한 object가 있으므로 이를 반환합니다. */ s_result = (void *)(&s_slab->entry[s_slab->f * s_slab->object_size]); s_slab->f = s_nft[s_slab->f]; } return(s_result); }할당가능한 Free object block index (s_slab->f)에 대응하는 Free object block의 메모리주소 (&s_slab->entry...)를 반환후 s_slab->f가 가르키는 Slab index table (s_nfts_slab->f)에서 가르키는 다음 Free object block index를 s_slab->f로 취하여 할당이 완료되게 됩니다.
/* 원래 s_slab은 전역 cache테이블로 감추고 s_ptr만으로 추출할수 있도록 구현하는게 바람직하지만 현재 예제를 들기 위한 부분이기에 그냥 인자로 넘겨 받도록 하여 소개합니다. */ void * mzslab_free(mzslab_t *s_slab, void *s_ptr) { mzslab_index_t *s_nft = (mzslab_index_t *)(&s_slab[1]); size_t s_index; s_index = (size_t)(((unsigned char *)s_ptr) - s_slab->entry) / s_slab->object_size; s_nft[s_index] = s_slab->f; s_slab->f = s_index; return((void *)0); }할당된 Object block memory 주소 (s_ptr)로부터 해당하는 Object block index (s_index)를 취하고 해당 Object block index의 Slab index table (s_ntfs_index)에 현재 할당 가능한 Freee object block index (s_slab->f)를 저장하고 Object block index (s_index)를 Free object block index (s_slab->f)에 저장하여 해제동작이 완료됩니다.