From 0dc2be41d36ed8b3b1e88a03c07a823cc9eeac00 Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Sat, 12 Aug 1995 01:10:57 +0000 Subject: [PATCH] dont allow res id reuse --- src/libCom/fdmgr.c | 170 ++++++++++++++++++++++++++++++++------------- 1 file changed, 122 insertions(+), 48 deletions(-) diff --git a/src/libCom/fdmgr.c b/src/libCom/fdmgr.c index f5d3a8cee..eb047bb75 100644 --- a/src/libCom/fdmgr.c +++ b/src/libCom/fdmgr.c @@ -66,6 +66,10 @@ * problem (send call back discarded when fdmgr pend * event time out expires even if the send call back * has not been called at least once). + * .18 joh 051995 Changed the semantics of alarm create/delete + * routines in a backwards compatible way so that + * we eliminate delete ambiguity (chance of the same + * being reused). * * NOTES: * @@ -73,22 +77,7 @@ * with the lower likelyhood of select blocking * on a fd write. * - * .02 joh 012093 **** WARNING **** - * Assume that a timer id returned by fdmgr_add_timeout() - * will be reused (and returned from a subsequent call to - * fdmgr_add_timeout()) after either of the following two - * circumstances occur: - * 1) You delete the timer referenced by the timer id with - * fdmgr_clear_timeout() - * 2) The timer expires (and the handler which you - * have established for the timer id is executed) - * Take care not to attempt to delete a timer which - * has already expired (and therefore executed your timer - * expiration handler subroutine). Attempting to - * delete a timer which has already expired could - * result in deletion of the wrong timer. - * - * .03 joh 012193 terse DOCUMENTATION has been added to the header file + * .02 joh 012193 terse DOCUMENTATION has been added to the header file * share/epicsH/fdmgr.h * */ @@ -102,7 +91,19 @@ static char *pSccsId = "@(#) $Id$"; #include #include #include -#include + +/* + * Yuk + */ +#if defined (MULTINET) +# define select_errno socket_errno +#elif defined (WINTCP) +# define select_errno uerrno + extern int uerrno; +#else +# include +# define select_errno errno +#endif #ifdef vxWorks #include @@ -116,6 +117,10 @@ static char *pSccsId = "@(#) $Id$"; #include #include +#include + +#define NOBSDNETPROTO +#include #ifndef TRUE #define TRUE 1 @@ -151,6 +156,15 @@ typedef struct{ int delete_pending; }fdentry; +typedef struct{ + ELLNODE node; + struct timeval t; + void (*func)(void *pParam); + void *param; + enum alarm_list_type alt; + unsigned id; +}fdmgrAlarm; + #if defined(vxWorks) # define LOCK(PFDCTX) assert(semTake((PFDCTX)->lock, WAIT_FOREVER)==OK); # define UNLOCK(PFDCTX) assert(semGive((PFDCTX)->lock)==OK); @@ -169,7 +183,7 @@ typedef struct{ # define UNLOCK_FD_HANDLER(PFDCTX) \ assert(semGive((PFDCTX)->fd_handler_lock)==OK); -#elif defined(UNIX) || defined(VMS) || defined(_WIN32) +#elif defined(UNIX) || defined(VMS) || defined(WIN32) # define LOCK(PFDCTX) # define UNLOCK(PFDCTX) # define UNLOCK_FDMGR_PEND_EVENT(PFDCTX) \ @@ -228,6 +242,16 @@ fdctx *fdmgr_init(void) fdctx *pfdctx; pfdctx = (fdctx *) calloc(1, sizeof(fdctx)); + if (!pfdctx) { + return pfdctx; + } + + pfdctx->pAlarmBucket = bucketCreate (1024); + if (!pfdctx->pAlarmBucket) { + free (pfdctx); + return NULL; + } + # if defined(vxWorks) pfdctx->lock = semMCreate (SEM_DELETE_SAFE); if (pfdctx->lock == NULL){ @@ -248,6 +272,7 @@ fdctx *fdmgr_init(void) pfdctx->clk_rate = sysClkRateGet(); pfdctx->last_tick_count = tickGet(); # endif + ellInit(&pfdctx->fdentry_list); ellInit(&pfdctx->fdentry_in_use_list); ellInit(&pfdctx->fdentry_free_list); @@ -255,6 +280,7 @@ fdctx *fdmgr_init(void) ellInit(&pfdctx->expired_alarm_list); ellInit(&pfdctx->free_alarm_list); + /* * returns NULL if unsuccessful */ @@ -269,7 +295,9 @@ fdctx *fdmgr_init(void) */ int fdmgr_delete(fdctx *pfdctx) { - int status; + int status; + fdmgrAlarm *palarm; + fdmgrAlarm *pnext; if(!pfdctx){ return ERROR; @@ -289,7 +317,17 @@ int fdmgr_delete(fdctx *pfdctx) ellFree(&pfdctx->fdentry_list); ellFree(&pfdctx->fdentry_in_use_list); ellFree(&pfdctx->fdentry_free_list); - ellFree(&pfdctx->alarm_list); + for ( palarm = (fdmgrAlarm *) ellFirst (&pfdctx->alarm_list); + palarm; + palarm = pnext) { + pnext = (fdmgrAlarm *) ellNext (&palarm->node); + status = bucketRemoveItemUnsignedId( + pfdctx->pAlarmBucket, + &palarm->id); + assert (status == S_bucket_success); + free (palarm); + } + bucketFree (pfdctx->pAlarmBucket); ellFree(&pfdctx->expired_alarm_list); ellFree(&pfdctx->free_alarm_list); @@ -300,26 +338,26 @@ int fdmgr_delete(fdctx *pfdctx) /* * fdmgr_add_timeout() */ -fdmgrAlarm *fdmgr_add_timeout( +fdmgrAlarmId fdmgr_add_timeout( fdctx *pfdctx, struct timeval *ptimeout, void (*func)(void *), void *param ) { - fdmgrAlarm *palarm=NULL; - fdmgrAlarm *pa; + fdmgrAlarm *palarm=NULL; + fdmgrAlarm *pa; struct timeval t; int status; if(ptimeout->tv_sec < 0) - return NULL; + return fdmgrNoAlarm; if(ptimeout->tv_usec < 0) - return NULL; + return fdmgrNoAlarm; status = fdmgr_gettimeval(pfdctx, &t); if(status < 0) - return NULL; + return fdmgrNoAlarm; LOCK(pfdctx); palarm = (fdmgrAlarm *) ellGet(&pfdctx->free_alarm_list); @@ -327,14 +365,33 @@ void *param if(!palarm){ palarm = (fdmgrAlarm *) malloc(sizeof(fdmgrAlarm)); if(!palarm){ - return NULL; + return fdmgrNoAlarm; } } /* * force all fields to a known state */ - memset((char *)palarm, 0, sizeof(*palarm)); + memset ((char *)palarm, 0, sizeof(*palarm)); + + do { + pfdctx->nextAlarmId++; + palarm->id = pfdctx->nextAlarmId; + status = bucketAddItemUnsignedId ( + pfdctx->pAlarmBucket, + &palarm->id, + palarm); + if (status == S_bucket_noMemory) { + free (palarm); + return fdmgrNoAlarm; + } + } while (status == S_bucket_idInUse); + + if (status != S_bucket_success) { + free (palarm); + errMessage (status, "Alarm installation failed"); + return fdmgrNoAlarm; + } ptimeout->tv_sec += ptimeout->tv_usec/USEC_PER_SEC; ptimeout->tv_usec = ptimeout->tv_usec%USEC_PER_SEC; @@ -364,7 +421,10 @@ void *param } } if(pa){ - ellInsert(&pfdctx->alarm_list, pa->node.previous, &palarm->node); + ellInsert ( + &pfdctx->alarm_list, + pa->node.previous, + &palarm->node); } else{ ellAdd(&pfdctx->alarm_list, &palarm->node); @@ -372,22 +432,33 @@ void *param palarm->alt = alt_alarm; UNLOCK(pfdctx); - return (void *) palarm; + return pfdctx->nextAlarmId; } /* - * * fdmgr_clear_timeout() - * */ int fdmgr_clear_timeout( fdctx *pfdctx, -fdmgrAlarm *palarm +fdmgrAlarmId id ) { int status; enum alarm_list_type alt; + fdmgrAlarm *palarm; + + palarm = bucketLookupItemUnsignedId ( + pfdctx->pAlarmBucket, + &id); + if (!palarm) { + return ERROR; + } + + status = bucketRemoveItemUnsignedId( + pfdctx->pAlarmBucket, + &id); + assert (status == S_bucket_success); status = ERROR; @@ -657,7 +728,7 @@ struct timeval *ptimeout { int status; struct timeval t; - fdmgrAlarm *palarm; + fdmgrAlarmId alarmId; lockFDMGRPendEvent(pfdctx); @@ -673,22 +744,22 @@ struct timeval *ptimeout /* * silence gcc warnings */ - palarm = NULL; + alarmId = fdmgrNoAlarm; } else{ pfdctx->select_tmo = FALSE; - palarm = fdmgr_add_timeout( + alarmId = fdmgr_add_timeout( pfdctx, ptimeout, select_alarm, pfdctx); - if(!palarm){ + if (alarmId==fdmgrNoAlarm) { return ERROR; } process_alarm_queue(pfdctx, &t); } - while(TRUE){ + while (TRUE) { status = fdmgr_select(pfdctx, &t); process_alarm_queue(pfdctx, &t); if(status){ @@ -698,8 +769,8 @@ struct timeval *ptimeout break; } - if(pfdctx->select_tmo==FALSE) - fdmgr_clear_timeout(pfdctx, palarm); + if(pfdctx->select_tmo==FALSE && alarmId != fdmgrNoAlarm) + fdmgr_clear_timeout(pfdctx, alarmId); UNLOCK_FDMGR_PEND_EVENT(pfdctx); @@ -745,7 +816,7 @@ struct timeval *ptimeout taskSafe(); # endif # if defined (__hpux) - status = select( + status = select ( pfdctx->maxfd, (int *)&pfdctx->readch, (int *)&pfdctx->writech, @@ -766,9 +837,9 @@ struct timeval *ptimeout return labor_performed; } else if(status < 0){ - if(errno == EINTR) + if(select_errno == EINTR) ; - else if(errno == EINVAL) + else if(select_errno == EINVAL) fdmgrPrintf( "fdmgr: bad select args ? %d %d %d\n", pfdctx->maxfd, @@ -777,7 +848,7 @@ struct timeval *ptimeout else fdmgrPrintf( "fdmgr: error from select %s\n", - strerror(errno)); + strerror(select_errno)); return labor_performed; } @@ -888,6 +959,10 @@ struct timeval *poffset ellDelete(&pfdctx->alarm_list, &pa->node); ellAdd(&pfdctx->expired_alarm_list, &pa->node); pa->alt = alt_expired; + status = bucketRemoveItemUnsignedId( + pfdctx->pAlarmBucket, + &pa->id); + assert (status == S_bucket_success); } UNLOCK(pfdctx); @@ -984,7 +1059,7 @@ struct timeval *pt { struct timezone tz; - return gettimeofday(pt, &tz); + return gettimeofday (pt, &tz); } #endif @@ -996,7 +1071,7 @@ struct timeval *pt * * */ -#ifdef _WIN32 +#ifdef WIN32 LOCAL int fdmgr_gettimeval( fdctx *pfdctx, struct timeval *pt @@ -1004,8 +1079,7 @@ struct timeval *pt { SYSTEMTIME st; GetSystemTime(&st); - pt->tv_sec = (long)st.wSecond + (long)st.wMinute*60 + (long)st.wHour*360 -0; + pt->tv_sec = (long)st.wSecond + (long)st.wMinute*60 + (long)st.wHour*3600; pt->tv_usec = st.wMilliseconds*1000; return 0;