M7350/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/rtw_prealloc.c
2024-09-09 08:59:52 +00:00

214 lines
4.1 KiB
C
Executable File

/*
* hello-1.c - The simplest kernel module.
*/
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/slab.h>
#ifdef DBG_MEMORY_LEAK
#include <asm/atomic.h>
atomic_t _malloc_cnt = ATOMIC_INIT(0);
atomic_t _malloc_size = ATOMIC_INIT(0);
#endif /* DBG_MEMORY_LEAK */
void* _rtw_malloc(u32 sz)
{
void *pbuf = NULL;
pbuf = kmalloc(sz, /*GFP_KERNEL*/GFP_ATOMIC);
#ifdef DBG_MEMORY_LEAK
if (pbuf != NULL) {
atomic_inc(&_malloc_cnt);
atomic_add(sz, &_malloc_size);
}
#endif
return pbuf;
}
void _rtw_mfree(const void *pbuf, u32 sz)
{
if (pbuf)
{
kfree(pbuf);
#ifdef DBG_MEMORY_LEAK
atomic_dec(&_malloc_cnt);
atomic_sub(sz, &_malloc_size);
#endif
}
}
void* _rtw_zmalloc(u32 sz)
{
void *pbuf = _rtw_malloc(sz);
if (pbuf != NULL) {
memset(pbuf, 0, sz);
}
return pbuf;
}
#define rtw_malloc(sz) _rtw_malloc((sz))
#define rtw_zmalloc(sz) _rtw_zmalloc((sz))
#define rtw_mfree(pbuf, sz) _rtw_mfree((pbuf), (sz))
struct prealloc_node {
struct list_head entry;
int type;
int size;
void *buf;
};
struct list_head alloc_list;
struct list_head free_list;
spinlock_t lock;
void *rtw_find_prealloc(int type, size_t size)
{
struct list_head *phead, *plist;
struct prealloc_node *node;
unsigned long flags;
void *pbuf = NULL;
spin_lock_irqsave(&lock, flags);
phead = &free_list;
plist = phead->next;
while (plist != phead) {
node = list_entry(plist, struct prealloc_node, entry);
plist = plist->next;
if (node->type == type) {
// deletes entry from free_list
list_del(&node->entry);
// add a new entry to alloc_list
list_add_tail(&node->entry, &alloc_list);
pbuf = node->buf;
break;
}
}
spin_unlock_irqrestore(&lock, flags);
return pbuf;
}
void *rtw_pre_malloc(int type, size_t size)
{
struct prealloc_node *node;
void *pbuf;
unsigned long flags;
pbuf = rtw_find_prealloc(type, size);
if (pbuf)
return pbuf;
node = rtw_zmalloc(sizeof(struct prealloc_node));
if (NULL == node)
return NULL;
node->buf = rtw_zmalloc(size);
if (NULL == node->buf) {
rtw_mfree(node, sizeof(struct prealloc_node));
return NULL;
}
node->type = type;
node->size = size;
// add a new entry to alloc_list
spin_lock_irqsave(&lock, flags);
list_add_tail(&node->entry, &alloc_list);
spin_unlock_irqrestore(&lock, flags);
return node->buf;
}
EXPORT_SYMBOL(rtw_pre_malloc);
void rtw_pre_free(const void *p)
{
struct list_head *phead, *plist;
struct prealloc_node *node;
unsigned long flags;
spin_lock_irqsave(&lock, flags);
phead = &alloc_list;
plist = phead->next;
while (plist != phead) {
node = list_entry(plist, struct prealloc_node, entry);
plist = plist->next;
if (node->buf == p) {
// deletes entry from alloc_list
list_del(&node->entry);
// add a new entry to free_list
list_add_tail(&node->entry, &free_list);
goto out;
}
}
printk("[%s] invalid address.\n", __func__);
out:
spin_unlock_irqrestore(&lock, flags);
}
EXPORT_SYMBOL(rtw_pre_free);
void rtw_init(void)
{
INIT_LIST_HEAD(&alloc_list);
INIT_LIST_HEAD(&free_list);
spin_lock_init(&lock);
}
void rtw_free(void)
{
struct list_head *phead, *plist;
struct prealloc_node *node;
unsigned long flags;
spin_lock_irqsave(&lock, flags);
phead = &free_list;
plist = phead->next;
while (plist != phead) {
node = list_entry(plist, struct prealloc_node, entry);
plist = plist->next;
rtw_mfree(node->buf, node->size);
rtw_mfree(node, sizeof(struct prealloc_node));
}
phead = &alloc_list;
plist = phead->next;
while (plist != phead) {
node = list_entry(plist, struct prealloc_node, entry);
plist = plist->next;
printk("WARNING!! prealloc memory is not freed(type %d size %d).\n",
node->type, node->size);
rtw_mfree(node->buf, node->size);
rtw_mfree(node, sizeof(struct prealloc_node));
}
spin_unlock_irqrestore(&lock, flags);
}
int init_module(void)
{
printk(KERN_INFO "Hello world 1.\n");
rtw_init();
/*
* A non 0 return means init_module failed; module can't be loaded.
*/
return 0;
}
void cleanup_module(void)
{
printk(KERN_INFO "Goodbye world 1.\n");
rtw_free();
}