Files
m241Neelima/components/ip_net2-6.9/iprohc/src/iprohc_comp.c
T
2026-07-30 11:19:44 +05:30

1058 lines
29 KiB
C

/* iprohc_comp.c - ROHC compressor utility routines */
/*
* Copyright (c) 2008-2013 Wind River Systems, Inc.
*
* The right to copy, distribute or otherwise make use of this software
* may be licensed only pursuant to the terms of an applicable Wind River
* license agreement. No license to Wind River intellectual property rights
* is granted herein. All rights not licensed by Wind River are reserved
* by Wind River.
*/
/*
modification history
--------------------
01s,08aug13,j_y Clean low impact code review defects
01n,21nov12,ggz Defect WIND00387435. Validate comp/decomp ptrs before usage
01m,01oct12,ggz Use cid = 1 instead of random val. Defect WIND00380294
01l,20oct11,ggz Fix for defect WIND00312450
01k,11feb11,ggz Fix for defect WIND00254208
01j,10feb11,ggz Resolve a lock issue for non vxworks port. Defet WIND00254463
01i,13apr10,ggz Resolve 64bit compiler warnings
01h,24feb09,tlu Replace ipcom_tmo by ipnet_timeout to port to LKM
01g,15jul08,tlu Add for CID bit map allocation
01f,03jul08,tlu Modify to call ipcom_random only to init CID
and release context lock when finding a context
01e,15jun08,ggz Added normal state to iprohc_comp_state for uncompressed profile
01d,23jun08,tlu Modify to init CID with a random number
01c,12may08,tlu Add more debugging functions
01b,30apr08,tlu Add debug function to print compression context
01a,07mar08,tlu Created.
*/
/*
****************************************************************************
* DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* CONFIGURATION
****************************************************************************
*/
#include "iprohc_config.h"
/*
****************************************************************************
* INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
/* ipcom */
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
#include <ipcom_os.h>
#include <ipcom_sysvar.h>
#include <ipcom_err.h>
#include <ipcom_syslog.h>
#include <ipcom_list.h>
#include <ipcom_time.h>
#include <ipcom_inet.h>
/* iprohc */
#include "iprohc.h"
/*
****************************************************************************
* DEFINES
****************************************************************************
*/
IP_EXTERN Iprohc_data iprohc;
/* This is a compile flag, turning on it will build debug message into image */
#undef ROHC_DEBUG
/*
****************************************************************************
* LOCAL TYPES
****************************************************************************
*/
/*
****************************************************************************
* LOCAL Data
****************************************************************************
*/
/*
****************************************************************************
* LOCAL PROTOTYPES
****************************************************************************
*/
IP_STATIC Iprohc_c_context *
iprohc_c_find_context_by_cid(Iprohc_compressor *comp, Ip_u16 cid,
Ip_u8 src_addr_type, void *src_addr);
/*
****************************************************************************
* LOCAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* iprohc_c_find_context_by_cid
*===========================================================================
* Description: Find a compression context according to CID and source
* address of the feedback pkt.
* Parameters:
* Returns:
*
*/
IP_STATIC Iprohc_c_context *
iprohc_c_find_context_by_cid(Iprohc_compressor *comp, Ip_u16 cid,
Ip_u8 src_addr_type, void *src_addr)
{
Iprohc_c_context *context, *ncontext;
#ifdef IPCOM_USE_INET
Ipa_union *addr4 = IP_NULL;
#endif
#ifdef IPCOM_USE_INET6
struct Ip_in6_addr *addr6 = IP_NULL;
#endif
#ifdef ROHC_DEBUG
ipcom_printf("Enter iprohc_c_find_context_by_cid\n");
#endif
if (src_addr)
{
#ifdef IPCOM_USE_INET
if (src_addr_type == ROHC_PKT_IPV4)
addr4 = (Ipa_union *)src_addr;
#ifdef IPCOM_USE_INET6
else
#endif /* IPCOM_USE_INET6 */
#endif
#ifdef IPCOM_USE_INET6
if (src_addr_type == ROHC_PKT_IPV6)
addr6 = (struct Ip_in6_addr *)src_addr;
#endif
}
IPROHC_COMP_LOCK(comp);
for (context = IPCOM_LIST_FIRST(&comp->context_head);
context != IP_NULL;
context = ncontext)
{
ncontext = IPCOM_LIST_NEXT(&context->context_list);
IPROHC_C_CONTEXT_LOCK(context);
/* Check the CID */
if (context->cid == cid)
{
/* Check the address if supplied*/
#ifdef IPCOM_USE_INET
if (addr4 &&
(context->stream_type == ROHC_PKT_IPV4) &&
(addr4->addr32 == context->dst.addr4.addr32))
goto findit;
#ifdef IPCOM_USE_INET6
else
#endif /* #ifdef IPCOM_USE_INET6 */
#endif /* #ifdef IPCOM_USE_INET */
#ifdef IPCOM_USE_INET6
if (addr6 &&
(context->stream_type == ROHC_PKT_IPV6) &&
(ipcom_memcmp(addr6, &context->dst.addr6,
sizeof(struct Ip_in6_addr)) == 0))
goto findit;
#endif /* #ifdef IPCOM_USE_INET6 */
else
goto next_c;
/* Find the context, return it */
findit:
IPROHC_C_CONTEXT_UNLOCK(context);
IPROHC_COMP_UNLOCK(comp);
return context;
}
next_c:
IPROHC_C_CONTEXT_UNLOCK(context);
}
IPROHC_COMP_UNLOCK(comp);
/* Didn't find the context, return IP_NULL */
return IP_NULL;
}
/*
****************************************************************************
* PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* iprohc_alloc_compressor
*===========================================================================
* Description: Allocate a ROHC compressor structure
* Parameters:
* Returns:
*
*/
IP_PUBLIC Iprohc_compressor *
iprohc_alloc_compressor(struct Iprohc_interface *interface)
{
Iprohc_compressor *comp;
Ip_u32 ra = ipcom_random() & 0x7;
Ip_u16 cid_map_size;
/* Allocate and pre-init compressor structure */
comp = (Iprohc_compressor *)ipcom_malloc(sizeof(Iprohc_compressor));
if(comp == IP_NULL)
return IP_NULL;
ipcom_memset(comp, 0, sizeof(Iprohc_compressor));
/* Allocate CID bit map */
cid_map_size = (Ip_u16)((iprohc.max_cid+1)/16);
if ((iprohc.max_cid+1) % 16)
cid_map_size = (Ip_u16)(cid_map_size + 1);
comp->bit_map_size = cid_map_size;
comp->cid_bit_map = ipcom_malloc(2 * cid_map_size);
if(comp->cid_bit_map == IP_NULL)
{
ipcom_free(comp);
return IP_NULL;
}
ipcom_memset(comp->cid_bit_map, 0, (2*cid_map_size));
/* Mark CID 0 as used in the bit map */
comp->cid_bit_map[0] |= 1;
comp->interface = interface;
/* init the next to-be-used CID to a random not 0 value (won't use 0
* as CID) to avoid confusing of the ADD-CID octet with the PADDING
* octet */
comp->to_be_used_cid = (Ip_u16)(ra?ra:1);
/* init list */
ipcom_list_init(&(comp->context_head));
#ifdef IPROHC_ENABLE_REENTRANT
(void)ipcom_mutex_create(&comp->code_mutex);
#endif
return comp;
}
/*
*===========================================================================
* iprohc_del_compressor
*===========================================================================
* Description: Free a ROHC compressor structure
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
iprohc_del_compressor(Iprohc_compressor *compressor)
{
Ip_err retval = IPCOM_SUCCESS;
Iprohc_c_context *context, *ncontext;
/* just return IPCOM_SUCCESS for a NULL compressor */
if (compressor == IP_NULL) return retval;
IPROHC_COMP_LOCK(compressor);
/* free cid_bit_map */
ipcom_free(compressor->cid_bit_map);
for (context = IPCOM_LIST_FIRST(&compressor->context_head);
context != IP_NULL;
context = ncontext)
{
ncontext = IPCOM_LIST_NEXT(&context->context_list);
compressor->context_num--;
/* free the context */
iprohc.profiles[context->profileid].c_del_context(context);
}
IPROHC_COMP_UNLOCK(compressor);
#ifdef IPROHC_ENABLE_REENTRANT
(void)ipcom_mutex_delete(&compressor->code_mutex);
#endif
/* free the compressor */
ipcom_free(compressor);
return retval;
}
/*
*===========================================================================
* iprohc_c_del_profile_contexts
*===========================================================================
* Description: Free contexts associated with a profile
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
iprohc_c_del_profile_contexts(Iprohc_compressor *compressor, Ip_u8 profileid)
{
Ip_err retval = IPCOM_SUCCESS;
Iprohc_c_context *context, *ncontext;
Ip_u16 i, j, m = 0;
/* just return IPCOM_SUCCESS for a NULL compressor */
if (compressor == IP_NULL) return retval;
IPROHC_COMP_LOCK(compressor);
for (context = IPCOM_LIST_FIRST(&compressor->context_head);
context != IP_NULL;
context = ncontext)
{
ncontext = IPCOM_LIST_NEXT(&context->context_list);
if (context->profileid != profileid) continue;
compressor->context_num--;
/* find the next cid to be allocated */
i = (Ip_u16)((int)context->cid / 16);
j = (Ip_u16)((int)context->cid % 16);
m = (Ip_u16)(1 << j);
m = (Ip_u16)~m;
/* Reset CID used flag */
compressor->cid_bit_map[i] = compressor->cid_bit_map[i] & m;
/* free the context */
iprohc.profiles[context->profileid].c_del_context(context);
}
IPROHC_COMP_UNLOCK(compressor);
return retval;
}
/*
*===========================================================================
* iprohc_comp_mod_cid
*===========================================================================
* Description: Allocate a ROHC compressor structure
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
iprohc_comp_mod_cid(struct Iprohc_interface *interface,
Ip_u8 profileid, Ip_u16 cid)
{
Iprohc_compressor *comp;
#ifdef ROHC_DEBUG
if (((Iprohc_interface *)interface)->have_unitNum)
{
ipcom_printf("Enter iprohc_comp_mod_cid, interface %s%d, profileid %d, cid %d\n",
((Iprohc_interface *)interface)->name,
((Iprohc_interface *)interface)->unitNum, profileid, cid);
}
else
{
ipcom_printf("Enter iprohc_comp_mod_cid, interface %s, profileid %d, cid %d\n",
((Iprohc_interface *)interface)->name, profileid, cid);
}
#endif
/* Check whether the profile is configured */
if (iprohc_find_profile(profileid) != IPCOM_SUCCESS)
{
IPCOM_LOG1(ERR, "iprohc_comp_mod_cid, not a configured profile %d\n",
profileid);
return IPCOM_ERR_INVALID_ARG;
}
/* Validate CID value */
if ((cid < 1) || (cid > iprohc.max_cid))
{
IPCOM_LOG2(ERR,
"iprohc_comp_mod_cid, %d not in valid cid range [1, %d]\n",
cid, iprohc.max_cid);
return IPCOM_ERR_INVALID_ARG;
}
comp = ((Iprohc_interface *)interface)->compressor;
IPROHC_COMP_LOCK(comp);
/* init the next to-be-used CID to a random not 0 value (won't use 0
* as CID) to avoid confusing of the ADD-CID octet with the PADDING
* octet */
comp->to_be_used_cid = cid;
IPROHC_COMP_UNLOCK(comp);
#ifdef ROHC_DEBUG
ipcom_printf("iprohc_comp_mod_cid, modified next to be used cid\n");
#endif
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* iprohc_c_context_common_create
*===========================================================================
* Description: Allocate a ROHC compression context common structure
* Parameters:
* Returns:
*
*/
IP_PUBLIC Iprohc_c_context *
iprohc_c_context_common_create(Ip_u16 cid)
{
Iprohc_c_context *c_context;
/* Allocate and pre-init compression context structure */
c_context = (Iprohc_c_context *)ipcom_malloc(sizeof(Iprohc_c_context));
if (c_context == IP_NULL)
{
IPCOM_LOG0(ERR,"iprohc_c_context_common_create, out of memory");
return IP_NULL;
}
ipcom_memset(c_context, 0, sizeof(Iprohc_c_context));
/* Initialize the context fields */
c_context->cid = cid;
c_context->state = ROHC_COMP_STATE_IR;
c_context->mode = ROHC_MODE_U;
c_context->pkt_type = ROHC_PKT_IR;
#ifdef IPROHC_ENABLE_REENTRANT
(void)ipcom_mutex_create(&c_context->code_mutex);
#endif
return c_context;
}
/*
*===========================================================================
* iprohc_c_context_common_del
*===========================================================================
* Description: Free a ROHC compression context common structure
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
iprohc_c_context_common_del(Iprohc_c_context *c_context)
{
/* Cancel the timer. */
ipnet_timeout_cancel(c_context->retx_ir);
#ifdef IPROHC_ENABLE_REENTRANT
(void)ipcom_mutex_delete(&c_context->code_mutex);
#endif
ipcom_free(c_context);
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* iprohc_c_process_feedback
*===========================================================================
* Description: Process the received feedback elements from the decompressor
*
* Feedback consists of one or more concatenated feedback elements,
* where each feedback element has the following format:
*
* ---------------------------
* | 1 1 1 1 0 | Code | feedback type octet
* ---------------------------
* : Size : if Code = 0
* ---------------------------
* / feedback data / variable length
* ---------------------------
*
* The feedback data has the following structure:
*
* ---------------------------
* : Add-CID octet : if for small CIDs and (CID != 0)
* ---------------------------
* : :
* / large CID / 1 - 2 octects for large CIDs
* : (4.5.6 encoding) :
* ---------------------------
* / feedback field /
* ---------------------------
*
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
iprohc_c_process_feedback(Iprohc_compressor *compressor,
Ip_u8 src_addr_type,
void *src_addr,
Ip_u16 feedback_num,
Ip_u8 *feedbacks)
{
Ip_err retval = IPCOM_SUCCESS;
Ip_u8 pointer = 0, fb_p = 0;
Ip_u8 size, data_size;
Ip_u16 cid = 0, i;
Iprohc_c_context *context;
#ifdef ROHC_DEBUG
ipcom_printf("Enter iprohc_c_process_feedback, feedback_num %d, feedback %x\n",
feedback_num, feedbacks);
#endif
if (compressor == IP_NULL) goto leave;
for (i = 0; i < feedback_num; i++)
{
#ifdef ROHC_DEBUG
ipcom_printf("iprohc_c_process_feedback(for), i %d, pointer %d, feedbacks[pointer] %x\n",
i, pointer, feedbacks[pointer]);
#endif
if ((feedbacks[pointer]>>ROHC_PKT_FEEDBACK_SHIFT) != ROHC_PKT_FEEDBACK)
{
/* Pass in a non feedback element */
IPCOM_LOG0(ERR, "iprohc_c_process_feedback, not a feedback element\n");
IPROHC_LEAVE(IPCOM_ERR_INVALID_ARG);
}
/* Get the size */
if ((feedbacks[pointer] & 0x07) == 0)
{
/* move the pointer */
pointer++;
data_size = size = feedbacks[pointer];
/* Count Size octet */
size ++;
}
else
data_size = size = (Ip_u8)(feedbacks[pointer] & 0x07);
#ifdef ROHC_DEBUG
ipcom_printf("iprohc_c_process_feedback, data_size %d, size %d\n",
data_size, size);
#endif
/* Move the pointer */
pointer++;
/* get the CID */
if (iprohc.large_cid)
{
/*
* Decode cid according to RFC 3095, 4.5.6.
* RFC 3095, section 5.2.2: If the first bit is 0, the CID uses
* one octet. If the first bit is 1, the CID uses two octet.
*/
if ((feedbacks[pointer] & 0x80) == 0)
cid = feedbacks[pointer];
else
{
ipcom_memcpy(&cid, &(feedbacks[pointer]), 2);
cid = ip_ntohs(cid);
cid = (Ip_u16)(cid & 0x7fff);
}
}
else if ((feedbacks[pointer]>>ROHC_PKT_ADD_CID_SHIFT)
== ROHC_PKT_ADD_CID)
{
/* Small CID */
cid = (Ip_u16)(feedbacks[pointer] & 0x0F);
}
else
cid = 0;
#ifdef ROHC_DEBUG
ipcom_printf("iprohc_c_process_feedback, cid %d, size %d\n",
cid, size);
#endif
/* Find the context according to cid and source address */
context = iprohc_c_find_context_by_cid(compressor, cid,
src_addr_type, src_addr);
#ifdef ROHC_DEBUG
if (context)
{
ipcom_printf("iprohc_c_process_feedback, find a c_context\n");
iprohc_c_print_a_context(context);
}
else
ipcom_printf("iprohc_c_process_feedback, didn't find a c_context\n");
#endif
/* Dispatch the feedback field to the compressor context */
if (context)
iprohc.profiles[context->profileid].c_process_feedback(context,
feedbacks+fb_p+size-data_size+1, data_size);
/* Move pointer and fb_p to point to the next feedback element */
fb_p = (Ip_u8)(fb_p + 1 + size);
pointer = fb_p;
#ifdef ROHC_DEBUG
ipcom_printf("iprohc_c_process_feedback, fb_p %d, pointer %d\n",
fb_p, pointer);
#endif
}
leave:
ipcom_free(feedbacks);
return retval;
}
/*
*===========================================================================
* iprohc_retx_ir_timeout
*===========================================================================
* Description: Set next transmitting packet type to be IR if the compression
* context is not in Pending state.
* Parameters:
* Returns:
*
*/
IP_PUBLIC void
iprohc_retx_ir_timeout(void *cookie)
{
Iprohc_c_context *c_context;
#ifdef ROHC_DEBUG
ipcom_printf("iprohc_retx_ir_timeout: retx IR timer times out\n");
#endif
c_context = (Iprohc_c_context *)cookie;
IPROHC_C_CONTEXT_LOCK(c_context);
if (c_context->trans != ROHC_COMP_TRANS_PENDING)
{
c_context->pkt_type = ROHC_PKT_IR;
c_context->ext_type = ROHC_EXT_NO_EXT;
}
IPROHC_C_CONTEXT_UNLOCK(c_context);
}
/*
*===========================================================================
* iprohc_c_print_a_context
*===========================================================================
* Description: For debugging -- print out a compression context
* Parameters:
* Returns:
*
*/
IP_PUBLIC void
iprohc_c_print_a_context(Iprohc_c_context *context)
{
Ip_u8 profileid;
char buf[48], srcbuf[48];
profileid = context->profileid;
ipcom_printf(" Compression Context (%x):\n", context);
ipcom_printf(" cid: %d\n", context->cid);
ipcom_printf(" state: %s\n",
iprohc_comp_state(context->state));
ipcom_printf(" mode: %s\n",
iprohc_context_mode(context->mode));
ipcom_printf(" decline_mode_trans: %s\n",
context->decline_mode_trans?"Yes":"No");
ipcom_printf(" trans: %s\n",
iprohc_comp_trans(context->trans));
ipcom_printf(" pkt_type: %s\n",
iprohc_pkt_type(context->pkt_type));
ipcom_printf(" ext_type: %s\n",
iprohc_ext_type(context->ext_type));
ipcom_printf(" reject: %s\n",
context->reject?"Yes":"No");
ipcom_printf(" num_ir: %d\n", context->num_ir);
ipcom_printf(" num_compressed: %d\n",
context->num_compressed);
ipcom_printf(" stream type: %s\n",
(context->stream_type==ROHC_PKT_IPV4)?"IPv4":"IPv6");
if (context->stream_type == ROHC_PKT_IPV4)
#ifdef IPCOM_USE_INET
{
(void)ipcom_inet_ntop(IP_AF_INET, &context->dst.addr4.addr32, buf,
sizeof(buf));
(void)ipcom_inet_ntop(IP_AF_INET, &context->src.addr4.addr32, srcbuf,
sizeof(srcbuf));
}
#ifdef IPCOM_USE_INET6
else
#endif
#endif /* #ifdef IPCOM_USE_INET */
#ifdef IPCOM_USE_INET6
{
(void)ipcom_inet_ntop(IP_AF_INET6, &context->dst.addr6, buf,
sizeof(buf));
(void)ipcom_inet_ntop(IP_AF_INET6, &context->src.addr6, srcbuf,
sizeof(srcbuf));
}
#endif /* #ifdef IPCOM_USE_INET6 */
ipcom_printf(" src address: %s\n", srcbuf);
ipcom_printf(" dst address: %s\n", buf);
/* Print profile specific compression context */
iprohc.profiles[profileid].c_print_context(context);
}
/*
*===========================================================================
* iprohc_c_print_context
*===========================================================================
* Description: Print out all the contexts in the compressor
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
iprohc_c_print_context(Iprohc_compressor *compressor, Ip_u8 profile)
{
Ip_err retval = IPCOM_SUCCESS;
Iprohc_c_context *context, *ncontext;
if (compressor == IP_NULL)
return retval;
if (compressor->context_num == 0)
{
ipcom_printf(" Compression Context: None\n");
return retval;
}
for (context = IPCOM_LIST_FIRST(&compressor->context_head);
context != IP_NULL;
context = ncontext)
{
ncontext = IPCOM_LIST_NEXT(&context->context_list);
if (context->profileid != profile) continue;
iprohc_c_print_a_context(context);
}
return retval;
}
/*
*===========================================================================
* iprohc_comp_state
*===========================================================================
* Description: Debugging utility to print a compression context state
* Parameters:
* Returns:
*
*/
IP_PUBLIC char * iprohc_comp_state(Iprohc_comp_state state)
{
switch (state)
{
case ROHC_COMP_STATE_IR:
ipcom_strcpy(iprohc.buf, "IR");
break;
case ROHC_COMP_STATE_FO:
ipcom_strcpy(iprohc.buf, "FO");
break;
case ROHC_COMP_STATE_SO:
ipcom_strcpy(iprohc.buf, "SO");
break;
case ROHC_COMP_STATE_NORMAL:
ipcom_strcpy(iprohc.buf, "NORM");
break;
default:
ipcom_strcpy(iprohc.buf, "Illegal");
break;
}
return iprohc.buf;
}
/*
*===========================================================================
* iprohc_comp_trans
*===========================================================================
* Description: Debugging utility to print a compression context mode
* transition state
* Parameters:
* Returns:
*
*/
IP_PUBLIC char * iprohc_comp_trans(Iprohc_comp_trans trans)
{
switch (trans)
{
case ROHC_COMP_TRANS_DONE:
ipcom_strcpy(iprohc.buf, "Done");
break;
case ROHC_COMP_TRANS_PENDING:
ipcom_strcpy(iprohc.buf, "Pending");
break;
default:
ipcom_strcpy(iprohc.buf, "Illegal");
break;
}
return iprohc.buf;
}
#ifndef IP_PORT_VXWORKS /* for Linux recursive semaphore */
/*
*===========================================================================
* iprohc_comp_lck
*===========================================================================
* Description: This function provides a recursive semaphore lock to an ROHC
* compressor.
* Parameters:
* Returns:
*
*/
IP_PUBLIC void
iprohc_comp_lck(Iprohc_compressor *comp)
{
Ip_pid_t cpid = ipcom_getpid();
#ifdef ROHC_DEBUG
ipcom_printf("Calling iprohc_comp_lck: pid %d, counter %d, cpid %d\n",
comp->pid, comp->s_counter, cpid);
#endif
if (comp->pid == 0)
{
/* No one has semaphore, take it */
comp->pid = cpid;
comp->s_counter = 1;
ipcom_mutex_lock(comp->code_mutex);
}
else if (comp->pid != cpid)
{
/* block a different process/task */
ipcom_mutex_lock(comp->code_mutex);
comp->pid = cpid;
comp->s_counter++;
}
else
/* the semaphore is taken by the same process, increase the counter */
comp->s_counter ++;
#ifdef ROHC_DEBUG
ipcom_printf("iprohc_comp_lck: pid %d, counter %d, cpid %d\n",
comp->pid, comp->s_counter, cpid);
#endif
}
/*
*===========================================================================
* iprohc_comp_unlck
*===========================================================================
* Description: This function provides a recursive semaphore unlock to an
* ROHC compressor.
* Parameters:
* Returns:
*
*/
IP_PUBLIC void
iprohc_comp_unlck(Iprohc_compressor *comp)
{
Ip_pid_t cpid = ipcom_getpid();
#ifdef ROHC_DEBUG
ipcom_printf("Calling iprohc_comp_unlck: pid %d, counter %d, cpid %d\n",
comp->pid, comp->s_counter, cpid);
#endif
if (comp->pid != cpid)
{
IPCOM_LOG0(ERR, "iprohc_comp_unlck: released by a different process");
return;
}
/* decrease the counter */
comp->s_counter --;
if (comp->s_counter == 0)
{
/* clear the semaphore PID */
comp->pid = 0;
/* release the semaphore */
ipcom_mutex_unlock(comp->code_mutex);
}
#ifdef ROHC_DEBUG
ipcom_printf("iprohc_comp_unlck: pid %d, counter %d, cpid %d\n",
comp->pid, comp->s_counter, cpid);
#endif
}
/*
*===========================================================================
* iprohc_c_context_lck
*===========================================================================
* Description: This function provides a recursive semaphore lock to an ROHC
* compression context.
* Parameters:
* Returns:
*
*/
IP_PUBLIC void
iprohc_c_context_lck(Iprohc_c_context *context)
{
Ip_pid_t cpid = ipcom_getpid();
#ifdef ROHC_DEBUG
ipcom_printf("Calling iprohc_c_context_lck: pid %d, counter %d, cpid %d\n",
context->pid, context->s_counter, cpid);
#endif
if (context->pid == 0)
{
/* No one has semaphore, take it */
context->pid = cpid;
context->s_counter = 1;
ipcom_mutex_lock(context->code_mutex);
}
else if (context->pid != cpid)
{
/* block a different process/task */
ipcom_mutex_lock(context->code_mutex);
context->pid = cpid;
context->s_counter++;
}
else
/* the semaphore is taken by the same process, increase the counter */
context->s_counter ++;
#ifdef ROHC_DEBUG
ipcom_printf("iprohc_c_context_lck: pid %d, counter %d, cpid %d\n",
context->pid, context->s_counter, cpid);
#endif
}
/*
*===========================================================================
* iprohc_c_context_unlck
*===========================================================================
* Description: This function provides a recursive semaphore unlock to an
* ROHC compression context.
* Parameters:
* Returns:
*
*/
IP_PUBLIC void
iprohc_c_context_unlck(Iprohc_c_context *context)
{
Ip_pid_t cpid = ipcom_getpid();
#ifdef ROHC_DEBUG
ipcom_printf("Enter iprohc_c_context_unlck: pid %d, counter %d, cpid %d\n",
context->pid, context->s_counter, cpid);
#endif
if (context->pid != cpid)
{
IPCOM_LOG0(ERR,"iprohc_c_context_unlck: released by different process");
return;
}
/* decrease the counter */
context->s_counter --;
if (context->s_counter == 0)
{
/* clear the semaphore PID */
context->pid = 0;
/* release the semaphore */
ipcom_mutex_unlock(context->code_mutex);
}
#ifdef ROHC_DEBUG
ipcom_printf("iprohc_c_context_unlck: pid %d, counter %d, cpid %d\n",
context->pid, context->s_counter, cpid);
#endif
}
#endif /* !IP_PORT_VXWORKS */
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/