123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693 |
- #include "slab.h"
- #include <common/compiler.h>
- struct slab kmalloc_cache_group[16] =
- {
- {32, 0, 0, NULL, NULL, NULL, NULL},
- {64, 0, 0, NULL, NULL, NULL, NULL},
- {128, 0, 0, NULL, NULL, NULL, NULL},
- {256, 0, 0, NULL, NULL, NULL, NULL},
- {512, 0, 0, NULL, NULL, NULL, NULL},
- {1024, 0, 0, NULL, NULL, NULL, NULL},
- {2048, 0, 0, NULL, NULL, NULL, NULL},
- {4096, 0, 0, NULL, NULL, NULL, NULL},
- {8192, 0, 0, NULL, NULL, NULL, NULL},
- {16384, 0, 0, NULL, NULL, NULL, NULL},
- {32768, 0, 0, NULL, NULL, NULL, NULL},
- {65536, 0, 0, NULL, NULL, NULL, NULL},
- {131072, 0, 0, NULL, NULL, NULL, NULL},
- {262144, 0, 0, NULL, NULL, NULL, NULL},
- {524288, 0, 0, NULL, NULL, NULL, NULL},
- {1048576, 0, 0, NULL, NULL, NULL, NULL},
- };
- struct slab *slab_create(ul size, void *(*constructor)(void *vaddr, ul arg), void *(*destructor)(void *vaddr, ul arg), ul arg)
- {
- struct slab *slab_pool = (struct slab *)kmalloc(sizeof(struct slab), 0);
-
- if (slab_pool == NULL)
- {
- kBUG("slab_create()->kmalloc()->slab == NULL");
- return NULL;
- }
- memset(slab_pool, 0, sizeof(struct slab));
- slab_pool->size = SIZEOF_LONG_ALIGN(size);
- slab_pool->count_total_using = 0;
- slab_pool->count_total_free = 0;
-
- slab_pool->cache_pool_entry = (struct slab_obj *)kmalloc(sizeof(struct slab_obj), 0);
-
- if (slab_pool->cache_pool_entry == NULL)
- {
- kBUG("slab_create()->kmalloc()->slab->cache_pool_entry == NULL");
- kfree(slab_pool);
- return NULL;
- }
- memset(slab_pool->cache_pool_entry, 0, sizeof(struct slab_obj));
-
- slab_pool->cache_dma_pool_entry = NULL;
-
- slab_pool->constructor = constructor;
- slab_pool->destructor = destructor;
- list_init(&slab_pool->cache_pool_entry->list);
-
- slab_pool->cache_pool_entry->page = alloc_pages(ZONE_NORMAL, 1, PAGE_KERNEL);
-
- if (slab_pool->cache_pool_entry->page == NULL)
- {
- kBUG("slab_create()->kmalloc()->slab->cache_pool_entry == NULL");
- kfree(slab_pool->cache_pool_entry);
- kfree(slab_pool);
- return NULL;
- }
-
- slab_pool->cache_pool_entry->count_using = 0;
- slab_pool->cache_pool_entry->count_free = PAGE_2M_SIZE / slab_pool->size;
- slab_pool->count_total_free = slab_pool->cache_pool_entry->count_free;
- slab_pool->cache_pool_entry->vaddr = phys_2_virt(slab_pool->cache_pool_entry->page->addr_phys);
-
- slab_pool->cache_pool_entry->bmp_count = slab_pool->cache_pool_entry->count_free;
-
- slab_pool->cache_pool_entry->bmp_len = ((slab_pool->cache_pool_entry->bmp_count + sizeof(ul) * 8 - 1) >> 6) << 3;
-
- slab_pool->cache_pool_entry->bmp = (ul *)kmalloc(slab_pool->cache_pool_entry->bmp_len, 0);
-
- if (slab_pool->cache_pool_entry->bmp == NULL)
- {
- kBUG("slab_create()->kmalloc()->slab->cache_pool_entry == NULL");
- free_pages(slab_pool->cache_pool_entry->page, 1);
- kfree(slab_pool->cache_pool_entry);
- kfree(slab_pool);
- return NULL;
- }
-
- memset(slab_pool->cache_pool_entry->bmp, 0, slab_pool->cache_pool_entry->bmp_len);
- return slab_pool;
- }
- ul slab_destroy(struct slab *slab_pool)
- {
- struct slab_obj *slab_obj_ptr = slab_pool->cache_pool_entry;
- if (slab_pool->count_total_using)
- {
- kBUG("slab_cache->count_total_using != 0");
- return ESLAB_NOTNULL;
- }
- struct slab_obj *tmp_slab_obj = NULL;
- while (!list_empty(&slab_obj_ptr->list))
- {
- tmp_slab_obj = slab_obj_ptr;
-
- slab_obj_ptr = container_of(list_next(&slab_obj_ptr->list), struct slab_obj, list);
- list_del(&tmp_slab_obj->list);
- kfree(tmp_slab_obj->bmp);
- page_clean(tmp_slab_obj->page);
- free_pages(tmp_slab_obj->page, 1);
- kfree(tmp_slab_obj);
- }
- kfree(slab_obj_ptr->bmp);
- page_clean(slab_obj_ptr->page);
- free_pages(slab_obj_ptr->page, 1);
- kfree(slab_obj_ptr);
- kfree(slab_pool);
- return 0;
- }
- void *slab_malloc(struct slab *slab_pool, ul arg)
- {
- struct slab_obj *slab_obj_ptr = slab_pool->cache_pool_entry;
- struct slab_obj *tmp_slab_obj = NULL;
-
- if (slab_pool->count_total_free == 0)
- {
- tmp_slab_obj = (struct slab_obj *)kmalloc(sizeof(struct slab_obj), 0);
-
- if (tmp_slab_obj == NULL)
- {
- kBUG("slab_malloc()->kmalloc()->slab->tmp_slab_obj == NULL");
- return NULL;
- }
- memset(tmp_slab_obj, 0, sizeof(struct slab_obj));
- list_init(&tmp_slab_obj->list);
- tmp_slab_obj->page = alloc_pages(ZONE_NORMAL, 1, PAGE_KERNEL);
-
- if (tmp_slab_obj->page == NULL)
- {
- kBUG("slab_malloc()->kmalloc()=>tmp_slab_obj->page == NULL");
- kfree(tmp_slab_obj);
- return NULL;
- }
- tmp_slab_obj->count_using = 0;
- tmp_slab_obj->count_free = PAGE_2M_SIZE / slab_pool->size;
- tmp_slab_obj->vaddr = phys_2_virt(tmp_slab_obj->page->addr_phys);
- tmp_slab_obj->bmp_count = tmp_slab_obj->count_free;
-
- tmp_slab_obj->bmp_len = ((tmp_slab_obj->bmp_count + sizeof(ul) * 8 - 1) >> 6) << 3;
- tmp_slab_obj->bmp = (ul *)kmalloc(tmp_slab_obj->bmp_len, 0);
-
- if (tmp_slab_obj->bmp == NULL)
- {
- kBUG("slab_malloc()->kmalloc()=>tmp_slab_obj->bmp == NULL");
- free_pages(tmp_slab_obj->page, 1);
- kfree(tmp_slab_obj);
- return NULL;
- }
- memset(tmp_slab_obj->bmp, 0, tmp_slab_obj->bmp_len);
- list_add(&slab_pool->cache_pool_entry->list, &tmp_slab_obj->list);
- slab_pool->count_total_free += tmp_slab_obj->count_free;
- slab_obj_ptr = tmp_slab_obj;
- }
-
- int tmp_md;
- do
- {
- if (slab_obj_ptr->count_free == 0)
- {
- slab_obj_ptr = container_of(list_next(&slab_obj_ptr->list), struct slab_obj, list);
- continue;
- }
- for (int i = 0; i < slab_obj_ptr->bmp_count; ++i)
- {
-
- if (*(slab_obj_ptr->bmp + (i >> 6)) == 0xffffffffffffffffUL)
- {
- i += 63;
- continue;
- }
-
- tmp_md = i % 64;
- if ((*(slab_obj_ptr->bmp + (i >> 6)) & (1UL << tmp_md)) == 0)
- {
-
- *(slab_obj_ptr->bmp + (i >> 6)) |= (1UL << tmp_md);
-
- ++(slab_obj_ptr->count_using);
- --(slab_obj_ptr->count_free);
-
- ++(slab_pool->count_total_using);
- --(slab_pool->count_total_free);
- if (slab_pool->constructor != NULL)
- {
-
- return slab_pool->constructor((char *)slab_obj_ptr->vaddr + slab_pool->size * i, arg);
- }
-
- else
- return (void *)((char *)slab_obj_ptr->vaddr + slab_pool->size * i);
- }
- }
- } while (slab_obj_ptr != slab_pool->cache_pool_entry);
-
- kBUG("slab_malloc() ERROR: can't malloc");
-
- if (tmp_slab_obj != NULL)
- {
- list_del(&tmp_slab_obj->list);
- kfree(tmp_slab_obj->bmp);
- page_clean(tmp_slab_obj->page);
- free_pages(tmp_slab_obj->page, 1);
- kfree(tmp_slab_obj);
- }
- return NULL;
- }
- ul slab_free(struct slab *slab_pool, void *addr, ul arg)
- {
- struct slab_obj *slab_obj_ptr = slab_pool->cache_pool_entry;
- do
- {
-
- if (!(slab_obj_ptr->vaddr <= addr && addr <= (slab_obj_ptr->vaddr + PAGE_2M_SIZE)))
- {
- slab_obj_ptr = container_of(list_next(&slab_obj_ptr->list), struct slab_obj, list);
- }
- else
- {
-
- int index = (addr - slab_obj_ptr->vaddr) / slab_pool->size;
-
- *(slab_obj_ptr->bmp + (index >> 6)) ^= (1UL << index % 64);
- ++(slab_obj_ptr->count_free);
- --(slab_obj_ptr->count_using);
- ++(slab_pool->count_total_free);
- --(slab_pool->count_total_using);
-
- if (slab_pool->destructor != NULL)
- slab_pool->destructor((char *)slab_obj_ptr->vaddr + slab_pool->size * index, arg);
-
- if ((slab_obj_ptr->count_using == 0) && ((slab_pool->count_total_free >> 1) >= slab_obj_ptr->count_free) && (slab_obj_ptr != slab_pool->cache_pool_entry))
- {
- list_del(&slab_obj_ptr->list);
- slab_pool->count_total_free -= slab_obj_ptr->count_free;
- kfree(slab_obj_ptr->bmp);
- page_clean(slab_obj_ptr->page);
- free_pages(slab_obj_ptr->page, 1);
- kfree(slab_obj_ptr);
- }
- }
- return 0;
- } while (slab_obj_ptr != slab_pool->cache_pool_entry);
- kwarn("slab_free(): address not in current slab");
- return ENOT_IN_SLAB;
- }
- ul slab_init()
- {
- kinfo("Initializing SLAB...");
-
- ul tmp_addr = memory_management_struct.end_of_struct;
- for (int i = 0; i < 16; ++i)
- {
-
- kmalloc_cache_group[i].cache_pool_entry = (struct slab_obj *)memory_management_struct.end_of_struct;
- memory_management_struct.end_of_struct += sizeof(struct slab_obj) + (sizeof(ul) << 2);
- list_init(&kmalloc_cache_group[i].cache_pool_entry->list);
-
- kmalloc_cache_group[i].cache_pool_entry->count_using = 0;
- kmalloc_cache_group[i].cache_pool_entry->count_free = PAGE_2M_SIZE / kmalloc_cache_group[i].size;
- kmalloc_cache_group[i].cache_pool_entry->bmp_len = (((kmalloc_cache_group[i].cache_pool_entry->count_free + sizeof(ul) * 8 - 1) >> 6) << 3);
- kmalloc_cache_group[i].cache_pool_entry->bmp_count = kmalloc_cache_group[i].cache_pool_entry->count_free;
-
- kmalloc_cache_group[i].cache_pool_entry->bmp = (ul *)memory_management_struct.end_of_struct;
-
- memory_management_struct.end_of_struct = (ul)(memory_management_struct.end_of_struct + kmalloc_cache_group[i].cache_pool_entry->bmp_len + (sizeof(ul) << 2)) & (~(sizeof(ul) - 1));
-
- memset(kmalloc_cache_group[i].cache_pool_entry->bmp, 0xff, kmalloc_cache_group[i].cache_pool_entry->bmp_len);
- for (int j = 0; j < kmalloc_cache_group[i].cache_pool_entry->bmp_count; ++j)
- *(kmalloc_cache_group[i].cache_pool_entry->bmp + (j >> 6)) ^= 1UL << (j % 64);
- kmalloc_cache_group[i].count_total_using = 0;
- kmalloc_cache_group[i].count_total_free = kmalloc_cache_group[i].cache_pool_entry->count_free;
- }
- struct Page *page = NULL;
-
- ul tmp_page_mms_end = virt_2_phys(memory_management_struct.end_of_struct) >> PAGE_2M_SHIFT;
- ul page_num = 0;
- for (int i = PAGE_2M_ALIGN(virt_2_phys(tmp_addr)) >> PAGE_2M_SHIFT; i <= tmp_page_mms_end; ++i)
- {
- page = memory_management_struct.pages_struct + i;
- page_num = page->addr_phys >> PAGE_2M_SHIFT;
- *(memory_management_struct.bmp + (page_num >> 6)) |= (1UL << (page_num % 64));
- ++page->zone->count_pages_using;
- --page->zone->count_pages_free;
- page_init(page, PAGE_KERNEL_INIT | PAGE_KERNEL | PAGE_PGT_MAPPED);
- }
-
-
- ul *virt = NULL;
- for (int i = 0; i < 16; ++i)
- {
-
- virt = (ul *)((memory_management_struct.end_of_struct + PAGE_2M_SIZE * i + PAGE_2M_SIZE - 1) & PAGE_2M_MASK);
- page = Virt_To_2M_Page(virt);
- page_num = page->addr_phys >> PAGE_2M_SHIFT;
- *(memory_management_struct.bmp + (page_num >> 6)) |= (1UL << (page_num % 64));
- ++page->zone->count_pages_using;
- --page->zone->count_pages_free;
- page_init(page, PAGE_PGT_MAPPED | PAGE_KERNEL | PAGE_KERNEL_INIT);
- kmalloc_cache_group[i].cache_pool_entry->page = page;
- kmalloc_cache_group[i].cache_pool_entry->vaddr = virt;
- }
-
- kinfo("SLAB initialized successfully!");
- return 0;
- }
- struct slab_obj *kmalloc_create_slab_obj(ul size)
- {
- struct Page *page = alloc_pages(ZONE_NORMAL, 1, 0);
-
- if (page == NULL)
- {
- kBUG("kmalloc_create()->alloc_pages()=>page == NULL");
- return NULL;
- }
- page_init(page, PAGE_KERNEL);
- ul *vaddr = NULL;
- ul struct_size = 0;
- struct slab_obj *slab_obj_ptr;
-
-
- switch (size)
- {
-
-
- case 32:
- case 64:
- case 128:
- case 256:
- case 512:
- vaddr = phys_2_virt(page->addr_phys);
-
- struct_size = sizeof(struct slab_obj) + PAGE_2M_SIZE / size / 8;
-
- slab_obj_ptr = (struct slab_obj *)((unsigned char *)vaddr + PAGE_2M_SIZE - struct_size);
- slab_obj_ptr->bmp = (void *)slab_obj_ptr + sizeof(struct slab_obj);
- slab_obj_ptr->count_free = (PAGE_2M_SIZE - struct_size) / size;
- slab_obj_ptr->count_using = 0;
- slab_obj_ptr->bmp_count = slab_obj_ptr->count_free;
- slab_obj_ptr->vaddr = vaddr;
- slab_obj_ptr->page = page;
- list_init(&slab_obj_ptr->list);
- slab_obj_ptr->bmp_len = ((slab_obj_ptr->bmp_count + sizeof(ul) * 8 - 1) >> 6) << 3;
-
- memset(slab_obj_ptr->bmp, 0xff, slab_obj_ptr->bmp_len);
- for (int i = 0; i < slab_obj_ptr->bmp_count; ++i)
- *(slab_obj_ptr->bmp + (i >> 6)) ^= 1UL << (i % 64);
- break;
-
-
- case 1024:
- case 2048:
- case 4096:
- case 8192:
- case 16384:
- case 32768:
- case 65536:
- case 131072:
- case 262144:
- case 524288:
- case 1048576:
- slab_obj_ptr = (struct slab_obj *)kmalloc(sizeof(struct slab_obj), 0);
- slab_obj_ptr->count_free = PAGE_2M_SIZE / size;
- slab_obj_ptr->count_using = 0;
- slab_obj_ptr->bmp_count = slab_obj_ptr->count_free;
- slab_obj_ptr->bmp_len = ((slab_obj_ptr->bmp_count + sizeof(ul) * 8 - 1) >> 6) << 3;
- slab_obj_ptr->bmp = (ul *)kmalloc(slab_obj_ptr->bmp_len, 0);
-
- memset(slab_obj_ptr->bmp, 0xff, slab_obj_ptr->bmp_len);
- for (int i = 0; i < slab_obj_ptr->bmp_count; ++i)
- *(slab_obj_ptr->bmp + (i >> 6)) ^= 1UL << (i % 64);
- slab_obj_ptr->vaddr = phys_2_virt(page->addr_phys);
- slab_obj_ptr->page = page;
- list_init(&slab_obj_ptr->list);
- break;
-
- default:
- kerror("kamlloc_create(): Wrong size%d", size);
- free_pages(page, 1);
- return NULL;
- break;
- }
- return slab_obj_ptr;
- }
- void *kmalloc(unsigned long size, unsigned long flags)
- {
- if (size > 1048576)
- {
- kwarn("kmalloc(): Can't alloc such memory: %ld bytes, because it is too large.", size);
- return NULL;
- }
- int index;
- for (int i = 0; i < 16; ++i)
- if (kmalloc_cache_group[i].size >= size)
- {
- index = i;
- break;
- }
- struct slab_obj *slab_obj_ptr = kmalloc_cache_group[index].cache_pool_entry;
-
-
- if (kmalloc_cache_group[index].count_total_free == 0)
- {
-
- slab_obj_ptr = kmalloc_create_slab_obj(kmalloc_cache_group[index].size);
-
- if (slab_obj_ptr == NULL)
- {
- kBUG("kmalloc()->kmalloc_create_slab_obj()=>slab == NULL");
- return NULL;
- }
- kmalloc_cache_group[index].count_total_free += slab_obj_ptr->count_free;
- list_add(&kmalloc_cache_group[index].cache_pool_entry->list, &slab_obj_ptr->list);
- }
- else
- {
- do
- {
-
- if (slab_obj_ptr->count_free == 0)
- slab_obj_ptr = container_of(list_next(&slab_obj_ptr->list), struct slab_obj, list);
- else
- break;
- } while (slab_obj_ptr != kmalloc_cache_group[index].cache_pool_entry);
- }
-
- int md;
- for (int i = 0; i < slab_obj_ptr->bmp_count; ++i)
- {
-
- if (*(slab_obj_ptr->bmp + (i >> 6)) == 0xffffffffffffffffUL)
- {
- i += 63;
- continue;
- }
- md = i % 64;
-
- if ((*(slab_obj_ptr->bmp + (i >> 6)) & (1UL << md)) == 0)
- {
- *(slab_obj_ptr->bmp + (i >> 6)) |= (1UL << md);
- ++(slab_obj_ptr->count_using);
- --(slab_obj_ptr->count_free);
- --kmalloc_cache_group[index].count_total_free;
- ++kmalloc_cache_group[index].count_total_using;
- return (void *)((char *)slab_obj_ptr->vaddr + kmalloc_cache_group[index].size * i);
- }
- }
- kerror("kmalloc(): Cannot alloc more memory: %d bytes", size);
- return NULL;
- }
- unsigned long kfree(void *address)
- {
- if (unlikely(address == NULL))
- return 0;
- struct slab_obj *slab_obj_ptr = NULL;
-
- void *page_base_addr = (void *)((ul)address & PAGE_2M_MASK);
- int index;
- for (int i = 0; i < 16; ++i)
- {
- slab_obj_ptr = kmalloc_cache_group[i].cache_pool_entry;
- do
- {
-
- if (slab_obj_ptr->vaddr != page_base_addr)
- {
- slab_obj_ptr = container_of(list_next(&slab_obj_ptr->list), struct slab_obj, list);
- }
- else
- {
-
- index = (address - slab_obj_ptr->vaddr) / kmalloc_cache_group[i].size;
-
- *(slab_obj_ptr->bmp + (index >> 6)) ^= 1UL << (index % 64);
- ++(slab_obj_ptr->count_free);
- --(slab_obj_ptr->count_using);
- ++kmalloc_cache_group[i].count_total_free;
- --kmalloc_cache_group[i].count_total_using;
-
-
- if ((slab_obj_ptr->count_using == 0) && (kmalloc_cache_group[i].count_total_free >= ((slab_obj_ptr->bmp_count) << 1)) && (kmalloc_cache_group[i].cache_pool_entry != slab_obj_ptr))
- {
- switch (kmalloc_cache_group[i].size)
- {
- case 32:
- case 64:
- case 128:
- case 256:
- case 512:
-
- list_del(&slab_obj_ptr->list);
- kmalloc_cache_group[i].count_total_free -= slab_obj_ptr->bmp_count;
- page_clean(slab_obj_ptr->page);
- free_pages(slab_obj_ptr->page, 1);
- break;
- default:
-
- list_del(&slab_obj_ptr->list);
- kmalloc_cache_group[i].count_total_free -= slab_obj_ptr->bmp_count;
- kfree(slab_obj_ptr->bmp);
- page_clean(slab_obj_ptr->page);
- free_pages(slab_obj_ptr->page, 1);
- kfree(slab_obj_ptr);
- break;
- }
- }
- return 0;
- }
- } while (slab_obj_ptr != kmalloc_cache_group[i].cache_pool_entry);
- }
- kBUG("kfree(): Can't free memory.");
- return ECANNOT_FREE_MEM;
- }
|