From f57df209ab73ec6c604a3da8e0545da181094f6b Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Mon, 23 Sep 2002 17:05:47 +0000 Subject: [PATCH] fixed SPARC alignment with ca put notify --- src/rsrv/camessage.c | 202 +++++++++++++++++++++++++++++++--------- src/rsrv/caservertask.c | 23 ++--- src/rsrv/server.h | 40 +++----- 3 files changed, 183 insertions(+), 82 deletions(-) diff --git a/src/rsrv/camessage.c b/src/rsrv/camessage.c index b3bfd1234..16c9d10de 100644 --- a/src/rsrv/camessage.c +++ b/src/rsrv/camessage.c @@ -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->valueSizepPutNotify); - 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 */ diff --git a/src/rsrv/caservertask.c b/src/rsrv/caservertask.c index b9004ae14..33c854d87 100644 --- a/src/rsrv/caservertask.c +++ b/src/rsrv/caservertask.c @@ -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; diff --git a/src/rsrv/server.h b/src/rsrv/server.h index 3ed60166f..46ae1aa91 100644 --- a/src/rsrv/server.h +++ b/src/rsrv/server.h @@ -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