fixed SPARC alignment with ca put notify

This commit is contained in:
Jeff Hill
2002-09-23 17:05:47 +00:00
parent 03717d7944
commit f57df209ab
3 changed files with 183 additions and 82 deletions

View File

@@ -51,6 +51,36 @@ LOCAL EVENTFUNC read_reply;
#define logBadId(CLIENT, MP, PPL)\
logBadIdWithFileAndLineno(CLIENT, MP, PPL, __FILE__, __LINE__)
/*
* for tracking db put notifies
*/
typedef struct rsrv_put_notify {
ELLNODE node;
putNotify dbPutNotify;
caHdrLargeArray msg;
unsigned valueSize; /* size of block pointed to by dbPutNotify */
char busy; /* put notify in progress */
char onExtraLaborQueue;
/*
* Include a union of all scalar types
* including fixed length strings so
* that in many cases we can avoid
* allocating another buffer and only
* use an rsrv_put_notify from its
* free list.
*/
union {
dbr_string_t strval;
dbr_short_t shrtval;
dbr_short_t intval;
dbr_float_t fltval;
dbr_enum_t enmval;
dbr_char_t charval;
dbr_long_t longval;
dbr_double_t doubleval;
} dbrScalarValue;
} RSRVPUTNOTIFY;
/*
* casCalloc()
*
@@ -1478,6 +1508,116 @@ LOCAL void putNotifyErrorReply ( struct client *client, caHdrLargeArray *mp, int
SEND_UNLOCK ( client );
}
void initializePutNotifyFreeList ()
{
if ( ! rsrvPutNotifyFreeList ) {
freeListInitPvt ( &rsrvPutNotifyFreeList,
sizeof(struct rsrv_put_notify), 512 );
assert ( rsrvPutNotifyFreeList );
}
}
static struct rsrv_put_notify *
rsrvAllocPutNotify ( struct channel_in_use * pciu )
{
struct rsrv_put_notify *pNotify;
if ( rsrvPutNotifyFreeList ) {
pNotify = (RSRVPUTNOTIFY *)
freeListCalloc ( rsrvPutNotifyFreeList );
if ( pNotify ) {
pNotify->dbPutNotify.pbuffer =
&pNotify->dbrScalarValue;
pNotify->valueSize =
sizeof (pNotify->dbrScalarValue);
pNotify->dbPutNotify.usrPvt = pciu;
pNotify->dbPutNotify.paddr = &pciu->addr;
pNotify->dbPutNotify.userCallback =
write_notify_call_back;
}
}
else {
pNotify = NULL;
}
return pNotify;
}
static int rsrvExpandPutNotify (
struct rsrv_put_notify * pNotify, unsigned sizeNeeded )
{
int booleanStatus;
if ( sizeNeeded > pNotify->valueSize ) {
/*
* try to use the union embeded in the free list
* item, but allocate a random sized block if they
* writing a vector.
*/
if ( pNotify->valueSize >
sizeof (pNotify->dbrScalarValue) ) {
free ( pNotify->dbPutNotify.pbuffer );
}
pNotify->dbPutNotify.pbuffer = casCalloc(1,sizeNeeded);
if ( pNotify->dbPutNotify.pbuffer ) {
pNotify->valueSize = sizeNeeded;
booleanStatus = TRUE;
}
else {
/*
* revert back to the embedded union
*/
pNotify->dbPutNotify.pbuffer =
&pNotify->dbrScalarValue;
pNotify->valueSize =
sizeof (pNotify->dbrScalarValue);
booleanStatus = FALSE;
}
}
else {
booleanStatus = TRUE;
}
return booleanStatus;
}
unsigned rsrvSizeOfPutNotify ( struct rsrv_put_notify *pNotify )
{
unsigned size = sizeof ( *pNotify );
if ( pNotify ) {
if ( pNotify->valueSize >
sizeof ( pNotify->dbrScalarValue ) ) {
size += pNotify->valueSize;
}
}
return size;
}
void rsrvFreePutNotify ( client *pClient,
struct rsrv_put_notify *pNotify )
{
if ( pNotify ) {
/*
* if the put notify is outstanding then cancel it
*/
if ( pNotify->busy ) {
dbNotifyCancel ( &pNotify->dbPutNotify );
}
epicsMutexMustLock ( pClient->putNotifyLock );
if ( pNotify->onExtraLaborQueue ) {
ellDelete ( &pClient->putNotifyQue,
&pNotify->node );
}
epicsMutexUnlock ( pClient->putNotifyLock );
if ( pNotify->valueSize >
sizeof(pNotify->dbrScalarValue) ) {
free ( pNotify->dbPutNotify.pbuffer );
}
freeListFree ( rsrvPutNotifyFreeList, pNotify );
}
}
/*
* write_notify_action()
*/
@@ -1507,7 +1647,7 @@ LOCAL int write_notify_action ( caHdrLargeArray *mp, void *pPayload,
size = dbr_size_n (mp->m_dataType, mp->m_count);
if (pciu->pPutNotify) {
if ( pciu->pPutNotify ) {
/*
* serialize concurrent put notifies
@@ -1523,35 +1663,26 @@ LOCAL int write_notify_action ( caHdrLargeArray *mp, void *pPayload,
return RSRV_OK;
}
}
/*
* if not busy then free the current
* block if it is to small
*/
if(pciu->pPutNotify->valueSize<size){
free(pciu->pPutNotify);
pciu->pPutNotify = NULL;
}
}
/*
* send error and go to next request
* if there isnt enough memory left
*/
if(!pciu->pPutNotify){
pciu->pPutNotify = (RSRVPUTNOTIFY *)
casCalloc(1, sizeof(*pciu->pPutNotify)+size);
if(!pciu->pPutNotify){
else {
pciu->pPutNotify = rsrvAllocPutNotify ( pciu );
if ( ! pciu->pPutNotify ) {
/*
* send error and go to next request
* if there isnt enough memory left
*/
log_header ( "no memory to initiate put notify",
client, mp, pPayload, 0 );
putNotifyErrorReply (client, mp, ECA_ALLOCMEM);
return RSRV_ERROR;
}
pciu->pPutNotify->valueSize = size;
pciu->pPutNotify->dbPutNotify.pbuffer = (pciu->pPutNotify+1);
pciu->pPutNotify->dbPutNotify.usrPvt = pciu;
pciu->pPutNotify->dbPutNotify.paddr = &pciu->addr;
pciu->pPutNotify->dbPutNotify.userCallback = write_notify_call_back;
}
if ( ! rsrvExpandPutNotify ( pciu->pPutNotify, size ) ) {
log_header ( "no memory to initiate vector put notify",
client, mp, pPayload, 0 );
putNotifyErrorReply ( client, mp, ECA_ALLOCMEM );
return RSRV_ERROR;
}
pciu->pPutNotify->busy = TRUE;
@@ -1690,7 +1821,8 @@ LOCAL int event_add_action (caHdrLargeArray *mp, void *pPayload, struct client *
/*
* clear_channel_reply()
*/
LOCAL int clear_channel_reply ( caHdrLargeArray *mp, void *pPayload, struct client *client )
LOCAL int clear_channel_reply ( caHdrLargeArray *mp,
void *pPayload, struct client *client )
{
struct event_ext *pevext;
struct channel_in_use *pciu;
@@ -1707,19 +1839,7 @@ LOCAL int clear_channel_reply ( caHdrLargeArray *mp, void *pPayload, struct clie
return RSRV_ERROR;
}
/*
* if a put notify is outstanding then cancel it
*/
if(pciu->pPutNotify){
if(pciu->pPutNotify->busy){
dbNotifyCancel ( &pciu->pPutNotify->dbPutNotify );
}
epicsMutexMustLock ( client->putNotifyLock );
if ( pciu->pPutNotify->onExtraLaborQueue ) {
ellDelete ( &client->putNotifyQue, &pciu->pPutNotify->node );
}
epicsMutexUnlock ( client->putNotifyLock );
}
rsrvFreePutNotify ( client, pciu->pPutNotify );
while (TRUE){
epicsMutexMustLock(client->eventqLock);
@@ -1744,11 +1864,7 @@ LOCAL int clear_channel_reply ( caHdrLargeArray *mp, void *pPayload, struct clie
SEND_UNLOCK(client);
return RSRV_ERROR;
}
if (pciu->pPutNotify) {
free (pciu->pPutNotify);
}
/*
* send delete confirmed message
*/

View File

@@ -166,7 +166,7 @@ LOCAL int req_server (void)
}
/* listen and accept new connections */
if ( listen ( IOC_sock, 10 ) < 0 ) {
if ( listen ( IOC_sock, 20 ) < 0 ) {
errlogPrintf ("CAS: Listen error\n");
socket_close (IOC_sock);
epicsThreadSuspendSelf ();
@@ -239,6 +239,7 @@ epicsShareFunc int epicsShareAPI rsrv_init (void)
freeListInitPvt ( &rsrvChanFreeList, sizeof(struct channel_in_use), 512 );
freeListInitPvt ( &rsrvEventFreeList, sizeof(struct event_ext), 512 );
freeListInitPvt ( &rsrvSmallBufFreeListTCP, MAX_TCP, 16 );
initializePutNotifyFreeList ();
status = envGetLongConfigParam ( &EPICS_CA_MAX_ARRAY_BYTES, &maxBytesAsALong );
if ( status || maxBytesAsALong < 0 ) {
@@ -264,7 +265,6 @@ epicsShareFunc int epicsShareAPI rsrv_init (void)
}
}
freeListInitPvt ( &rsrvLargeBufFreeListTCP, rsrvSizeofLargeBufTCP, 1 );
ellInit ( &beaconAddrList );
prsrv_cast_client = NULL;
pCaBucket = NULL;
@@ -363,10 +363,7 @@ LOCAL void log_one_client (struct client *client, unsigned level)
while (pciu){
bytes_reserved += sizeof(struct channel_in_use);
bytes_reserved += sizeof(struct event_ext)*ellCount(&pciu->eventq);
if(pciu->pPutNotify){
bytes_reserved += sizeof(*pciu->pPutNotify);
bytes_reserved += pciu->pPutNotify->valueSize;
}
bytes_reserved += rsrvSizeOfPutNotify ( pciu->pPutNotify );
pciu = (struct channel_in_use *) ellNext(&pciu->node);
}
epicsMutexUnlock(client->addrqLock);
@@ -449,12 +446,15 @@ void epicsShareAPI casr (unsigned level)
freeListItemsAvail ( rsrvSmallBufFreeListTCP );
bytes_reserved += rsrvSizeofLargeBufTCP *
freeListItemsAvail ( rsrvLargeBufFreeListTCP );
bytes_reserved += rsrvSizeOfPutNotify ( 0 ) *
freeListItemsAvail ( rsrvPutNotifyFreeList );
printf( "There are currently %u bytes on the server's free list\n",
bytes_reserved);
printf( "%u client(s), %u channel(s), %u event(s) (monitors)\n",
printf( "%u client(s), %u channel(s), %u event(s) (monitors) %u putNotify(s)\n",
freeListItemsAvail (rsrvClientFreeList),
freeListItemsAvail (rsrvChanFreeList),
freeListItemsAvail (rsrvEventFreeList));
freeListItemsAvail (rsrvEventFreeList),
freeListItemsAvail ( rsrvPutNotifyFreeList ));
printf( "%u small buffers (%u bytes ea), and %u jumbo buffers (%u bytes ea)\n",
freeListItemsAvail ( rsrvSmallBufFreeListTCP ), MAX_TCP,
freeListItemsAvail ( rsrvLargeBufFreeListTCP ), rsrvSizeofLargeBufTCP );
@@ -601,12 +601,7 @@ void destroy_tcp_client ( struct client *client )
}
freeListFree (rsrvEventFreeList, pevext);
}
if (pciu->pPutNotify) {
if ( pciu->pPutNotify->busy ) {
dbNotifyCancel ( &pciu->pPutNotify->dbPutNotify );
}
free ( pciu->pPutNotify );
}
rsrvFreePutNotify ( client, pciu->pPutNotify );
LOCK_CLIENTQ;
status = bucketRemoveItemUnsignedId ( pCaBucket, &pciu->sid);
UNLOCK_CLIENTQ;

View File

@@ -97,37 +97,22 @@ typedef struct client {
char disconnect; /* disconnect detected */
} client;
/*
* for tracking db put notifies
*/
typedef struct rsrv_put_notify {
ELLNODE node;
putNotify dbPutNotify;
caHdrLargeArray msg;
unsigned valueSize; /* size of block pointed to by dbPutNotify */
char busy; /* put notify in progress */
char onExtraLaborQueue;
} RSRVPUTNOTIFY;
/*
* per channel structure
* (stored in addrq off of a client block)
*/
struct channel_in_use {
ELLNODE node;
ELLLIST eventq;
struct client *client;
RSRVPUTNOTIFY *pPutNotify; /* potential active put notify */
const unsigned cid; /* client id */
const unsigned sid; /* server id */
epicsTimeStamp time_at_creation; /* for UDP timeout */
struct dbAddr addr;
ASCLIENTPVT asClientPVT;
ELLNODE node;
ELLLIST eventq;
struct client *client;
struct rsrv_put_notify *pPutNotify; /* potential active put notify */
const unsigned cid; /* client id */
const unsigned sid; /* server id */
epicsTimeStamp time_at_creation; /* for UDP timeout */
struct dbAddr addr;
ASCLIENTPVT asClientPVT;
};
/*
* Event block extension for channel access
* some things duplicated for speed
@@ -177,6 +162,7 @@ GLBLTYPE void *rsrvEventFreeList;
GLBLTYPE void *rsrvSmallBufFreeListTCP;
GLBLTYPE void *rsrvLargeBufFreeListTCP;
GLBLTYPE unsigned rsrvSizeofLargeBufTCP;
GLBLTYPE void *rsrvPutNotifyFreeList;
#define CAS_HASH_TABLE_SIZE 4096
@@ -191,7 +177,7 @@ void cas_send_bs_msg ( struct client *pclient, int lock_needed );
void cas_send_dg_msg ( struct client *pclient );
int rsrv_online_notify_task (void);
int cast_server (void);
struct client *create_client ();
struct client *create_client ( SOCKET sock, int proto );
void destroy_client ( struct client * );
struct client *create_tcp_client ( SOCKET sock );
void destroy_tcp_client ( struct client * );
@@ -200,6 +186,10 @@ int camessage ( struct client *client );
void write_notify_reply ( void *pArg );
int rsrvCheckPut ( const struct channel_in_use *pciu );
int rsrv_version_reply ( struct client *client );
void rsrvFreePutNotify ( struct client *pClient,
struct rsrv_put_notify *pNotify );
void initializePutNotifyFreeList (void);
unsigned rsrvSizeOfPutNotify ( struct rsrv_put_notify *pNotify );
/*
* inclming protocol maintetnance