original files of m241

This commit is contained in:
neelimap
2026-07-30 11:19:44 +05:30
parent 170c2b3f3a
commit afc7070c1f
12254 changed files with 7655111 additions and 0 deletions
@@ -0,0 +1,499 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipcom_cache.c,v $ $Revision: 1.6.10.4 $
* $Source: /home/interpeak/CVSRoot/ipcom/src/ipcom_cache.c,v $
* $Author: hxie $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth.jonsson@windriver.com>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipcom_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include "ipcom_cache.h"
#include "ipcom_h.h"
#include "ipcom_clib.h"
#include "ipcom_syslog.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/* Maxium number of objects that the cache can hold. The definition is
a bit awkward, but it is done that way so
sizeof(Ipcom_cache_index)==4 won't cause overflow when the shift
operation is done. */
#define IPCOM_CACHE_MAX_OBJ_CNT \
((1u << (8 * sizeof(Ipcom_cache_index) - 1)) \
- 1u \
+ (1u << (8 * sizeof(Ipcom_cache_index) - 1)))
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipcom_cache_obj_order
*===========================================================================
* Description: Calculates the order of an object given it size.
* Parameters: obj_size - size of the object
* Returns: The order of the object.
*
*/
IP_STATIC unsigned
ipcom_cache_obj_order(unsigned obj_size)
{
unsigned obj_order = 3;
while (obj_size > (1u << obj_order))
++obj_order;
return obj_order;
}
/*
*===========================================================================
* ipcom_cache_obj_index
*===========================================================================
* Description: Returns the index of 'obj' in the object array.
* Parameters: cache - a cache instance
* obj - an object in the cache
* Returns:
*
*/
IP_STATIC Ipcom_cache_index
ipcom_cache_obj_index(Ipcom_cache *cache, const void *obj)
{
Ip_ptrdiff_t obj_base = (Ip_ptrdiff_t) cache->objs;
Ip_ptrdiff_t obj_val = (Ip_ptrdiff_t) obj;
ip_assert(((obj_val - obj_base) & (Ip_ptrdiff_t)((1 << cache->obj_order) - 1)) == 0);
return (Ipcom_cache_index) ((obj_val - obj_base) >> cache->obj_order);
}
/*
*===========================================================================
* ipcom_cache_alloc_obj
*===========================================================================
* Description: Allocates a new object from the cache.
* Parameters: cache - a cache instance
* Returns: A newly allocated object.
*
*/
IP_STATIC void *
ipcom_cache_alloc_obj(Ipcom_cache *cache)
{
unsigned hidx;
if (cache->free_objs != IP_NULL)
{
Ipcom_cache_free_obj *obj = cache->free_objs;
cache->free_objs = obj->next;
return obj;
}
/* Out of free objects, reuse an object */
IPCOM_CACHE_STATS(++cache->stats.recycles);
hidx = ipcom_random() % cache->htbl_cnt;
for (;;)
{
Ipcom_cache_index_set *obj_set = &cache->htbl[hidx];
/* Only check the first set, it will be valid if there is ANY
valid entry in this bucket. */
if (obj_set->obj_idx[0] != IPCOM_CACHE_INVALID_INDEX)
{
void *obj;
/* Reuse this object */
obj = ipcom_cache_index_to_obj(cache,
obj_set->obj_idx[0]);
/* Move all indexes forward one step and make sure the
last index is the invalid index */
ipcom_memmove(&obj_set->obj_idx[0],
&obj_set->obj_idx[1],
ip_offsetof(Ipcom_cache_index_set, obj_idx[IPCOM_CACHE_SET_N - 1]));
obj_set->obj_idx[IPCOM_CACHE_SET_N - 1] = IPCOM_CACHE_INVALID_INDEX;
return obj;
}
hidx = (hidx + 1) % cache->htbl_cnt;
}
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipcom_cache_delete
*===========================================================================
* Description: Frees all resouces allocated by the cache
* Parameters: cache - the cache to delete
* Returns:
*
*/
IP_PUBLIC void
ipcom_cache_delete(Ipcom_cache *cache)
{
ipcom_free(cache);
}
/*
*===========================================================================
* ipcom_cache_new_with_bucket_count
*===========================================================================
* Description: Creates a new cache with a specific number of objects
* in the cache. The amount of memory occupied by the
* cache will be the amount required to fit all objects.
* Parameters: htbl_cnt - number of buckets the cache will hold
* obj_size - the size of each object, this actual object
* size might be larger to satisfy cache line alignment
* obj_func - given an object, will return the
* corresponding hash value
* key_func - given a search key, will return the
* corresponding hash value
* cmp_func - functions that returns if an object and a
* search key match
* Returns: A newly created cache or IP_NULL if not enough memory
* could be allocated.
*
*/
IP_PUBLIC Ipcom_cache *
ipcom_cache_new_with_bucket_count(unsigned htbl_cnt,
unsigned obj_size,
Ipcom_hash_obj_func obj_func,
Ipcom_hash_key_func key_func,
Ipcom_hash_cmp_func cmp_func)
{
Ipcom_cache *cache;
unsigned obj_order;
unsigned objs_size;
unsigned obj_cnt;
unsigned htbl_size;
obj_cnt = (htbl_cnt
* IPCOM_CACHE_FILL_RATIO
* IPCOM_CACHE_SET_N
/ 100);
obj_cnt = IP_MIN(IPCOM_CACHE_MAX_OBJ_CNT, obj_cnt);
obj_order = ipcom_cache_obj_order(obj_size);
objs_size = obj_cnt * (unsigned)(1 << obj_order);
htbl_size = (unsigned)sizeof(Ipcom_cache_index_set) * htbl_cnt;
cache = ipcom_calloc(1,
sizeof(*cache)
+ sizeof(void*)
+ htbl_size
+ ipcom_cache_line_size()
+ objs_size);
if (cache == IP_NULL)
{
IPCOM_LOG0(ERR, "ipcom_cache: Failed to allocate memory");
return IP_NULL;
}
cache->obj_func = obj_func;
cache->key_func = key_func;
cache->cmp_func = cmp_func;
cache->htbl = IP_PTR_ALIGN((cache + 1), sizeof(void*));
cache->htbl_cnt = htbl_cnt;
cache->objs = IP_PTR_ALIGN((char*)cache->htbl + htbl_size,
ipcom_cache_line_size());
cache->obj_cnt = (Ipcom_cache_index) obj_cnt;
cache->obj_size = obj_size;
cache->obj_order = obj_order;
ipcom_cache_flush(cache);
return cache;
}
/*
*===========================================================================
* ipcom_cache_new_with_memory_limit
*===========================================================================
* Description: Creates a new cache that will not occupy more than a
* the specified amount of memory. The actualt number of
* objects in the cache will be determined by the memory
* limit.
* Parameters: memory_limit - number of bytes the cache is allowed to
* use
* obj_size - the size of each object, this actual object
* size might be larger to satisfy cache line alignment
* obj_func - given an object, will return the
* corresponding hash value
* key_func - given a search key, will return the
* corresponding hash value
* cmp_func - functions that returns if an object and a
* search key match
* Returns: A newly created cache or IP_NULL if not enough memory
* could be allocated.
*
*/
IP_PUBLIC Ipcom_cache *
ipcom_cache_new_with_memory_limit(unsigned memory_limit,
unsigned obj_size,
Ipcom_hash_obj_func obj_func,
Ipcom_hash_key_func key_func,
Ipcom_hash_cmp_func cmp_func)
{
unsigned obj_cnt_hi = 0xfffe;
unsigned obj_cnt_lo = 1;
unsigned obj_cnt = (obj_cnt_lo + obj_cnt_hi) / 2;
unsigned htbl_cnt;
unsigned actual_obj_size;
unsigned mem;
unsigned mem_spill_limit;
memory_limit -= (unsigned)(sizeof(Ipcom_cache));
memory_limit -= ipcom_cache_line_size();
actual_obj_size = (unsigned)(1 << ipcom_cache_obj_order(obj_size));
mem_spill_limit = IP_MAX(ipcom_cache_line_size(), actual_obj_size);
/* Using iterative way of calculating the object count since
doing the calculation analytical is subject to rounding errors
and aliasing effect since it not possible to use floating
point math. It is also easier to get formula (1) correct this
way. */
for (;;)
{
obj_cnt = (obj_cnt_lo + obj_cnt_hi) / 2;
htbl_cnt = obj_cnt * 100 / IPCOM_CACHE_FILL_RATIO / IPCOM_CACHE_SET_N;
mem = obj_cnt
* actual_obj_size + htbl_cnt
* (unsigned)sizeof(Ipcom_cache_index_set);
if (mem > memory_limit)
obj_cnt_hi = obj_cnt;
else if (memory_limit - mem > mem_spill_limit)
obj_cnt_lo = obj_cnt;
else
break;
}
return ipcom_cache_new_with_bucket_count(htbl_cnt,
obj_size,
obj_func,
key_func,
cmp_func);
}
/*
*===========================================================================
* ipcom_cache_flush
*===========================================================================
* Description:
* Parameters: cache -
* Returns:
*
*/
IP_PUBLIC void
ipcom_cache_flush(Ipcom_cache *cache)
{
Ipcom_cache_index i;
Ipcom_cache_index first_idx = ipcom_cache_obj_index(cache, cache->objs);
cache->free_objs = IP_NULL;
for (i = (Ipcom_cache_index) (first_idx + cache->obj_cnt);
i > first_idx;
--i)
{
Ipcom_cache_free_obj *obj;
obj = ipcom_cache_index_to_obj(cache, (Ipcom_cache_index) (i - 1));
obj->next = cache->free_objs;
cache->free_objs = obj;
}
ipcom_memset(cache->htbl,
IPCOM_CACHE_INVALID_INDEX & 0xff,
cache->htbl_cnt * sizeof(Ipcom_cache_index_set));
}
/*
*===========================================================================
* ipcom_cache_insert
*===========================================================================
* Description: Inserts a new object into the cache.
* Parameters: cache - a cache instance
* obj - object to insert
* Returns:
*
*/
IP_PUBLIC void
ipcom_cache_insert(Ipcom_cache *cache, void *obj)
{
ipcom_cache_insert_with_index(cache,
obj,
cache->obj_func(obj) % cache->htbl_cnt);
}
/*
*===========================================================================
* ipcom_cache_insert_with_index
*===========================================================================
* Description: Inserts a new object into the cache, the hash table
* index must be pre-calculated.
* Parameters: cache - a cache instance
* obj - object to insert
* hidx - hash
* Returns:
*
*/
IP_PUBLIC void
ipcom_cache_insert_with_index(Ipcom_cache *cache,
void *obj,
unsigned hidx)
{
unsigned set_idx;
void *new_obj;
Ipcom_cache_index_set *obj_set = &cache->htbl[hidx];
IPCOM_CACHE_STATS(++cache->stats.inserts);
IPCOM_CACHE_STATS((obj_set->obj_idx[0] == IPCOM_CACHE_INVALID_INDEX
? cache->stats.bucketshares
: ++cache->stats.bucketshares));
for (set_idx = 0; set_idx < IPCOM_CACHE_SET_N; ++set_idx)
{
if (obj_set->obj_idx[set_idx] == IPCOM_CACHE_INVALID_INDEX)
{
/* Found unused slot, allocate a new object from the
cache */
new_obj = ipcom_cache_alloc_obj(cache);
if (set_idx > 0
&& obj_set->obj_idx[set_idx - 1] == IPCOM_CACHE_INVALID_INDEX)
/* ipcom_cache_alloc_obj() had to reuse an already
allocated object and it was selected from the same
bucket as this objects is being added to. So this
bucket now has one less valid entry */
--set_idx;
obj_set->obj_idx[set_idx] = ipcom_cache_obj_index(cache, new_obj);
break;
}
}
if (set_idx == IPCOM_CACHE_SET_N)
{
/* All sets used, overwrite on of the cached objects in this
set. */
IPCOM_CACHE_STATS(++cache->stats.collisions);
set_idx = ipcom_random() % IPCOM_CACHE_SET_N;
new_obj = ipcom_cache_index_to_obj(cache, obj_set->obj_idx[set_idx]);
}
ipcom_memcpy(new_obj, obj, cache->obj_size);
}
/*
*===========================================================================
* ipcom_cache_lookup
*===========================================================================
* Description: Lookups an object using a pre-calculated hash
* value. This function can be when the hash value is
* calculated by hardware.
* Parameters: cache - cache instance
* key - lookup key
* Returns: The matching object or IP_NULL if no match was found
*
*/
IP_PUBLIC void *
ipcom_cache_lookup(Ipcom_cache *cache, const void *key)
{
return ipcom_cache_lookup_with_index(cache,
key,
cache->key_func(key) % cache->htbl_cnt);
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/