cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

util_mem.c (3776B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  Copyright (C) 2000 Takashi Iwai <tiwai@suse.de>
      4 *
      5 *  Generic memory management routines for soundcard memory allocation
      6 */
      7
      8#include <linux/mutex.h>
      9#include <linux/init.h>
     10#include <linux/slab.h>
     11#include <linux/module.h>
     12#include <sound/core.h>
     13#include <sound/util_mem.h>
     14
     15MODULE_AUTHOR("Takashi Iwai");
     16MODULE_DESCRIPTION("Generic memory management routines for soundcard memory allocation");
     17MODULE_LICENSE("GPL");
     18
     19#define get_memblk(p)	list_entry(p, struct snd_util_memblk, list)
     20
     21/*
     22 * create a new memory manager
     23 */
     24struct snd_util_memhdr *
     25snd_util_memhdr_new(int memsize)
     26{
     27	struct snd_util_memhdr *hdr;
     28
     29	hdr = kzalloc(sizeof(*hdr), GFP_KERNEL);
     30	if (hdr == NULL)
     31		return NULL;
     32	hdr->size = memsize;
     33	mutex_init(&hdr->block_mutex);
     34	INIT_LIST_HEAD(&hdr->block);
     35
     36	return hdr;
     37}
     38
     39/*
     40 * free a memory manager
     41 */
     42void snd_util_memhdr_free(struct snd_util_memhdr *hdr)
     43{
     44	struct list_head *p;
     45
     46	if (!hdr)
     47		return;
     48	/* release all blocks */
     49	while ((p = hdr->block.next) != &hdr->block) {
     50		list_del(p);
     51		kfree(get_memblk(p));
     52	}
     53	kfree(hdr);
     54}
     55
     56/*
     57 * allocate a memory block (without mutex)
     58 */
     59struct snd_util_memblk *
     60__snd_util_mem_alloc(struct snd_util_memhdr *hdr, int size)
     61{
     62	struct snd_util_memblk *blk;
     63	unsigned int units, prev_offset;
     64	struct list_head *p;
     65
     66	if (snd_BUG_ON(!hdr || size <= 0))
     67		return NULL;
     68
     69	/* word alignment */
     70	units = size;
     71	if (units & 1)
     72		units++;
     73	if (units > hdr->size)
     74		return NULL;
     75
     76	/* look for empty block */
     77	prev_offset = 0;
     78	list_for_each(p, &hdr->block) {
     79		blk = get_memblk(p);
     80		if (blk->offset - prev_offset >= units)
     81			goto __found;
     82		prev_offset = blk->offset + blk->size;
     83	}
     84	if (hdr->size - prev_offset < units)
     85		return NULL;
     86
     87__found:
     88	return __snd_util_memblk_new(hdr, units, p->prev);
     89}
     90
     91
     92/*
     93 * create a new memory block with the given size
     94 * the block is linked next to prev
     95 */
     96struct snd_util_memblk *
     97__snd_util_memblk_new(struct snd_util_memhdr *hdr, unsigned int units,
     98		      struct list_head *prev)
     99{
    100	struct snd_util_memblk *blk;
    101
    102	blk = kmalloc(sizeof(struct snd_util_memblk) + hdr->block_extra_size,
    103		      GFP_KERNEL);
    104	if (blk == NULL)
    105		return NULL;
    106
    107	if (prev == &hdr->block)
    108		blk->offset = 0;
    109	else {
    110		struct snd_util_memblk *p = get_memblk(prev);
    111		blk->offset = p->offset + p->size;
    112	}
    113	blk->size = units;
    114	list_add(&blk->list, prev);
    115	hdr->nblocks++;
    116	hdr->used += units;
    117	return blk;
    118}
    119
    120
    121/*
    122 * allocate a memory block (with mutex)
    123 */
    124struct snd_util_memblk *
    125snd_util_mem_alloc(struct snd_util_memhdr *hdr, int size)
    126{
    127	struct snd_util_memblk *blk;
    128	mutex_lock(&hdr->block_mutex);
    129	blk = __snd_util_mem_alloc(hdr, size);
    130	mutex_unlock(&hdr->block_mutex);
    131	return blk;
    132}
    133
    134
    135/*
    136 * remove the block from linked-list and free resource
    137 * (without mutex)
    138 */
    139void
    140__snd_util_mem_free(struct snd_util_memhdr *hdr, struct snd_util_memblk *blk)
    141{
    142	list_del(&blk->list);
    143	hdr->nblocks--;
    144	hdr->used -= blk->size;
    145	kfree(blk);
    146}
    147
    148/*
    149 * free a memory block (with mutex)
    150 */
    151int snd_util_mem_free(struct snd_util_memhdr *hdr, struct snd_util_memblk *blk)
    152{
    153	if (snd_BUG_ON(!hdr || !blk))
    154		return -EINVAL;
    155
    156	mutex_lock(&hdr->block_mutex);
    157	__snd_util_mem_free(hdr, blk);
    158	mutex_unlock(&hdr->block_mutex);
    159	return 0;
    160}
    161
    162/*
    163 * return available memory size
    164 */
    165int snd_util_mem_avail(struct snd_util_memhdr *hdr)
    166{
    167	unsigned int size;
    168	mutex_lock(&hdr->block_mutex);
    169	size = hdr->size - hdr->used;
    170	mutex_unlock(&hdr->block_mutex);
    171	return size;
    172}
    173
    174
    175EXPORT_SYMBOL(snd_util_memhdr_new);
    176EXPORT_SYMBOL(snd_util_memhdr_free);
    177EXPORT_SYMBOL(snd_util_mem_alloc);
    178EXPORT_SYMBOL(snd_util_mem_free);
    179EXPORT_SYMBOL(snd_util_mem_avail);
    180EXPORT_SYMBOL(__snd_util_mem_alloc);
    181EXPORT_SYMBOL(__snd_util_mem_free);
    182EXPORT_SYMBOL(__snd_util_memblk_new);