diff --git a/src/db/Makefile b/src/db/Makefile index 8cca632b9..1397c10a2 100644 --- a/src/db/Makefile +++ b/src/db/Makefile @@ -1,7 +1,77 @@ TOP=../.. -include $(TOP)/config/CONFIG_BASE +include $(TOP)/configure/CONFIG -include $(TOP)/config/RULES_ARCHS +# includes to install from this sub-project +# +INC += drvSup.h +INC += callback.h +INC += dbLock.h +INC += dbAccess.h +INC += dbConvert.h +INC += dbEvent.h +INC += dbScan.h +INC += db_access.h +INC += dbAddr.h +INC += db_field_log.h +INC += initHooks.h +INC += recSup.h +INC += devSup.h +INC += taskwd.h +INC += recGbl.h +INC += dbBkpt.h +MENUS += menuAlarmSevr.h +MENUS += menuAlarmStat.h +MENUS += menuArrType.h +MENUS += menuCompress.h +MENUS += menuFtype.h +MENUS += menuIvoa.h +MENUS += menuLinr.h +MENUS += menuOmsl.h +MENUS += menuPriority.h +MENUS += menuScan.h +MENUS += menuYesNo.h + +RECTYPES += dbCommon.h +USER_DBDFLAGS += -I .. + +DBDINSTALL += dbCommonRecord.dbd +DBDINSTALL += menuGlobal.dbd + +#=================================================== + +USR_CFLAGS += -ansi + +dbLib_SRCS = \ + dbLock.c\ + dbAccess.c\ + dbBkpt.c\ + dbConvert.c\ + dbFastLinkConv.c\ + dbNotify.c \ + iocInit.c\ + dbScan.c\ + dbEvent.c\ + dbTest.c\ + db_access.c\ + db_test.c\ + recGbl.c\ + callback.c\ + taskwd.c\ + dbCa.c \ + initHooks.c \ + dbcar.c + + +IOC_LIBRARY_vxWorks = dbLib + +#=================================================== + +include $(TOP)/configure/RULES_BUILD + +dbCommon.h: ../dbCommonRecord.dbd ../dbCommon.dbd + $(RM) $@ + $(EPICS_BASE)/bin/$(HOST_ARCH)/dbToRecordtypeH$(EXE) \ + $(USER_DBDFLAGS) $< diff --git a/src/db/Makefile.Host b/src/db/Makefile.Host deleted file mode 100644 index 4a1556c75..000000000 --- a/src/db/Makefile.Host +++ /dev/null @@ -1,53 +0,0 @@ -# Makefile.Host for base/src/db -# -# - -TOP = ../../.. -include $(TOP)/config/CONFIG_BASE - -# includes to install from this sub-project -# -INC += drvTS.h -INC += drvSup.h -INC += callback.h -INC += dbLock.h -INC += dbAccess.h -INC += dbConvert.h -INC += dbEvent.h -INC += dbScan.h -INC += db_access.h -INC += dbAddr.h -INC += db_field_log.h -INC += fast_lock.h -INC += initHooks.h -INC += recSup.h -INC += devSup.h -INC += taskwd.h -INC += recGbl.h -INC += dbBkpt.h -INC += devLib.h - -MENUS += menuAlarmSevr.h -MENUS += menuAlarmStat.h -MENUS += menuArrType.h -MENUS += menuCompress.h -MENUS += menuFtype.h -MENUS += menuIvoa.h -MENUS += menuLinr.h -MENUS += menuOmsl.h -MENUS += menuPriority.h -MENUS += menuScan.h -MENUS += menuYesNo.h - -RECTYPES += dbCommon.h -USER_DBDFLAGS += -I .. - -DBDINSTALL += dbCommonRecord.dbd -DBDINSTALL += menuGlobal.dbd - -include $(TOP)/config/RULES.Host - -dbCommon.h: ../dbCommonRecord.dbd ../dbCommon.dbd - $(RM) $@ - $(EPICS_BASE)/bin/$(HOST_ARCH)/dbToRecordtypeH$(EXE) \ - $(USER_DBDFLAGS) $< diff --git a/src/db/Makefile.Vx b/src/db/Makefile.Vx deleted file mode 100644 index 336b7c8ce..000000000 --- a/src/db/Makefile.Vx +++ /dev/null @@ -1,62 +0,0 @@ -TOP = ../../.. -include $(TOP)/config/CONFIG_BASE - -USER_DBDFLAGS += -I .. -USR_CFLAGS += -ansi - -SRCS.c = \ - ../dbLock.c\ - ../dbAccess.c\ - ../dbBkpt.c\ - ../dbConvert.c\ - ../dbFastLinkConv.c\ - ../dbNotify.c\ - ../iocInit.c\ - ../drvTS.c\ - ../dbScan.c \ - ../dbEvent.c\ - ../dbTest.c\ - ../db_access.c \ - ../db_test.c\ - ../recGbl.c\ - ../callback.c\ - ../taskwd.c \ - ../dbCa.c\ - ../dbcar.c\ - ../devLib.c\ - ../devLibVxWorks.c\ - ../initHooks.c - -LIBOBJS = \ - dbLock.o\ - dbAccess.o\ - dbBkpt.o\ - dbConvert.o\ - dbFastLinkConv.o\ - dbNotify.o \ - iocInit.o\ - drvTS.o\ - dbScan.o\ - dbEvent.o\ - dbTest.o\ - db_access.o\ - db_test.o\ - recGbl.o\ - callback.o\ - taskwd.o\ - dbCa.o \ - dbcar.o \ - devLib.o \ - devLibVxWorks.o - -PROD += initHooks.o - -LIBNAME = dbLib - -include $(TOP)/config/RULES.Vx - -dbCommon.h: ../dbCommonRecord.dbd ../dbCommon.dbd - $(RM) $@ - $(EPICS_BASE)/bin/$(HOST_ARCH)/dbToRecordtypeH$(EXE) \ - $(USER_DBDFLAGS) $< - diff --git a/src/db/TSdriver.html b/src/db/TSdriver.html deleted file mode 100644 index 7cca95bd3..000000000 --- a/src/db/TSdriver.html +++ /dev/null @@ -1,466 +0,0 @@ - - - - - - Synchronized Time Stamp Support - - - -

-Synchronized Time Stamp Support

-Author: Jim Kowalkowski -

-MODIFICATION: 04AUG1998 (Marty Kraimer)

-The routine TSsetClockFromUnix was made global. Calling it forces a resynchronization -with a host time server. This is useful to force a master timing ioc to -resynchronize. -

-Introduction

- -

-Purpose

-New software has been added to IOC core to maintain time stamps. The new -software has the ability to maintain time stamps over all IOCs on a network. -The purpose of this paper is to explain how EPICS will synchronize the -time stamps. In addition, this paper will explain how to configure and -use the new EPICS time stamp support software. -

-Definitions

-Time Stamp: Two long words representing the time in seconds/nanoseconds -past an epoch. The first long word represents the seconds past the epoch, -the second long word represents the nanoseconds within the second. The -EPICS epoch is currently January 1, 1990. A commonly used Unix epoch in -January 1,1900 or in vxWorks case, January 1,1970. -

Event System: A hardware based subsystem for delivering events to all -IOCs on a network. Typical events are the "tick" event and the "reset counter" -event. -

Event System Synchronized Time: Time stamps maintained using an event -system. The clock pulses which increment the time stamps are provided by -a single source, all IOCs increment time stamps using the single source -pulse. -

Soft Time: Each IOC increments the time stamps using it's own internal -clock. -

Master Timing IOC: The IOC which knows the actual time and is the source -of the actual time to all those who inquire. -

Slave IOC: An IOC which relies on a master IOC to provide the actual -time. This IOC will keep it's time stamp in sync with a master. -

Soft Slave: An IOC which uses Soft Time and synchronizes it's time stamp -with a master. -

Event Slave: An IOC which uses Event System Synchronized Time to maintain -it's time stamp. This type of IOC uses the master to verify that it's time -stamp is correct. -

Soft Master: A Master Timing IOC that maintains it's time stamp using -a private clock. -

Event Master: An IOC which uses Event System Synchronized Time and is -a Master Timing IOC. In addition, this IOC is the source of the clock pulses. -

-Overview

-Time stamps are maintained across IOCs using UDP with a master/slave relationship. -A master timing IOC is responsible for knowing the actual time. A slave -IOC uses the master to verify it's own time stamps. Time stamps are maintained -in two fashions: using an event system or using IOC tick counters. Both -differ radically and require some explanation. -

-Event System Support

-The time stamp software has special requirements in order to provide event -system synchronized time. The time stamp software assumes that hardware -is present which has finite counters for counting pulses or ticks delivered -to it from some master tick generator. The software further assumes that -every so other, before the finite counters overflow, a signal or event -will occur to reset the counters to zero. The software requires access -to these counters at any time and notification when the "counter reset" -arrives. The combination of hardware tick counters and reset event notification -gives the software the ability to maintain time. If the event system supports -other events, it is required that the software be notified of the occurrence -of each event. The event time will be recorded in a table which holds one -time stamp for each possible event so that a user can inquire as to when -the event occurred. -

-Soft Time Support

-If no event system is present, the time stamp software can operate in a -software timing mode. In this mode, no events are available, only the current -time can be retrieved. An IOC using soft time will increment a time stamp -using the system clock (usually updated at 60Hz). The master/slave relationship -allows a slave to periodically ask a master for the correct time. At this -point the slave's time stamp can be adjusted to match the masters. -

-Role of a Master Timing IOC

-A master timing IOC has difference responsibilities depending on if it -is an event master or a soft master. An event master will be an event generator -(create "tick" and "counter reset" events). When the event master detects -a "counter reset", it broadcasts the time the event occurred to all event -slaves on the network. The slaves can use the time stamp data to verify -their own time. A soft timing master does not have any events, so no broadcasting -is done. Both soft and event masters have the ability to be queried at -any time by slaves for the current time. -

-Role of a Slave Timing IOC

-A slave timing IOC also has difference responsibilities depending on if -it is an event slave or a soft slave. An event slave contains hardware -to manage "tick" and "counter reset" events. The time stamp support software -uses this information to maintain time. An event slave will listen for -broadcasts from the event master timing IOC and use the information to -verify it's time. A soft slave periodically queries a master timing IOC -to get the current time. -

-Design Specifications Summary

- -

-Event System Synchronized Time

-All IOCs will have identical event times. In addition, all IOCs will maintain -the same current time. -

The minimum events which must be supported is two. One must be used -as a "tick" event and one must be used as a "reset hardware tick counter" -event. The second will be used to update the time stamp representing the -current time. -

An optional event can be used as a "heartbeat" event. This event can -be used to signal errors. -

-Soft Time

-All IOCs of this type will maintain time stamps which are within two clocks -ticks or 1/30th of a second of a master. The master may be a designated -IOC or the Unix boot server. A Unix boot server master or the server pointed -to by the EPICS environment variable EPICS_TS_NTP_INET must have NTP available -for polling. -

-User Level Interface

- -

-General Use Functions

-Three functions exist in the synchronous time stamp support software for -the user to retrieve time stamps: - -To retrieve the time stamp which represents the time that an event occurred, -use TSgetTimeStamp(). TScurrentTimeStamp() can be used to -retrieve the time stamp which represents the time of day. TsLocalTime() -is the function for returning the current time stamp in the old time stamp -driver, the routine can still be used to retrieve this information. The -function TSgetFirstOfYear() attempts to give the caller a time stamp -representing January 1 of the current year relative to the vxWorks epoch -1970. -

An EPICS enironment variable named EPICS_TS_NTP_INET exists which can -be set to point to an NTP server. The default NTP server is the IOC boot -server. -

-Test Functions

-The following functions can be run from the vxWorks shell to give information -about the time stamp driver. - - -

-Debugging Information

-A global variable exists named TSdriverDebug. Setting this variable -to a positive value in the vxWorks start up script will inform the time -stamp driver to print information about what it is doing. The greater the -value, the more information the driver will print. The number can be set -and adjusted to any value any time while the IOC is running. -

-Record Support

-Record support will have the ability to tie the record processing time -to an event. This means that a user can specify that processing of a record -is due to an event (from the event system). When the record gets processed, -the time in the TIME field of the record will be the time when the event -occurred. In order to support the event times from record support, two -new fields will be added to dbCommon. The fields will be Time Stamp Event -(TSE), and Time Stamp Event Link (TSEL). The TSE field will be the actual -event time the user is interested in. The TSEL field will be a link used -to populate the TSE. -

To facilitate the use of the time stamp support software, a new record -support function will be added: -

-This routine uses TSgetTimeStamp(prec->tse, &prec->time) to set the -processing time of the record. The new recGblGetTimeStamp() will replace -the existing call to tsLocalTime(). If the TSE field is zero (the default), -then TSgetTimeStamp() will report the current time. It is important to -remember that if a TSE field is set, then the processing time (in field -TIME) will always reflect the last time the event occurred. -

-Driver Configuration

-The synchronous time stamp support software is configured by calling TSconfigure() -from the "startup.cmd" file. The parameters to this routine are: - -This routine must be run before iocInit(). The synchronous time stamp support -software is initialized as part of iocInit. Running TSreport() after -iocInit() will produce a report which shows the current state of the driver. -

-Event System interface

-The event system interface consists of seven function which can be provided -by an event system. The synchronous time stamp support software uses a -card number of zero on all functions that require a card number. The functions -are as follows: - -The definition are as follows: - -All of these routines are checked to exist when the time stamp support -code initializes. All have some kind of default routine provided if they -are not found, most of which just return an error condition. The functions -which the time stamp support software registers (event and error) have -the following format: - -Here the Card is the event system board of interest (always zero), the -EventNum is the event that occurred, and the Ticks is the number of ticks -since the last board tick counter reset. -

In addition to the above functions, a global variable exists on the -IOC which can be used to indicate that direct time is available. Setting -the variable TSdirectTimeVar to a nonzero value has the same effect -as providing the ErDirectTime() function. -

-Creating Direct Time Support

-Most of the above interface functions apply only when special event hardware -is present. A much simpler configuration is when a GPS is present and time -stamps are distributed using IRIG-B to all or most of the IOCs. The easiest -way to implement this scenario is to define ErDirectTime() to return the -value one and define ErGetTime(). The job of ErGetTime() will be to actually -be to generate and return the time stamp representing the current time -(from the EPICS epoch). At system initialization, the actual time is retrieved -from a Unix server through NTP or the Unix time protocol, so that year -will be valid in the vxWorks time clock. At the GPS driver initialization, -the vxWorks function clock_gettime() can be used to calculate the year. -Record support will internally eventually call ErGetTime() each time the -record is processed. The GPS driver should be included as part of drvSup.ascii, -so it initialized in the proper order. -

-Operation

-An IOC can be configured to run in one of four ways: synchronous-master, -soft-master, synchronous-slave, soft-slave. Each mode maintains time differently. -When the time stamp support code initializes, it determines the mode which -it will operate in based on configuration parameters and event system function -information. -

-Synchronous Time

-Synchronous timing is determined by the presence of event system hardware. -The function ErHaveReceiver() gives this information. All IOCs using synchronous -time will have the exact same time stamps. The "tick" event increments -all IOC's event system tick counters, the "reset tick counter" resets the -counter to zero and posts the event to the time stamp support software. -The time stamp support software system knows the current time by looking -at the last "tick reset event" time and querying the event system with -ErGetTicks() for the number of ticks which have elapsed since the last -reset. Since the event handler function gets called with the "ticks since -last reset", an event time is the last "tick reset event" time plus the -ticks count in the call. -

-Master

-A synchronous master is determined by the first parameter to TSconfigure() -and the presence of event hardware. A master must have an event generator -and an event receiver. Since the event system is configured from EPICS -database records, the database must have records in it to initialize the -event system. The master is responsible for providing the "tick" event -and the "reset tick counter" event. -

When the time stamp support software's event handler function on a master -timing IOC receives a "reset tick counter" event, a time stamp message -is broadcast out on the slave_port (configured by TSconfigure()). The master -timing IOC is also listening on the master_port (also configured by TSconfigure()) -for incoming requests for time stamp information. -

At boot time, a master will set the vxWorks clock from the Unix boot -server time. The time is retrieved from the boot server using NTP or the -time protocol, or the server pointed to by the EPICS environment variable -EPICS_TS_NTP_INET using NTP. The GPS module takes an unknown period of -time to sync to the correct time, so it can not be used until it's time -is valid. The event system is not up and running until record support initialization -is complete, therefore the event system time stamps are not ticking until -the event system initializes. At the time of the first sync, the event -system is known to be up, and the "reset tick counter" or "sync" event -is set to the current time (vxWorks clock). -

-Slave

-A synchronous slave is determined by the first parameter to TSconfigure() -and the presence of event hardware. This mode is automatically selected -if no TSconfigure() call is used in the "startup.cmd" file. This type of -slave must have an event receiver. The EPICS database must be configured -to initialize the event system. -

When a synchronous slave configuration is determined, the IOC broadcasts -a request for master on the master_port port. If a master is found, then -all current time, sync rate, and clock are extracted from the master's -response (the sync rate and clock rate from the TSconfigure() are overwritten -to match the master's configuration). If a master is not found, the slave -IOC goes into a polling mode to try to find a master every two minutes. -While a slave has no master, The IOC's clock is initialized from the Unix -boot server and TSgetTimeStamp() returns the vxWorks time clock value. -

The slave experiences the same problems as the master upon boot. -

-Soft Time

-Soft time IOCs use the 60 hertz clock available from vxWorks to maintain -a time stamp. The IOC will increment a time stamp at a 60 hertz rate. Soft -time is determined by the absence of event system hardware. All soft timing -IOC's will not have the same time stamps. -

-Master

-A soft master is determined by the first parameter of TSconfigure() and -the absence of event hardware. Upon boot, the master soft timing IOC retrieves -the current time from the Unix boot server. The IOC sets up a soft time-stamp -counter using a one tick watch dog and sets the vxWorks clock. From this -point on, the master runs using the soft time-stamp counter. The master -listens on the master_port port for requests for the master's current time. -

-Slave

-A soft slave is determined by the first parameter of TSconfigure() and -the absence of the event hardware. This mode is automatically selected -if no TSconfigure() is present in the "startup.cmd" file. The basic operation -of a soft slave is to synchronize the time stamp with a master when possible -or to the Unix boot server if no master is available. Upon initialization -the time stamp support code determines if a master is present on the network, -and if NTP support is available from the Unix boot server or the server -pointed to by the EPICS environment variable EPICS_TS_NTP_INET. The slave -will request time stamps from a master or unix server at sync_rate_in_seconds -rate from TSconfigure(). If the time stamp on the slave is found to be -off, the clock will be incrementally adjusted so that by the next sync, -the clock will be corrected to match the master's time stamp. A soft slave -will automatically switch between a master and the unix boot server depending -on if the master is available or not. In order to sync with the unix boot -server, NTP must be available there for query only.  -
-

Home page for Jim -Kowalkowski . -
Argonne National Laboratory Copyright -Information -

-jbk@aps.anl.gov (Jim Kowalkowski)
- -
updated 8/10/95 - - diff --git a/src/db/callback.c b/src/db/callback.c index 6e1fdf1e1..103ac3508 100644 --- a/src/db/callback.c +++ b/src/db/callback.c @@ -5,63 +5,43 @@ /* * Original Author: Marty Kraimer * Date: 07-18-91 - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * Modification Log: - * ----------------- - * .01 12-12-91 mrk moved from dbScan.c to callback.c - * .02 04-23-92 jba Fixed test on priority - * .03 06-28-93 mrk In callbackRequest replaced errMessage by logMsg */ - -#include -#include -#include -#include -#include -#include -#include -#include "dbDefs.h" -#include "errlog.h" -#include "callback.h" -#include "dbAccess.h" -#include "recSup.h" -#include "taskwd.h" -#include "errMdef.h" -#include "dbCommon.h" -#include "dbLock.h" -#include "task_params.h" +/********************COPYRIGHT NOTIFICATION********************************** +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +****************************************************************************/ + +#include +#include +#include + +#include "dbDefs.h" +#include "osiSem.h" +#include "osiThread.h" +#include "osiInterrupt.h" +#include "osiRing.h" +#include "errlog.h" +#include "callback.h" +#include "dbAccess.h" +#include "recSup.h" +#include "taskwd.h" +#include "errMdef.h" +#include "dbCommon.h" +#include "dbLock.h" int callbackQueueSize = 2000; -static SEM_ID callbackSem[NUM_CALLBACK_PRIORITIES]; -static RING_ID callbackQ[NUM_CALLBACK_PRIORITIES]; -static int callbackTaskId[NUM_CALLBACK_PRIORITIES]; +static semId callbackSem[NUM_CALLBACK_PRIORITIES]; +static ringId callbackQ[NUM_CALLBACK_PRIORITIES]; +static threadId callbackTaskId[NUM_CALLBACK_PRIORITIES]; static int ringOverflow[NUM_CALLBACK_PRIORITIES]; volatile int callbackRestart=FALSE; +static int priorityValue[NUM_CALLBACK_PRIORITIES] = {0,1,2}; + /* forward references */ -static void wdCallback(long ind); /*callback from taskwd*/ +static void wdCallback(int *ind); /*callback from taskwd*/ static void start(int ind); /*start or restart a callbackTask*/ /*public routines */ @@ -86,51 +66,43 @@ long callbackInit() void callbackRequest(CALLBACK *pcallback) { int priority = pcallback->priority; - int lockKey; int nput; - static int status; + int lockKey; if(priority<0 || priority>=(NUM_CALLBACK_PRIORITIES)) { - - logMsg("callbackRequest called with invalid priority\n",0,0,0,0,0,0); + epicsPrintf("callbackRequest called with invalid priority\n"); return; } if(ringOverflow[priority]) return; - lockKey = intLock(); - nput = rngBufPut(callbackQ[priority],(void *)&pcallback,sizeof(pcallback)); - intUnlock(lockKey); + lockKey = interruptLock(); + nput = ringPut(callbackQ[priority],(void *)&pcallback,sizeof(pcallback)); + interruptUnlock(lockKey); if(nput!=sizeof(pcallback)){ - logMsg("callbackRequest ring buffer full\n",0,0,0,0,0,0); + epicsPrintf("callbackRequest ring buffer full\n"); ringOverflow[priority] = TRUE; } - if((status=semGive(callbackSem[priority]))!=OK) { -/*semGive randomly returns garbage value*/ -/* - logMsg("semGive returned error in callbackRequest\n",0,0,0,0,0,0); -*/ - } + semBinaryGive(callbackSem[priority]); return; } - + /* General purpose callback task */ -/*static*/ - void callbackTask(int priority) +static void callbackTask(int *ppriority) { + int priority = *ppriority; CALLBACK *pcallback; int nget; ringOverflow[priority] = FALSE; while(TRUE) { /* wait for somebody to wake us up */ - if(semTake(callbackSem[priority],WAIT_FOREVER)!=OK ){ - errMessage(0,"semTake returned error in callbackTask\n"); - taskSuspend(0); - } - while(rngNBytes(callbackQ[priority])>=sizeof(pcallback)) { - nget = rngBufGet(callbackQ[priority],(void *)&pcallback,sizeof(pcallback)); + semBinaryTakeAssert(callbackSem[priority]); + while(TRUE) { + nget = ringGet(callbackQ[priority], + (void *)&pcallback,sizeof(pcallback)); + if(nget==0) break; if(nget!=sizeof(pcallback)) { - errMessage(0,"rngBufGet failed in callbackTask"); - taskSuspend(0); + errMessage(0,"ringGet failed in callbackTask"); + threadSuspend(threadGetIdSelf()); } ringOverflow[priority] = FALSE; (*pcallback->callback)(pcallback); @@ -141,42 +113,40 @@ void callbackRequest(CALLBACK *pcallback) static char *priorityName[3] = {"Low","Medium","High"}; static void start(int ind) { - int priority; - char taskName[20]; + unsigned int priority; + char taskName[20]; - if((callbackSem[ind] = semBCreate(SEM_Q_FIFO,SEM_EMPTY))==NULL) - errMessage(0,"semBcreate failed while starting a callback task\n"); - if(ind==0) priority = CALLBACK_PRI_LOW; - else if(ind==1) priority = CALLBACK_PRI_MEDIUM; - else if(ind==2) priority = CALLBACK_PRI_HIGH; + if((callbackSem[ind] = semBinaryCreate(semEmpty))==0) + errMessage(0,"semBinaryCreate failed while starting a callback task\n"); + if(ind==0) priority = threadPriorityScanLow - 1; + else if(ind==1) priority = threadPriorityScanLow +4; + else if(ind==2) priority = threadPriorityScanHigh + 1; else { - errMessage(0,"semBcreate failed while starting a callback task\n"); + errMessage(0,"callback start called with illegal priority\n"); return; } - if((callbackQ[ind]=rngCreate(sizeof(CALLBACK *)*callbackQueueSize)) == NULL) - errMessage(0,"rngCreate failed while starting a callback task"); + if((callbackQ[ind]=ringCreate(sizeof(CALLBACK *)*callbackQueueSize)) == 0) + errMessage(0,"ringCreate failed while starting a callback task"); sprintf(taskName,"cb%s",priorityName[ind]); - callbackTaskId[ind] = taskSpawn(taskName,priority, - CALLBACK_OPT,CALLBACK_STACK, - (FUNCPTR)callbackTask,ind, - 0,0,0,0,0,0,0,0,0); - if(callbackTaskId[ind]==ERROR) { + callbackTaskId[ind] = threadCreate(taskName,priority, + threadGetStackSize(threadStackBig),(THREADFUNC)callbackTask, + &priorityValue[ind]); + if(callbackTaskId[ind]==0) { errMessage(0,"Failed to spawn a callback task"); return; } - taskwdInsert(callbackTaskId[ind],wdCallback,(void *)(long)ind); + taskwdInsert(callbackTaskId[ind],wdCallback,&priorityValue[ind]); } -static void wdCallback(long ind) +static void wdCallback(int *pind) { + int ind = *pind; taskwdRemove(callbackTaskId[ind]); if(!callbackRestart)return; - if(taskDelete(callbackTaskId[ind])!=OK) - errMessage(0,"taskDelete failed while restarting a callback task\n"); - if(semDelete(callbackSem[ind])!=OK) - errMessage(0,"semDelete failed while restarting a callback task\n"); - rngDelete(callbackQ[ind]); + threadDestroy(callbackTaskId[ind]); + semBinaryDestroy(callbackSem[ind]); + ringDelete(callbackQ[ind]); start(ind); } diff --git a/src/db/callback.h b/src/db/callback.h index db06ce969..a552c9457 100644 --- a/src/db/callback.h +++ b/src/db/callback.h @@ -4,29 +4,15 @@ /* * Original Author: Marty Kraimer * Date: 07-18-91 - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * Modification Log: +*/ + +/********************COPYRIGHT NOTIFICATION********************************** +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +****************************************************************************/ + +/* Modification Log: * ----------------- * .01 12-12-91 mrk Initial version * .02 04-05-94 mrk Remove casts on Lvalues (ANSI forbids) @@ -34,10 +20,10 @@ * windows */ - + #ifndef INCcallbackh #define INCcallbackh 1 - + /* * WINDOWS also has a "CALLBACK" type def */ @@ -90,5 +76,4 @@ void callbackRequestProcessCallback(); int callbackSetQueueSize(); #endif /*__STDC__*/ - #endif /*INCcallbackh*/ diff --git a/src/db/dbAccess.c b/src/db/dbAccess.c index 6f7487028..7436816ee 100644 --- a/src/db/dbAccess.c +++ b/src/db/dbAccess.c @@ -4,28 +4,14 @@ * Original Author: Bob Dalesio * Current Author: Marty Kraimer * Date: 11-7-90 - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * +*/ + +/********************COPYRIGHT NOTIFICATION********************************** +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +****************************************************************************/ +/* * Modification Log: * ----------------- * .01 07-26-91 mrk Allow choices to be retrieved as numeric @@ -53,36 +39,33 @@ */ -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include -#include "dbDefs.h" -#include "errlog.h" -#include "fast_lock.h" -#include "cvtFast.h" -#include "alarm.h" -#include "dbBase.h" -#include "dbAccess.h" -#include "dbStaticLib.h" -#include "dbConvert.h" -#include "dbBkpt.h" -#include "dbScan.h" -#include "dbCommon.h" -#include "dbLock.h" -#include "dbFldTypes.h" -#include "dbEvent.h" -#include "db_field_log.h" -#include "errMdef.h" -#include "recSup.h" -#include "recGbl.h" -#include "special.h" -#include "asLib.h" +#include "dbDefs.h" +#include "errlog.h" +#include "cantProceed.h" +#include "cvtFast.h" +#include "alarm.h" +#include "dbBase.h" +#include "dbAccess.h" +#include "dbStaticLib.h" +#include "dbConvert.h" +#include "dbBkpt.h" +#include "dbScan.h" +#include "dbCommon.h" +#include "dbLock.h" +#include "dbFldTypes.h" +#include "dbEvent.h" +#include "db_field_log.h" +#include "errMdef.h" +#include "recSup.h" +#include "recGbl.h" +#include "special.h" +#include "asLib.h" extern struct dbBase *pdbbase; extern long lset_stack_not_empty; @@ -565,7 +548,8 @@ long dbProcess(dbCommon *precord) /* check for trace processing*/ if (tpro) { - if (vxTas(&trace)) { + if(trace==0) { + trace = 1; trace_lset = lset; set_trace = TRUE; } @@ -804,9 +788,7 @@ long dbGetLinkValue(struct link *plink, short dbrType, void *pbuffer, } if(poptions) *poptions = 0; } else { - status = -1; - errMessage(-1,"dbGetLinkValue: Illegal link type"); - taskSuspend(0); + cantProceed("dbGetLinkValue: Illegal link type"); } return(status); } @@ -843,9 +825,7 @@ long dbPutLinkValue(struct link *plink,short dbrType, if(status < 0) recGblSetSevr(psource,LINK_ALARM,INVALID_ALARM); } else { - status=-1; - errMessage(-1,"dbPutLinkValue: Illegal link type"); - taskSuspend(0); + cantProceed("dbPutLinkValue: Illegal link type"); } return(status); } diff --git a/src/db/dbAccess.h b/src/db/dbAccess.h index 3e2fb2308..7241e5b56 100644 --- a/src/db/dbAccess.h +++ b/src/db/dbAccess.h @@ -33,9 +33,7 @@ of this distribution. #include #include #include -#ifdef vxWorks #include -#endif #include #include #include diff --git a/src/db/dbBkpt.c b/src/db/dbBkpt.c index a4e53f55a..f9c6aa632 100644 --- a/src/db/dbBkpt.c +++ b/src/db/dbBkpt.c @@ -3,31 +3,20 @@ /* * Author: Matthew Needes * Date: 8-30-93 - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * Modification Log: +*/ + +/********************COPYRIGHT NOTIFICATION********************************** +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +****************************************************************************/ + +/* Modification Log: * ----------------- * $Log$ + * Revision 1.9 1998/01/20 16:19:48 mrk + * Fix include statements + * * Revision 1.8 1996/08/05 19:33:40 jhill * removed ; from if * @@ -66,35 +55,31 @@ /* #define BKPT_DIAG */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include -#include "dbDefs.h" -#include "errlog.h" -#include "fast_lock.h" -#include "alarm.h" -#include "dbBase.h" -#include "dbAccess.h" -#include "dbScan.h" -#include "dbCommon.h" -#include "dbLock.h" -#include "dbFldTypes.h" -#include "dbBkpt.h" -#include "db_field_log.h" -#include "errMdef.h" -#include "recSup.h" -#include "recGbl.h" -#include "special.h" -#include "task_params.h" +#include "dbDefs.h" +#include "osiClock.h" +#include "osiThread.h" +#include "osiSem.h" +#include "ellLib.h" +#include "errlog.h" +#include "alarm.h" +#include "dbBase.h" +#include "dbAccess.h" +#include "dbScan.h" +#include "dbCommon.h" +#include "dbLock.h" +#include "dbFldTypes.h" +#include "dbBkpt.h" +#include "db_field_log.h" +#include "errMdef.h" +#include "recSup.h" +#include "recGbl.h" +#include "special.h" /* private routines */ static void dbBkptCont(); @@ -176,8 +161,8 @@ long lset_stack_not_empty = 0; * The semaphore is used to prevent conflicts while * operating with this stack. */ -static LIST lset_stack; -static SEM_ID bkpt_stack_sem; +static ELLLIST lset_stack; +static semId bkpt_stack_sem; /* * Stores the last lockset continued or stepped from. @@ -194,10 +179,10 @@ static unsigned long last_lset = 0; * is returned in "pnode." */ #define FIND_LOCKSET(precord, pnode) \ - pnode = (struct LS_LIST *) lstFirst(&lset_stack); \ + pnode = (struct LS_LIST *) ellFirst(&lset_stack); \ while ((pnode) != NULL) { \ if (pnode->l_num == dbLockGetLockId(precord)) break; \ - pnode = (struct LS_LIST *) lstNext((NODE *)pnode); \ + pnode = (struct LS_LIST *) ellNext((ELLNODE *)pnode); \ } \ /* @@ -208,10 +193,10 @@ static unsigned long last_lset = 0; * being searched for in *pep_queue. */ #define FIND_QUEUE_ENTRY(pep_queue, pqe, precord) \ - pqe = (struct EP_LIST *) lstFirst(pep_queue); \ + pqe = (struct EP_LIST *) ellFirst(pep_queue); \ while ((pqe) != NULL) { \ if ((pqe)->entrypoint == (precord)) break; \ - pqe = (struct EP_LIST *) lstNext((NODE *)pqe); \ + pqe = (struct EP_LIST *) ellNext((ELLNODE *)pqe); \ } \ /* @@ -233,13 +218,13 @@ static long FIND_CONT_NODE( * Search through stack, taking the first entry that * is currently stopped at a breakpoint. */ - pnode = (struct LS_LIST *) lstFirst(&lset_stack); + pnode = (struct LS_LIST *) ellFirst(&lset_stack); while (pnode != NULL) { if (pnode->precord != NULL) { precord = pnode->precord; break; } - pnode = (struct LS_LIST *) lstNext((NODE *)pnode); + pnode = (struct LS_LIST *) ellNext((ELLNODE *)pnode); } if (pnode == NULL) { @@ -315,17 +300,17 @@ long dbb(char *record_name) */ if (! lset_stack_not_empty) { /* initialize list and semaphore */ - bkpt_stack_sem = semBCreate(SEM_Q_FIFO, SEM_FULL); - if (bkpt_stack_sem == NULL) { + bkpt_stack_sem = semMutexCreate(); + if (bkpt_stack_sem == 0) { printf(" BKPT> Out of memory\n"); dbScanUnlock(precord); return(1); } - lstInit(&lset_stack); + ellInit(&lset_stack); lset_stack_not_empty = 1; } - semTake(bkpt_stack_sem, WAIT_FOREVER); + semMutexTakeAssert(bkpt_stack_sem); FIND_LOCKSET(precord, pnode); @@ -335,30 +320,30 @@ long dbb(char *record_name) if (pnode == NULL) { printf(" BKPT> Out of memory\n"); dbScanUnlock(precord); - semGive(bkpt_stack_sem); + semMutexGive(bkpt_stack_sem); return(1); } pnode->precord = NULL; /* initialize breakpoint list */ - lstInit(&pnode->bp_list); + ellInit(&pnode->bp_list); /* initialize entry point queue */ - lstInit(&pnode->ep_queue); + ellInit(&pnode->ep_queue); /* create execution semaphore */ - pnode->ex_sem = semBCreate(SEM_Q_FIFO, SEM_EMPTY); + pnode->ex_sem = semBinaryCreate(semEmpty); if (pnode->ex_sem == NULL) { printf(" BKPT> Out of memory\n"); dbScanUnlock(precord); - semGive(bkpt_stack_sem); + semMutexGive(bkpt_stack_sem); return(1); } pnode->taskid = 0; pnode->step = 0; pnode->l_num = dbLockGetLockId(precord); - lstAdd(&lset_stack, (NODE *)pnode); + ellAdd(&lset_stack, (ELLNODE *)pnode); } /* @@ -368,11 +353,11 @@ long dbb(char *record_name) if (pbl == NULL) { printf(" BKPT> Out of memory\n"); dbScanUnlock(precord); - semGive(bkpt_stack_sem); + semMutexGive(bkpt_stack_sem); return(1); } pbl->precord = precord; - lstAdd(&pnode->bp_list, (NODE *)pbl); + ellAdd(&pnode->bp_list, (ELLNODE *)pbl); /* * Turn on breakpoint field in record @@ -387,20 +372,19 @@ long dbb(char *record_name) /* * Spawn continuation task */ - pnode->taskid = taskSpawn(BKPT_CONT_NAME, PERIODSCAN_PRI, BKPT_CONT_OPT, - BKPT_CONT_STACK, (FUNCPTR) dbBkptCont,(int) precord, - 0,0,0,0,0,0,0,0,0); - - if (pnode->taskid == ERROR) { + pnode->taskid = threadCreate("bkptCont",threadPriorityScanLow-1, + threadGetStackSize(threadStackBig), + (THREADFUNC)dbBkptCont,precord); + if (pnode->taskid == 0) { printf(" BKPT> Cannot spawn task to process record\n"); pnode->taskid = 0; dbScanUnlock(precord); - semGive(bkpt_stack_sem); + semMutexGive(bkpt_stack_sem); return(1); } } - semGive(bkpt_stack_sem); + semMutexGive(bkpt_stack_sem); dbScanUnlock(precord); return(0); } @@ -439,7 +423,7 @@ long dbd(char *record_name) dbScanLock(precord); - semTake(bkpt_stack_sem, WAIT_FOREVER); + semMutexTakeAssert(bkpt_stack_sem); FIND_LOCKSET(precord, pnode); @@ -448,7 +432,7 @@ long dbd(char *record_name) printf(" BKPT> Logic Error in dbd()\n"); precord->bkpt &= BKPT_OFF_MASK; - semGive(bkpt_stack_sem); + semMutexGive(bkpt_stack_sem); dbScanUnlock(precord); return(S_db_bkptLogic); } @@ -458,20 +442,20 @@ long dbd(char *record_name) */ /* find record in list */ - pbl = (struct BP_LIST *) lstFirst(&pnode->bp_list); + pbl = (struct BP_LIST *) ellFirst(&pnode->bp_list); while (pbl != NULL) { if (pbl->precord == precord) { - lstDelete(&pnode->bp_list, (NODE *)pbl); + ellDelete(&pnode->bp_list, (ELLNODE *)pbl); free(pbl); break; } - pbl = (struct BP_LIST *) lstNext((NODE *)pbl); + pbl = (struct BP_LIST *) ellNext((ELLNODE *)pbl); } if (pbl == NULL) { printf(" BKPT> Logic Error in dbd()\n"); precord->bkpt &= BKPT_OFF_MASK; - semGive(bkpt_stack_sem); + semMutexGive(bkpt_stack_sem); dbScanUnlock(precord); return(S_db_bkptLogic); } @@ -485,10 +469,10 @@ long dbd(char *record_name) * If there are no more breakpoints, give up semaphore * to cause the bkptCont task to quit. */ - if (lstCount(&pnode->bp_list) == 0) - semGive(pnode->ex_sem); + if (ellCount(&pnode->bp_list) == 0) + semBinaryGive(pnode->ex_sem); - semGive(bkpt_stack_sem); + semMutexGive(bkpt_stack_sem); dbScanUnlock(precord); return(0); @@ -506,11 +490,11 @@ long dbc(char *record_name) struct dbCommon *precord = NULL; long status = 0; - semTake(bkpt_stack_sem, WAIT_FOREVER); + semMutexTakeAssert(bkpt_stack_sem); status = FIND_CONT_NODE(record_name, &pnode, &precord); if (status) { - semGive(bkpt_stack_sem); + semMutexGive(bkpt_stack_sem); return(status); } @@ -529,13 +513,8 @@ long dbc(char *record_name) * for a record with a breakpoint. This occurs * because stepping mode has been switched off. */ - if (taskResume(pnode->taskid) == ERROR) { - printf(" BKPT> Cannot continue\n"); - semGive(bkpt_stack_sem); - return(S_db_cntCont); - } - - semGive(bkpt_stack_sem); + threadResume(pnode->taskid); + semMutexGive(bkpt_stack_sem); return(0); } @@ -550,11 +529,11 @@ long dbs(char *record_name) struct dbCommon *precord = NULL; long status = 0; - semTake(bkpt_stack_sem, WAIT_FOREVER); + semMutexTakeAssert(bkpt_stack_sem); status = FIND_CONT_NODE(record_name, &pnode, &precord); if (status) { - semGive(bkpt_stack_sem); + semMutexGive(bkpt_stack_sem); return(status); } @@ -563,13 +542,8 @@ long dbs(char *record_name) last_lset = pnode->l_num; - if (taskResume(pnode->taskid) == ERROR) { - printf(" BKPT> Cannot step\n"); - semGive(bkpt_stack_sem); - return(S_db_cntCont); - } - - semGive(bkpt_stack_sem); + threadResume(pnode->taskid); + semMutexGive(bkpt_stack_sem); return(0); } @@ -591,7 +565,7 @@ static void dbBkptCont(struct dbCommon *precord) * Reset breakpoint, process record, and * reset bkpt field in record */ - semTake(bkpt_stack_sem, WAIT_FOREVER); + semMutexTakeAssert(bkpt_stack_sem); FIND_LOCKSET(precord, pnode); @@ -607,15 +581,15 @@ static void dbBkptCont(struct dbCommon *precord) */ do { /* Give up semaphore before waiting to run ... */ - semGive(bkpt_stack_sem); + semMutexGive(bkpt_stack_sem); /* Wait to run */ - semTake(pnode->ex_sem, WAIT_FOREVER); + semBinaryTakeAssert(pnode->ex_sem); /* Bkpt stack must still be stable ! */ - semTake(bkpt_stack_sem, WAIT_FOREVER); + semMutexTakeAssert(bkpt_stack_sem); - pqe = (struct EP_LIST *) lstFirst(&pnode->ep_queue); + pqe = (struct EP_LIST *) ellFirst(&pnode->ep_queue); /* Run through entrypoint queue */ while (pqe != NULL) { @@ -633,22 +607,22 @@ static void dbBkptCont(struct dbCommon *precord) pqe->sched = 0; pnode->step = 0; } - pqe = (struct EP_LIST *) lstNext((NODE *)pqe); + pqe = (struct EP_LIST *) ellNext((ELLNODE *)pqe); } /* Reset precord. (Since no records are at a breakpoint) */ pnode->precord = NULL; } - while (lstCount(&pnode->bp_list) != 0); + while (ellCount(&pnode->bp_list) != 0); /* remove node from lockset stack */ - lstDelete(&lset_stack, (NODE *)pnode); + ellDelete(&lset_stack, (ELLNODE *)pnode); /* free entrypoint queue */ - lstFree(&pnode->ep_queue); + ellFree(&pnode->ep_queue); /* remove execution semaphore */ - semDelete(pnode->ex_sem); + semBinaryDestroy(pnode->ex_sem); printf("\n BKPT> End debug of lockset %lu\n-> ", pnode->l_num); @@ -656,14 +630,14 @@ static void dbBkptCont(struct dbCommon *precord) free(pnode); /* if last node on stack ... */ - if (lstCount(&lset_stack) == 0) { + if (ellCount(&lset_stack) == 0) { /* Unset flag, delete stack semaphore */ lset_stack_not_empty = 0; - semDelete(bkpt_stack_sem); + semMutexDestroy(bkpt_stack_sem); } if (lset_stack_not_empty) - semGive(bkpt_stack_sem); + semMutexGive(bkpt_stack_sem); } /* @@ -699,9 +673,9 @@ int dbBkpt(struct dbCommon *precord) * goodness breakpoint checking is turned off during * normal operation. */ - semTake(bkpt_stack_sem, WAIT_FOREVER); + semMutexTakeAssert(bkpt_stack_sem); FIND_LOCKSET(precord, pnode); - semGive(bkpt_stack_sem); + semMutexGive(bkpt_stack_sem); if (pnode == NULL) { /* no breakpoints in precord's lockset */ @@ -730,7 +704,7 @@ int dbBkpt(struct dbCommon *precord) * source, queue its execution, but dump out of dbProcess without * calling record support. */ - if (pnode->taskid && (taskIdSelf() != pnode->taskid)) { + if (pnode->taskid && (threadGetIdSelf() != pnode->taskid)) { /* CONTINUE TASK CANNOT ENTER HERE */ /* @@ -748,7 +722,7 @@ int dbBkpt(struct dbCommon *precord) pqe->entrypoint = precord; pqe->count = 1; - pqe->time = tickGet(); + pqe->time = clockGetCurrentTick(); pqe->sched = 0; #ifdef BKPT_DIAG @@ -758,12 +732,12 @@ int dbBkpt(struct dbCommon *precord) /* * Take semaphore, wait on continuation task */ - semTake(bkpt_stack_sem, WAIT_FOREVER); + semMutexTakeAssert(bkpt_stack_sem); /* Add entry to queue */ - lstAdd(&pnode->ep_queue, (NODE *)pqe); + ellAdd(&pnode->ep_queue, (ELLNODE *)pqe); - semGive(bkpt_stack_sem); + semMutexGive(bkpt_stack_sem); } else { if (pqe->count < MAX_EP_COUNT) @@ -779,7 +753,7 @@ int dbBkpt(struct dbCommon *precord) * Release the semaphore, letting the continuation * task begin execution of the new entrypoint. */ - semGive(pnode->ex_sem); + semBinaryGive(pnode->ex_sem); } return(1); } @@ -814,8 +788,8 @@ int dbBkpt(struct dbCommon *precord) pnode->precord = precord; /* Move current lockset to top of stack */ - lstDelete(&lset_stack, (NODE *)pnode); - lstInsert(&lset_stack, NULL, (NODE *)pnode); + ellDelete(&lset_stack, (ELLNODE *)pnode); + ellInsert(&lset_stack, NULL, (ELLNODE *)pnode); /* * Unlock database while the task suspends itself. This * is done so that dbb() dbd() dbc() dbs() may be used @@ -825,11 +799,11 @@ int dbBkpt(struct dbCommon *precord) * continue to be processed. Cross your fingers, this * might actually work ! */ - semGive(bkpt_stack_sem); + semMutexGive(bkpt_stack_sem); dbScanUnlock(precord); - taskSuspend(pnode->taskid); + threadSuspend(pnode->taskid); dbScanLock(precord); - semTake(bkpt_stack_sem, WAIT_FOREVER); + semMutexTakeAssert(bkpt_stack_sem); } return(0); } @@ -860,19 +834,19 @@ long dbp(char *record_name, int interest_level) struct dbCommon *precord; int status; - semTake(bkpt_stack_sem, WAIT_FOREVER); + semMutexTakeAssert(bkpt_stack_sem); /* find pnode and precord pointers */ status = FIND_CONT_NODE(record_name, &pnode, &precord); if (status) { - semGive(bkpt_stack_sem); + semMutexGive(bkpt_stack_sem); return(status); } /* print out record's fields */ dbpr(precord->name, (interest_level == 0) ? 2 : interest_level); - semGive(bkpt_stack_sem); + semMutexGive(bkpt_stack_sem); return(0); } @@ -916,40 +890,40 @@ long dbstat() struct EP_LIST *pqe; unsigned long time; - semTake(bkpt_stack_sem, WAIT_FOREVER); + semMutexTakeAssert(bkpt_stack_sem); - time = tickGet(); + time = clockGetCurrentTick(); /* * Traverse list, reporting stopped records */ - pnode = (struct LS_LIST *) lstFirst(&lset_stack); + pnode = (struct LS_LIST *) ellFirst(&lset_stack); while (pnode != NULL) { if (pnode->precord != NULL) { - printf("LSet: %lu Stopped at: %-28.28s #B: %5.5d T: 0x%7.7x\n", - pnode->l_num, pnode->precord->name, lstCount(&pnode->bp_list), pnode->taskid); + printf("LSet: %lu Stopped at: %-28.28s #B: %5.5d T: %p\n", + pnode->l_num, pnode->precord->name, ellCount(&pnode->bp_list), pnode->taskid); /* for each entrypoint detected, print out entrypoint statistics */ - pqe = (struct EP_LIST *) lstFirst(&pnode->ep_queue); + pqe = (struct EP_LIST *) ellFirst(&pnode->ep_queue); while (pqe != NULL) { if (time - pqe->time) { printf(" Entrypoint: %-28.28s #C: %5.5lu C/S: %7.1f\n", pqe->entrypoint->name, pqe->count, - vxTicksPerSecond * pqe->count/((double)(time-pqe->time))); + clockGetRate() * pqe->count/((double)(time-pqe->time))); } - pqe = (struct EP_LIST *) lstNext((NODE *)pqe); + pqe = (struct EP_LIST *) ellNext((ELLNODE *)pqe); } } else { - printf("LSet: %lu #B: %5.5d T: 0x%7.7x\n", - pnode->l_num, lstCount(&pnode->bp_list), pnode->taskid); + printf("LSet: %lu #B: %5.5d T: %p\n", + pnode->l_num, ellCount(&pnode->bp_list), pnode->taskid); } /* * Print out breakpoints set in the lock set */ - pbl = (struct BP_LIST *) lstFirst(&pnode->bp_list); + pbl = (struct BP_LIST *) ellFirst(&pnode->bp_list); while (pbl != NULL) { printf(" Breakpoint: %-28.28s", pbl->precord->name); @@ -959,13 +933,13 @@ long dbstat() else printf("\n"); - pbl = (struct BP_LIST *) lstNext((NODE *)pbl); + pbl = (struct BP_LIST *) ellNext((ELLNODE *)pbl); } - pnode = (struct LS_LIST *) lstNext((NODE *)pnode); + pnode = (struct LS_LIST *) ellNext((ELLNODE *)pnode); } - semGive(bkpt_stack_sem); + semMutexGive(bkpt_stack_sem); return(0); } @@ -1001,7 +975,7 @@ long dbprc(char *record_name) /* Reset breakpoints */ int dbreset() { - semGive(bkpt_stack_sem); + semMutexGive(bkpt_stack_sem); return(0); } diff --git a/src/db/dbBkpt.h b/src/db/dbBkpt.h index fdeca15df..ea72fdb4c 100644 --- a/src/db/dbBkpt.h +++ b/src/db/dbBkpt.h @@ -32,7 +32,9 @@ #ifndef INCdbBkptsh #define INCdbBkptsh 1 -#include +#include +#include +#include /* Needs to be put into dbTest.h ! */ long dbpr(char *name, int level); @@ -42,8 +44,8 @@ long dbpr(char *name, int level); */ struct BP_LIST { - NODE *next_list; - NODE *prev_list; + ELLNODE *next_list; + ELLNODE *prev_list; struct dbCommon *precord; }; @@ -52,8 +54,8 @@ struct BP_LIST { * detected for a lockset. */ struct EP_LIST { - NODE *next_list; - NODE *prev_list; + ELLNODE *next_list; + ELLNODE *prev_list; struct dbCommon *entrypoint; /* pointer to entry point in lockset */ unsigned long count; /* number of times record processed */ unsigned long time; /* time record first logged */ @@ -62,17 +64,17 @@ struct EP_LIST { /* * Structure for stack of lock sets that - * currently contain breakpoints. (uses lstLib) + * currently contain breakpoints. (uses ellLib) */ struct LS_LIST { - NODE *next_list; - NODE *prev_list; + ELLNODE *next_list; + ELLNODE *prev_list; struct dbCommon *precord;/* points to where execution is currently stopped */ struct dbCommon *current_ep; /* current entrypoint */ - LIST bp_list; /* list of records containing breakpoints in a lockset */ - LIST ep_queue; /* queue of entrypoints found so far */ - SEM_ID ex_sem; /* semaphore for execution queue */ - int taskid; /* saved taskid for the task in stepping mode */ + ELLLIST bp_list; /* list of records containing breakpoints in a lockset */ + ELLLIST ep_queue; /* queue of entrypoints found so far */ + semId ex_sem; /* semaphore for execution queue */ + threadId taskid; /* saved taskid for the task in stepping mode */ int step; /* one if currently "stepping," else zero */ unsigned long l_num; /* lockset number */ }; diff --git a/src/db/dbCa.c b/src/db/dbCa.c index 6e1c8bced..872e7e8eb 100644 --- a/src/db/dbCa.c +++ b/src/db/dbCa.c @@ -24,21 +24,21 @@ of this distribution. * .01 26MAR96 lrd rewritten for simplicity, robustness and flexibility ****************************************************************/ -#include +#include #include #include #include #include -#include #include "dbDefs.h" +#include "osiSem.h" +#include "osiThread.h" #include "errlog.h" #include "cadef.h" #include "caerr.h" #include "alarm.h" #include "db_access.h" #include "link.h" -#include "task_params.h" #include "errMdef.h" #include "epicsPrint.h" #include "dbCommon.h" @@ -48,8 +48,8 @@ void scanOnce(void *precord); extern volatile int interruptAccept; static ELLLIST caList; /* Work list for dbCaTask */ -static SEM_ID caListSem; /*Mutual exclusions semaphores for caList*/ -static SEM_ID caWakeupSem; /*wakeup semaphore for dbCaTask*/ +static semId caListSem; /*Mutual exclusions semaphores for caList*/ +static semId caWakeupSem; /*wakeup semaphore for dbCaTask*/ void dbCaTask(void); /*The Channel Access Task*/ /* caLink locking @@ -66,26 +66,25 @@ static void addAction(caLink *pca, short link_action) { int callAdd = FALSE; - semTake(caListSem,WAIT_FOREVER); + semMutexTakeAssert(caListSem); if(pca->link_action==0) callAdd = TRUE; pca->link_action |= link_action; if(callAdd) ellAdd(&caList,&pca->node); - semGive(caListSem); - if(callAdd) semGive(caWakeupSem); + semMutexGive(caListSem); + if(callAdd) semBinaryGive(caWakeupSem); } void dbCaLinkInit(void) { ellInit(&caList); - caListSem = semMCreate(SEM_DELETE_SAFE|SEM_INVERSION_SAFE|SEM_Q_PRIORITY); - caWakeupSem = semBCreate(SEM_Q_PRIORITY,SEM_EMPTY); + caListSem = semMutexCreate(); + caWakeupSem = semBinaryCreate(semEmpty); if(!caListSem || !caWakeupSem) { printf("dbCaLinkInit: semBCreate failed\n"); return; } - taskSpawn("dbCaLink", DB_CA_PRI, DB_CA_OPT, - DB_CA_STACK, (FUNCPTR) dbCaTask, - 0,0,0,0,0,0,0,0,0,0); + threadCreate("dbCaLink", threadPriorityMedium, + threadGetStackSize(threadStackBig), (THREADFUNC) dbCaTask,0); } void dbCaAddLink( struct link *plink) @@ -96,9 +95,9 @@ void dbCaAddLink( struct link *plink) pca->plink = plink; plink->type = CA_LINK; plink->value.pv_link.pvt = pca; - if((pca->lock = semBCreate(SEM_Q_PRIORITY,SEM_FULL)) == NULL){ - printf("dbCaAddLink: semBCreate failed\n"); - taskSuspend(0); + if((pca->lock = semMutexCreate()) == 0){ + printf("dbCaAddLink: semMutexCreate failed\n"); + threadSuspend(threadGetIdSelf()); } addAction(pca,CA_CONNECT); return; @@ -107,17 +106,12 @@ void dbCaAddLink( struct link *plink) void dbCaRemoveLink( struct link *plink) { caLink *pca = (caLink *)plink->value.pv_link.pvt; - STATUS semStatus; if(!pca) return; - semStatus = semTake(pca->lock,WAIT_FOREVER); - if(semStatus!=OK) { - epicsPrintf("dbCaRemoveLink: semStatus!OK\n"); - return; - } + semMutexTakeAssert(pca->lock); pca->plink = 0; plink->value.pv_link.pvt = 0; - semGive(pca->lock); + semMutexGive(pca->lock); addAction(pca,CA_DELETE); } @@ -128,7 +122,6 @@ long dbCaGetLink(struct link *plink,short dbrType, char *pdest, caLink *pca = (caLink *)plink->value.pv_link.pvt; long status = 0; long (*pconvert)(); - STATUS semStatus; short link_action = 0; if(!pca) { @@ -136,11 +129,7 @@ long dbCaGetLink(struct link *plink,short dbrType, char *pdest, plink->value.pv_link.precord); return(-1); } - semStatus = semTake(pca->lock,WAIT_FOREVER); - if(semStatus!=OK) { - epicsPrintf("dbCaGetLink: semStatus!OK\n"); - return(-1); - } + semMutexTakeAssert(pca->lock); if(!pca->chid || ca_state(pca->chid) != cs_conn) { pca->sevr = INVALID_ALARM; goto done; @@ -192,7 +181,7 @@ long dbCaGetLink(struct link *plink,short dbrType, char *pdest, } done: if(psevr) *psevr = pca->sevr; - semGive(pca->lock); + semMutexGive(pca->lock); if(link_action) addAction(pca,link_action); return(status); } @@ -203,7 +192,6 @@ long dbCaPutLink(struct link *plink,short dbrType, caLink *pca = (caLink *)plink->value.pv_link.pvt; long (*pconvert)(); long status = 0; - STATUS semStatus; short link_action = 0; if(!pca) { @@ -212,13 +200,9 @@ long dbCaPutLink(struct link *plink,short dbrType, return(-1); } /* put the new value in */ - semStatus = semTake(pca->lock,WAIT_FOREVER); - if(semStatus!=OK) { - epicsPrintf("dbCaGetLink: semStatus!OK\n"); - return(-1); - } + semMutexTakeAssert(pca->lock); if(!pca->chid || ca_state(pca->chid) != cs_conn) { - semGive(pca->lock); + semMutexGive(pca->lock); return(-1); } if((pca->dbrType == DBR_ENUM) && (dbDBRnewToDBRold[dbrType] == DBR_STRING)){ @@ -258,7 +242,7 @@ long dbCaPutLink(struct link *plink,short dbrType, if(pca->newOutNative) pca->nNoWrite++; pca->newOutNative = TRUE; } - semGive(pca->lock); + semMutexGive(pca->lock); addAction(pca,link_action); return(status); } @@ -268,7 +252,6 @@ long dbCaGetAttributes(struct link *plink, { caLink *pca; long status = 0; - STATUS semStatus; short link_action = 0; caAttributes *pcaAttributes; @@ -290,14 +273,10 @@ long dbCaGetAttributes(struct link *plink, pcaAttributes = dbCalloc(1,sizeof(caAttributes)); pcaAttributes->callback = callback; pcaAttributes->usrPvt = usrPvt; - semStatus = semTake(pca->lock,WAIT_FOREVER); - if(semStatus!=OK) { - epicsPrintf("dbCaGetLink: semStatus!OK\n"); - return(-1); - } + semMutexTakeAssert(pca->lock); pca->pcaAttributes = pcaAttributes; link_action |= CA_GET_ATTRIBUTES; - semGive(pca->lock); + semMutexGive(pca->lock); addAction(pca,link_action); return(status); } @@ -437,7 +416,6 @@ static void eventCallback(struct event_handler_args arg) caLink *pca = (caLink *)arg.usr; struct link *plink; long size; - STATUS semStatus; dbCommon *precord = 0; struct dbr_time_double *pdbr_time_double; @@ -445,11 +423,7 @@ static void eventCallback(struct event_handler_args arg) epicsPrintf("eventCallback why was arg.usr NULL\n"); return; } - semStatus = semTake(pca->lock,WAIT_FOREVER); - if(semStatus!=OK) { - epicsPrintf("dbCa eventTask: semStatus!OK\n"); - return; - } + semMutexTakeAssert(pca->lock); plink = pca->plink; if(!plink) goto done; precord = (dbCommon *)plink->value.pv_link.precord; @@ -498,14 +472,13 @@ static void eventCallback(struct event_handler_args arg) scanOnce(precord); } done: - semGive(pca->lock); + semMutexGive(pca->lock); } static void getAttribEventCallback(struct event_handler_args arg) { caLink *pca = (caLink *)arg.usr; struct link *plink; - STATUS semStatus; const struct dbr_ctrl_double *dbr; caAttributes *pcaAttributes = NULL; @@ -513,11 +486,7 @@ const struct dbr_ctrl_double *dbr; epicsPrintf("getAttribEventCallback why was arg.usr NULL\n"); return; } - semStatus = semTake(pca->lock,WAIT_FOREVER); - if(semStatus!=OK) { - epicsPrintf("getAttribEventCallback: semStatus!OK\n"); - return; - } + semMutexTakeAssert(pca->lock); plink = pca->plink; if(!plink) goto done; if(!arg.dbr) { @@ -531,25 +500,20 @@ const struct dbr_ctrl_double *dbr; pcaAttributes->gotData = TRUE; (pcaAttributes->callback)(pcaAttributes->usrPvt); done: - semGive(pca->lock); + semMutexGive(pca->lock); } static void accessRightsCallback(struct access_rights_handler_args arg) { caLink *pca = (caLink *)ca_puser(arg.chid); struct link *plink; - STATUS semStatus; if(!pca) { epicsPrintf("accessRightsCallback why was arg.usr NULL\n"); return; } if(ca_state(pca->chid) != cs_conn) return;/*connectionCallback will handle*/ - semStatus = semTake(pca->lock,WAIT_FOREVER); - if(semStatus!=OK) { - epicsPrintf("dbCa accessRightsCallback: semStatus!OK\n"); - return; - } + semMutexTakeAssert(pca->lock); if(ca_read_access(arg.chid) || ca_write_access(arg.chid)) goto done; plink = pca->plink; if(plink) { @@ -563,7 +527,7 @@ static void accessRightsCallback(struct access_rights_handler_args arg) } } done: - semGive(pca->lock); + semMutexGive(pca->lock); } static void connectionCallback(struct connection_handler_args arg) @@ -571,15 +535,10 @@ static void connectionCallback(struct connection_handler_args arg) caLink *pca; short link_action = 0; struct link *plink; - STATUS semStatus; pca = ca_puser(arg.chid); if(!pca) return; - semStatus = semTake(pca->lock,WAIT_FOREVER); - if(semStatus!=OK) { - epicsPrintf("dbCa connectionCallback: semStatus!OK\n"); - return; - } + semMutexTakeAssert(pca->lock); plink = pca->plink; if(!plink) goto done; if(ca_state(arg.chid) != cs_conn){ @@ -601,7 +560,7 @@ static void connectionCallback(struct connection_handler_args arg) /*Only safe thing is to delete old caLink and allocate a new one*/ pca->plink = 0; plink->value.pv_link.pvt = 0; - semGive(pca->lock); + semMutexGive(pca->lock); addAction(pca,CA_DELETE); dbCaAddLink(plink); return; @@ -624,7 +583,7 @@ static void connectionCallback(struct connection_handler_args arg) } if(pca->pcaAttributes) link_action |= CA_GET_ATTRIBUTES; done: - semGive(pca->lock); + semMutexGive(pca->lock); if(link_action) addAction(pca,link_action); } @@ -636,17 +595,17 @@ void dbCaTask() SEVCHK(ca_task_initialize(),NULL); /*Dont do anything until iocInit initializes database*/ - while(!interruptAccept) taskDelay(10); + while(!interruptAccept) threadSleep(.1); /* channel access event loop */ while (TRUE){ - semTake(caWakeupSem,WAIT_FOREVER); + semBinaryTakeAssert(caWakeupSem); while(TRUE) { /* process all requests in caList*/ - semTake(caListSem,WAIT_FOREVER); + semMutexTakeAssert(caListSem); if((pca = (caLink *)ellFirst(&caList))){/*Take off list head*/ ellDelete(&caList,&pca->node); link_action = pca->link_action; pca->link_action = 0; - semGive(caListSem); /*Give it back immediately*/ + semMutexGive(caListSem); /*Give it back immediately*/ if(link_action&CA_DELETE) {/*This must be first*/ if(pca->chid) ca_clear_channel(pca->chid); free(pca->pgetNative); @@ -654,7 +613,7 @@ void dbCaTask() free(pca->pgetString); free(pca->pputString); free(pca->pcaAttributes); - semDelete(pca->lock); + semMutexDestroy(pca->lock); free(pca); continue; /*No other link_action makes sense*/ } @@ -719,7 +678,7 @@ void dbCaTask() ca_message(status)); } } else { /* caList was empty */ - semGive(caListSem); + semMutexGive(caListSem); break; /*caList is empty*/ } } diff --git a/src/db/dbCa.h b/src/db/dbCa.h index e82573ac1..abcdc1db8 100644 --- a/src/db/dbCa.h +++ b/src/db/dbCa.h @@ -51,7 +51,7 @@ typedef struct caLink char *pputString; caAttributes *pcaAttributes; long nelements; - SEM_ID lock; + semId lock; unsigned long nDisconnect; unsigned long nNoWrite; short dbrType; diff --git a/src/db/dbCommon.dbd b/src/db/dbCommon.dbd index 1de51b6b6..f05639ff9 100644 --- a/src/db/dbCommon.dbd +++ b/src/db/dbCommon.dbd @@ -70,7 +70,7 @@ prompt("Monitor fastlock") special(SPC_NOMOD) interest(4) - extra("FAST_LOCK mlok") + extra("semId mlok") } field(MLIS,DBF_NOACCESS) { prompt("Monitor List") diff --git a/src/db/dbConvert.c b/src/db/dbConvert.c index 1e6f0a497..b7a9ad8c0 100644 --- a/src/db/dbConvert.c +++ b/src/db/dbConvert.c @@ -3,49 +3,31 @@ * Original Author: Bob Dalesio * Current Author: Marty Kraimer * Date: 11-7-90 - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * Modification Log: - * ----------------- - * .01 11OCT95 mrk Moved from dbLink.c - */ -#include -#include -#include -#include -#include +*/ -#include "dbDefs.h" -#include "errlog.h" -#include "cvtFast.h" -#include "dbBase.h" -#include "dbAccess.h" -#include "dbConvert.h" -#include "dbStaticLib.h" -#include "dbFldTypes.h" -#include "errMdef.h" -#include "recSup.h" -#include "recGbl.h" +/********************COPYRIGHT NOTIFICATION********************************** +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "dbDefs.h" +#include "errlog.h" +#include "cvtFast.h" +#include "dbBase.h" +#include "dbAccess.h" +#include "dbConvert.h" +#include "dbStaticLib.h" +#include "dbFldTypes.h" +#include "errMdef.h" +#include "recSup.h" +#include "recGbl.h" /* DATABASE ACCESS GET CONVERSION SUPPORT */ diff --git a/src/db/dbEvent.c b/src/db/dbEvent.c index c4386185b..57a4d7315 100644 --- a/src/db/dbEvent.c +++ b/src/db/dbEvent.c @@ -4,31 +4,21 @@ /* * Author: Jeffrey O. Hill * Date: 4-1-89 - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * NOTES: - * - * Modification Log: +*/ + +/***************************************************************** + COPYRIGHT NOTIFICATION +***************************************************************** + +(C) COPYRIGHT 1991 Regents of the University of California, +and the University of Chicago Board of Governors. + +This software was developed under a United States Government license +described on the COPYRIGHT_Combined file included as part +of this distribution. +**********************************************************************/ + +/* Modification Log: * ----------------- * joh 00 04xx89 Created * joh 01 043089 Init Release @@ -64,42 +54,35 @@ * problem */ -#include "epicsAssert.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dbDefs.h" -#include "errlog.h" -#include "taskwd.h" -#include "freeList.h" -#include "tsDefs.h" -#include "dbCommon.h" -#include "task_params.h" -#include "dbAccess.h" -#include "dbEvent.h" -#include "caeventmask.h" - -#include "memDebugLib.h" +#include +#include +#include +#include +#include +#include "epicsAssert.h" +#include "cantProceed.h" +#include "dbDefs.h" +#include "osiSem.h" +#include "osiThread.h" +#include "osiClock.h" +#include "errlog.h" +#include "taskwd.h" +#include "freeList.h" +#include "tsDefs.h" +#include "dbCommon.h" +#include "dbAccess.h" +#include "dbEvent.h" +#include "caeventmask.h" /* local function declarations */ - LOCAL int event_read(struct event_que *ev_que); LOCAL int db_post_single_event_private(struct event_block *event); /* what to do with unrecoverable errors */ -#define abort(S) taskSuspend((int)taskIdCurrent); +#define abort(S) cantProceed("dbEvent abort") /* * Reliable intertask communication requires copying the current value of the @@ -123,20 +106,22 @@ LOCAL int db_post_single_event_private(struct event_block *event); ) #define LOCKEVQUE(EV_QUE)\ -FASTLOCK(&(EV_QUE)->writelock); +semMutexTakeAssert((EV_QUE)->writelock); #define UNLOCKEVQUE(EV_QUE)\ -FASTUNLOCK(&(EV_QUE)->writelock); +semMutexGive((EV_QUE)->writelock); #define LOCKREC(RECPTR)\ -FASTLOCK(&(RECPTR)->mlok); +semMutexTakeAssert((RECPTR)->mlok); #define UNLOCKREC(RECPTR)\ -FASTUNLOCK(&(RECPTR)->mlok); +semMutexGive((RECPTR)->mlok); LOCAL void *dbevEventUserFreeList; LOCAL void *dbevEventQueueFreeList; +static char *EVENT_PEND_NAME = "event task"; + /* * DB_EVENT_LIST() @@ -170,7 +155,7 @@ int db_event_list(char *name) printf(" ev user %lx\n", (unsigned long) pevent->ev_que->evUser); printf("ring space %u\n", RNGSPACE(pevent->ev_que)); #endif - printf( "task %x select %x pfield %lx behind by %ld\n", + printf( "task %p select %x pfield %lx behind by %ld\n", pevent->ev_que->evUser->taskid, pevent->select, (unsigned long) pevent->paddr->pfield, @@ -210,17 +195,17 @@ struct event_user *db_init_events(void) return NULL; evUser->firstque.evUser = evUser; - FASTLOCKINIT(&(evUser->firstque.writelock)); - evUser->ppendsem = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY); + evUser->firstque.writelock = semMutexCreate(); + evUser->ppendsem = semBinaryCreate(semEmpty); if(!evUser->ppendsem){ - FASTLOCKFREE(&(evUser->firstque.writelock)); + semMutexDestroy(evUser->firstque.writelock); freeListFree(dbevEventUserFreeList, evUser); return NULL; } - evUser->pflush_sem = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY); + evUser->pflush_sem = semBinaryCreate(semEmpty); if(!evUser->pflush_sem){ - FASTLOCKFREE(&(evUser->firstque.writelock)); - semDelete(evUser->ppendsem); + semMutexDestroy(evUser->firstque.writelock); + semBinaryDestroy(evUser->ppendsem); freeListFree(dbevEventUserFreeList, evUser); return NULL; } @@ -253,7 +238,7 @@ int db_close_events(struct event_user *evUser) evUser->pendexit = TRUE; /* notify the waiting task */ - semGive(evUser->ppendsem); + semBinaryGive(evUser->ppendsem); return OK; @@ -319,7 +304,7 @@ struct event_block *pevent /* ptr to event blk (not required) */ if(!tmp_que) return ERROR; tmp_que->evUser = evUser; - FASTLOCKINIT(&(tmp_que->writelock)); + tmp_que->writelock = semMutexCreate(); ev_que->nextque = tmp_que; ev_que = tmp_que; break; @@ -455,7 +440,7 @@ int db_cancel_event(struct event_block *pevent) pevent->user_sub = NULL; while (pevent->npend || pevent->callBackInProgress) { UNLOCKEVQUE(pevent->ev_que) - semTake(pevent->ev_que->evUser->pflush_sem, sysClkRateGet()); + semBinaryTakeTimeout(pevent->ev_que->evUser->pflush_sem, 1.0); LOCKEVQUE(pevent->ev_que) } UNLOCKEVQUE(pevent->ev_que) @@ -498,7 +483,7 @@ struct event_user *evUser ) { while(evUser->extra_labor){ - taskDelay(sysClkRateGet()); + threadSleep(1.0); } return OK; @@ -530,13 +515,9 @@ void *arg */ int db_post_extra_labor(struct event_user *evUser) { - int status; - /* notify the event handler of extra labor */ evUser->extra_labor = TRUE; - status = semGive(evUser->ppendsem); - assert(status == OK); - + semBinaryGive(evUser->ppendsem); return OK; } @@ -715,7 +696,7 @@ LOCAL int db_post_single_event_private(struct event_block *event) /* * notify the event handler */ - semGive(ev_que->evUser->ppendsem); + semBinaryGive(ev_que->evUser->ppendsem); } if (pLog) { @@ -739,39 +720,28 @@ int init_func_arg, int priority_offset ) { - int status; int taskpri; + int firstTry; /* only one ca_pend_event thread may be started for each evUser ! */ - while(!vxTas(&evUser->pendlck)) - return ERROR; - - status = taskPriorityGet(taskIdSelf(), &taskpri); - if(status == ERROR) - return ERROR; - + threadLockContextSwitch(); + if(evUser->pendlck==0) { + firstTry = TRUE; + ++evUser->pendlck ; + } else { + firstTry = FALSE; + } + threadUnlockContextSwitch(); + if(!firstTry) return ERROR; + taskpri = threadGetPriority(threadGetIdSelf()); taskpri += priority_offset; - evUser->pendexit = FALSE; - - if(!taskname) - taskname = EVENT_PEND_NAME; - status = - taskSpawn( - taskname, - taskpri, - EVENT_PEND_OPT, - EVENT_PEND_STACK, - event_task, - (int)evUser, - (int)init_func, - (int)init_func_arg, - 0,0,0,0,0,0,0); - if(status == ERROR) - return ERROR; - - evUser->taskid = status; - + evUser->init_func = init_func; + evUser->init_func_arg = init_func_arg; + if(!taskname) taskname = EVENT_PEND_NAME; + evUser->taskid = threadCreate( + taskname,taskpri,threadGetStackSize(threadStackMedium), + (THREADFUNC)event_task,(void *)evUser); return OK; } @@ -781,35 +751,25 @@ int priority_offset * EVENT_TASK() * */ -int event_task( -struct event_user *evUser, -int (*init_func)(), -int init_func_arg -) +void event_task( struct event_user *evUser) { int status; struct event_que *ev_que; /* init hook */ - if (init_func) { - status = (*init_func)(init_func_arg); + if (evUser->init_func) { + status = (*evUser->init_func)(evUser->init_func_arg); if (status!=OK) { - logMsg("Unable to intialize the event system!\n", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL); - semGive(evUser->ppendsem); + errlogPrintf("Unable to intialize the event system!\n"); + semBinaryGive(evUser->ppendsem); evUser->pendexit = TRUE; } } - taskwdInsert((int)taskIdCurrent,NULL,NULL); + taskwdInsert(threadGetIdSelf(),NULL,NULL); do{ - semTake(evUser->ppendsem, WAIT_FOREVER); + semBinaryTakeAssert(evUser->ppendsem); /* * check to see if the caller has offloaded @@ -830,7 +790,6 @@ int init_func_arg for( ev_que= &evUser->firstque; ev_que; ev_que = ev_que->nextque){ - event_read(ev_que); } @@ -844,13 +803,8 @@ int init_func_arg evUser->overflow_arg, evUser->queovr); else - logMsg("Events lost, discard count was %d\n", - evUser->queovr, - NULL, - NULL, - NULL, - NULL, - NULL); + errlogPrintf("Events lost, discard count was %d\n", + evUser->queovr); evUser->queovr = 0; } } @@ -859,14 +813,7 @@ int init_func_arg evUser->pendlck = FALSE; - if(FASTLOCKFREE(&evUser->firstque.writelock)<0) - logMsg("evtsk: fast lock free fail 1\n", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL); + semMutexDestroy(evUser->firstque.writelock); /* joh- added this code to free additional event queues */ { @@ -876,45 +823,20 @@ int init_func_arg while(ev_que){ nextque = ev_que->nextque; - if(FASTLOCKFREE(&ev_que->writelock)<0) - logMsg("evtsk: fast lock free fail 2\n", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL); + semMutexDestroy(ev_que->writelock); freeListFree(dbevEventQueueFreeList, ev_que); ev_que = nextque; } } - status = semDelete(evUser->ppendsem); - if(status != OK){ - logMsg("evtsk: sem delete fail at exit\n", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL); - } - status = semDelete(evUser->pflush_sem); - if(status != OK){ - logMsg("evtsk: flush sem delete fail at exit\n", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL); - } + semBinaryDestroy(evUser->ppendsem); + semBinaryDestroy(evUser->pflush_sem); freeListFree(dbevEventUserFreeList, evUser); - taskwdRemove((int)taskIdCurrent); + taskwdRemove(threadGetIdSelf()); - return OK; + return; } @@ -929,7 +851,6 @@ LOCAL int event_read (struct event_que *ev_que) db_field_log *pfl; void (*user_sub) (void *user_arg, struct dbAddr *paddr, int eventsRemaining, db_field_log *pfl); - int status; /* * evUser ring buffer must be locked for the multiple @@ -1027,11 +948,7 @@ LOCAL int event_read (struct event_que *ev_que) * queue */ if (event->user_sub==NULL && event->npend==0u) { - status = semGive (ev_que->evUser->pflush_sem); - if (status!=OK) { - epicsPrintf ("%s.%d corrupt flush sem\n", - __FILE__, __LINE__); - } + semBinaryGive (ev_que->evUser->pflush_sem); } } @@ -1049,7 +966,7 @@ void db_event_flow_ctrl_mode_on (struct event_user *evUser) /* * notify the event handler task */ - semGive (evUser->ppendsem); + semBinaryGive(evUser->ppendsem); #ifdef DEBUG printf("fc on %lu\n", tickGet()); #endif @@ -1064,7 +981,7 @@ void db_event_flow_ctrl_mode_off (struct event_user *evUser) /* * notify the event handler task */ - semGive (evUser->ppendsem); + semBinaryGive (evUser->ppendsem); #ifdef DEBUG printf("fc off %lu\n", tickGet()); #endif diff --git a/src/db/dbEvent.h b/src/db/dbEvent.h index 19be91404..3516ddab2 100644 --- a/src/db/dbEvent.h +++ b/src/db/dbEvent.h @@ -41,6 +41,7 @@ #endif /*caClient*/ #include +#include struct event_block{ ELLNODE node; @@ -78,7 +79,7 @@ typedef void EVENTFUNC( struct event_que{ /* lock writers to the ring buffer only */ /* readers must never slow up writers */ - FAST_LOCK writelock; + semId writelock; db_field_log valque[EVENTQUESIZE]; struct event_block *evque[EVENTQUESIZE]; struct event_que *nextque; /* in case que quota exceeded */ @@ -91,8 +92,8 @@ struct event_que{ struct event_user{ struct event_que firstque; /* the first event que */ - SEM_ID ppendsem; /* Wait while empty */ - SEM_ID pflush_sem; /* wait for flush */ + semId ppendsem; /* Wait while empty */ + semId pflush_sem; /* wait for flush */ void (*overflow_sub)(/* called when overflow detect */ void *overflow_arg, unsigned count); @@ -102,13 +103,15 @@ struct event_user{ (void *extralabor_arg); void *extralabor_arg;/* parameter to above */ - int taskid; /* event handler task id */ + threadId taskid; /* event handler task id */ unsigned queovr; /* event que overflow count */ unsigned nDuplicates; /* events duplicated on q */ char pendlck; /* Only one task can pend */ unsigned char pendexit; /* exit pend task */ unsigned char extra_labor; /* if set call extra labor func */ unsigned char flowCtrlMode; /* replace existing monitor */ + int (*init_func)(); + int init_func_arg; }; typedef void OVRFFUNC(void *overflow_arg, unsigned count); @@ -163,11 +166,7 @@ int init_func_arg, int priority_offset ); -int event_task( -struct event_user *evUser, -int (*init_func)(int), -int init_func_arg -); +void event_task( struct event_user *evUser); int db_event_enable(struct event_block *pevent); int db_event_disable(struct event_block *pevent); diff --git a/src/db/dbFastLinkConv.c b/src/db/dbFastLinkConv.c index e9ee8b112..556df0d08 100644 --- a/src/db/dbFastLinkConv.c +++ b/src/db/dbFastLinkConv.c @@ -28,35 +28,26 @@ * Modification Log: * ----------------- */ -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include + +#include "dbDefs.h" +#include "errlog.h" +#include "cvtFast.h" +#include "alarm.h" +#include "dbBase.h" +#include "dbAccess.h" +#include "dbConvert.h" +#include "dbStaticLib.h" +#include "dbCommon.h" +#include "dbFldTypes.h" +#include "errMdef.h" +#include "recSup.h" +#include "recGbl.h" +#include "special.h" -#include "dbDefs.h" -#include "errlog.h" -#include "fast_lock.h" -#include "cvtFast.h" -#include "alarm.h" -#include "dbBase.h" -#include "dbAccess.h" -#include "dbConvert.h" -#include "dbStaticLib.h" -#include "dbScan.h" -#include "dbCommon.h" -#include "dbFldTypes.h" -#include "db_field_log.h" -#include "errMdef.h" -#include "recSup.h" -#include "recGbl.h" -#include "special.h" - -extern struct dbBase *pdbbase; /* * In the following functions: diff --git a/src/db/dbLock.c b/src/db/dbLock.c index 97b3e9f93..ce6239de5 100644 --- a/src/db/dbLock.c +++ b/src/db/dbLock.c @@ -19,15 +19,15 @@ of this distribution. /************** DISCUSSION OF DYNAMIC LINK MODIFICATION ********************** -Since the purpose of lock sets is to prevent multiple tasks from simultaneously +Since the purpose of lock sets is to prevent multiple thread from simultaneously accessing records in set, dynamically changing lock sets presents a problem. Four problems arise: -1) Two tasks simultaneoulsy trying to change lock sets -2) Another task has successfully issued a dbScanLock and currently owns it. -3) A task is waiting for dbScanLock. -4) While lock set is being changed, a task issues a dbScanLock. +1) Two threads simultaneoulsy trying to change lock sets +2) Another thread has successfully issued a dbScanLock and currently owns it. +3) A thread is waiting for dbScanLock. +4) While lock set is being changed, a thread issues a dbScanLock. Solution: @@ -45,59 +45,57 @@ Each problem above is solved as follows: 1) dbLockGlobal solves this problem. 2) dbLockSetRecordLock solves this problem. 3) After changing lock sets original semId id deleted. - This makes all tasks in semTake for that semaphore fail. - The code in dbScanLock makes task recover. + This makes all threads in semTake for that semaphore fail. + The code in dbScanLock makes thread recover. 4) The global variable changingLockSets and code in dbScanLock and semFlush in dbLockSetGblUnlock solves this problem. -Note that all other tasks are prevented from processing records between +Note that all other threads are prevented from processing records between dbLockSetGblLock and dbLockSetGblUnlock. dblsr may crash if executed while lock sets are being modified. It is NOT a good idea to make it more robust by issuing dbLockSetGblLock -since this will delay all other tasks. +since this will delay all other threads. *****************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include -#include "dbDefs.h" -#include "dbBase.h" -#include "ellLib.h" -#include "dbAccess.h" -#include "dbStaticLib.h" -#include "dbConvert.h" -#include "dbCommon.h" -#include "dbLock.h" -#include "epicsPrint.h" -#include "dbFldTypes.h" -#include "errMdef.h" +#include "dbDefs.h" +#include "dbBase.h" +#include "osiSem.h" +#include "osiClock.h" +#include "osiThread.h" +#include "cantProceed.h" +#include "ellLib.h" +#include "dbAccess.h" +#include "dbStaticLib.h" +#include "dbConvert.h" +#include "dbCommon.h" +#include "dbLock.h" +#include "epicsPrint.h" +#include "dbFldTypes.h" +#include "errMdef.h" #define STATIC static STATIC int lockListInitialized = FALSE; STATIC ELLLIST lockList; -STATIC SEM_ID globalLockSemId; -STATIC SEM_ID globalWaitSemid; +STATIC semId globalLock; +STATIC semId globalWait; STATIC unsigned long id = 0; STATIC int changingLockSets = FALSE; typedef struct lockSet { ELLNODE node; ELLLIST recordList; - SEM_ID semId; - ULONG start_time; - int task_id; + semId lock; + unsigned long start_time; + threadId thread_id; dbCommon *precord; unsigned long id; } lockSet; @@ -107,19 +105,16 @@ typedef struct lockRecord { lockSet *plockSet; dbCommon *precord; } lockRecord; -#define semMCoptions SEM_DELETE_SAFE|SEM_INVERSION_SAFE|SEM_Q_PRIORITY /*private routines */ STATIC void initLockList(void) { ellInit(&lockList); - if((globalLockSemId = semMCreate(semMCoptions))==0) { - errMessage(0,"allocLockNode called semMCreate\n"); - exit(-1); + if((globalLock = semMutexCreate())==0) { + cantProceed("initLockList failed calling semMutexCreate\n"); } - if((globalWaitSemid = semBCreate(SEM_Q_FIFO,SEM_EMPTY))==0) { - errMessage(0,"allocLockNode called semBCreate\n"); - exit(-1); + if((globalWait = semBinaryCreate(semEmpty))==0) { + cantProceed("initLockList failed calling semBinaryCreate\n"); } lockListInitialized = TRUE; } @@ -136,9 +131,8 @@ STATIC lockSet * allocLock(lockRecord *plockRecord) plockSet->id = id; ellAdd(&plockSet->recordList,&plockRecord->node); ellAdd(&lockList,&plockSet->node); - if((plockSet->semId = semMCreate(semMCoptions))==0) { - errMessage(0,"allocLockNode called semMCreate\n"); - exit(-1); + if((plockSet->lock = semMutexCreate())==0) { + cantProceed("allocLock calling semMutexCreate\n"); } return(plockSet); } @@ -152,24 +146,18 @@ STATIC void lockAddRecord(lockSet *plockSet,lockRecord *pnew) void dbLockSetGblLock(void) { - STATUS status; - if(!lockListInitialized) initLockList(); - status = semTake(globalLockSemId,WAIT_FOREVER); - if(status!=OK) { - epicsPrintf("dbLockSetGblLock failure\n"); - taskSuspend(0); - } + semMutexTakeAssert(globalLock); changingLockSets = TRUE; } void dbLockSetGblUnlock(void) { - taskLock(); + threadLockContextSwitch(); changingLockSets = FALSE; - semFlush(globalWaitSemid); - taskUnlock(); - semGive(globalLockSemId); + semBinaryFlush(globalWait); + threadUnlockContextSwitch(); + semMutexGive(globalLock); return; } @@ -177,32 +165,31 @@ void dbLockSetRecordLock(dbCommon *precord) { lockRecord *plockRecord = precord->lset; lockSet *plockSet; - STATUS status; + semTakeStatus status; /*Make sure that dbLockSetGblLock was called*/ if(!changingLockSets) { - epicsPrintf("dbLockSetRecordLock called before dbLockSetGblLock\n"); - taskSuspend(0); + cantProceed("dbLockSetRecordLock called before dbLockSetGblLock\n"); } - /*Must make sure that no other task has lock*/ + /*Must make sure that no other thread has lock*/ if(!plockRecord) return; plockSet = plockRecord->plockSet; if(!plockSet) return; - if(plockSet->task_id==taskIdSelf()) return; + if(plockSet->thread_id==threadGetIdSelf()) return; /*Wait for up to 1 minute*/ - status = semTake(plockRecord->plockSet->semId,sysClkRateGet()*60); - if(status==OK) { - plockSet->start_time = tickGet(); - plockSet->task_id = taskIdSelf(); + status = semMutexTakeTimeout(plockRecord->plockSet->lock,60.0); + if(status==semTakeOK) { + plockSet->start_time = clockGetCurrentTick(); + plockSet->thread_id = threadGetIdSelf(); plockSet->precord = (void *)precord; /*give it back in case it will not be changed*/ - semGive(plockRecord->plockSet->semId); + semMutexGive(plockRecord->plockSet->lock); return; } /*Should never reach this point*/ - epicsPrintf("dbLockSetRecordLock timeout caller 0x%x owner 0x%x", - taskIdSelf(),plockSet->task_id); - epicsPrintf(" record %s\n",precord->name); + errlogPrintf("dbLockSetRecordLock timeout caller 0x%x owner 0x%x", + threadGetIdSelf(),plockSet->thread_id); + errlogPrintf(" record %s\n",precord->name); return; } @@ -210,25 +197,25 @@ void dbScanLock(dbCommon *precord) { lockRecord *plockRecord; lockSet *plockSet; - STATUS status; + semTakeStatus status; if(!(plockRecord= precord->lset)) { epicsPrintf("dbScanLock plockRecord is NULL record %s\n", precord->name); - taskSuspend(0); + threadSuspend(threadGetIdSelf()); } while(TRUE) { if(changingLockSets) { - semTake(globalWaitSemid,WAIT_FOREVER); + semBinaryTakeAssert(globalWait); continue; } - status = semTake(plockRecord->plockSet->semId,WAIT_FOREVER); - /*semTake fails if semDelete was called while active*/ - if(status==OK) break; + status = semMutexTake(plockRecord->plockSet->lock); + /*semMutexTake fails if semMutexDestroy was called while active*/ + if(status==semTakeOK) break; } plockSet = plockRecord->plockSet; - plockSet->start_time = tickGet(); - plockSet->task_id = taskIdSelf(); + plockSet->start_time = clockGetCurrentTick(); + plockSet->thread_id = threadGetIdSelf(); plockSet->precord = (void *)precord; return; } @@ -241,7 +228,7 @@ void dbScanUnlock(dbCommon *precord) epicsPrintf("dbScanUnlock plockRecord or plockRecord->plockSet NULL\n"); return; } - semGive(plockRecord->plockSet->semId); + semMutexGive(plockRecord->plockSet->lock); return; } @@ -347,10 +334,7 @@ void dbLockSetMerge(dbCommon *pfirst,dbCommon *psecond) p2lockRecord = (lockRecord *)ellNext(&p2lockRecord->node); } ellConcat(&p1lockSet->recordList,&p2lockSet->recordList); - if(semDelete(p2lockSet->semId)!=OK) { - errMessage(0,"dbLockSetMerge calling semDelete"); - taskSuspend(0); - } + semMutexDestroy(p2lockSet->lock); ellDelete(&lockList,&p2lockSet->node); free((void *)p2lockSet); return; @@ -409,10 +393,7 @@ void dbLockSetSplit(dbCommon *psource) } if(!plockRecord->plockSet) allocLock(plockRecord); } - if(semDelete(plockSet->semId)!=OK) { - errMessage(0,"dbLockSetSplit calling semDelete"); - taskSuspend(0); - } + semMutexDestroy(plockSet->lock); ellDelete(&lockList,&plockSet->node); free((void *)plockSet); free((void *)paprecord); @@ -453,14 +434,14 @@ long dblsr(char *recordname,int level) printf("Lock Set %lu %d members", plockSet->id,ellCount(&plockSet->recordList)); - if(semTake(plockSet->semId,NO_WAIT)==OK) { - semGive(plockSet->semId); + if(semMutexTakeNoWait(plockSet->lock)==semTakeOK) { + semMutexGive(plockSet->lock); printf(" Not Locked\n"); } else { lockSeconds = plockSet->start_time; - lockSeconds = (tickGet() - lockSeconds) / sysClkRateGet(); + lockSeconds = (clockGetCurrentTick() - lockSeconds) / clockGetRate(); printf(" Locked %f seconds", lockSeconds); - printf(" task 0x%x",plockSet->task_id); + printf(" thread %p",plockSet->thread_id); if(! plockSet->precord || !plockSet->precord->name) printf(" NULL record or record name\n"); else diff --git a/src/db/dbNotify.c b/src/db/dbNotify.c index 4687b92ce..7c5873cf1 100644 --- a/src/db/dbNotify.c +++ b/src/db/dbNotify.c @@ -31,26 +31,22 @@ * .01 03-30-95 mrk Extracted from dbLink.c */ -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include -#include "dbDefs.h" -#include "errlog.h" -#include "fast_lock.h" -#include "dbBase.h" -#include "dbAccess.h" -#include "dbStaticLib.h" -#include "dbScan.h" -#include "dbCommon.h" -#include "errMdef.h" -#include "ellLib.h" -#include "recGbl.h" +#include "dbDefs.h" +#include "osiSem.h" +#include "errlog.h" +#include "dbBase.h" +#include "dbAccess.h" +#include "dbStaticLib.h" +#include "dbScan.h" +#include "dbCommon.h" +#include "errMdef.h" +#include "ellLib.h" +#include "recGbl.h" /*NODE structure attached to ppnn field of each record in list*/ typedef struct pnWaitNode { @@ -223,7 +219,7 @@ static void notifyCallback(CALLBACK *pcallback) dbScanUnlock(precord); ppn->restart = FALSE; ppn->callbackState = callbackNotActive; - semGive((SEM_ID)ppn->waitForCallback); + semBinaryGive((semId)ppn->waitForCallback); return; } if(ppn->callbackState==callbackActive) { @@ -251,14 +247,14 @@ void dbNotifyCancel(PUTNOTIFY *ppn) dbScanLock(precord); notifyCancel(ppn); if(ppn->callbackState == callbackActive) { - ppn->waitForCallback = (void *)semBCreate(SEM_Q_FIFO,SEM_FULL); + ppn->waitForCallback = (void *)semBinaryCreate(semFull); ppn->callbackState = callbackCanceled; dbScanUnlock(precord); - if(semTake((SEM_ID)ppn->waitForCallback,sysClkRateGet()*10)!=OK) { - errMessage(0,"dbNotifyCancel had semTake timeout"); + if(semBinaryTakeTimeout((semId)ppn->waitForCallback,10.0)!=semTakeOK) { + errlogPrintf("dbNotifyCancel had semTake timeout\n"); ppn->callbackState = callbackNotActive; } - semDelete((SEM_ID)ppn->waitForCallback); + semBinaryDestroy((semId)ppn->waitForCallback); } else { dbScanUnlock(precord); } diff --git a/src/db/dbScan.c b/src/db/dbScan.c index 4628fb761..20f605359 100644 --- a/src/db/dbScan.c +++ b/src/db/dbScan.c @@ -42,47 +42,46 @@ * .12 05-02-96 mrk Allow multiple priority event scan */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include -#include "dbDefs.h" -#include "epicsPrint.h" -#include "dbBase.h" -#include "dbStaticLib.h" -#include "dbAccess.h" -#include "dbScan.h" -#include "taskwd.h" -#include "callback.h" -#include "dbBase.h" -#include "dbCommon.h" -#include "dbLock.h" -#include "devSup.h" -#include "recGbl.h" -#include "task_params.h" -#include "fast_lock.h" -#include "dbStaticLib.h" +#include "dbDefs.h" +#include "ellLib.h" +#include "osiSem.h" +#include "osiInterrupt.h" +#include "osiThread.h" +#include "osiClock.h" +#include "cantProceed.h" +#include "osiRing.h" +#include "epicsPrint.h" +#include "dbBase.h" +#include "dbStaticLib.h" +#include "dbAccess.h" +#include "dbScan.h" +#include "taskwd.h" +#include "callback.h" +#include "dbBase.h" +#include "dbCommon.h" +#include "dbLock.h" +#include "devSup.h" +#include "recGbl.h" +#include "dbStaticLib.h" extern struct dbBase *pdbbase; /* SCAN ONCE */ int onceQueueSize = 1000; -static SEM_ID onceSem; -static RING_ID onceQ; -static int onceTaskId; +static semId onceSem; +static ringId onceQ; +static threadId onceTaskId; /*all other scan types */ typedef struct scan_list{ - FAST_LOCK lock; + semId lock; ELLLIST list; short modified;/*has list been modified?*/ long ticks; /*ticks per period for periodic*/ @@ -117,12 +116,12 @@ static io_scan_list *iosl_head[NUM_CALLBACK_PRIORITIES]={NULL,NULL,NULL}; /* PERIODIC SCANNER */ static int nPeriodic=0; static scan_list **papPeriodic; /* pointer to array of pointers*/ -static int *periodicTaskId; /*array of integers after allocation*/ +static void **periodicTaskId; /*array of pointers after allocation*/ /* Private routines */ static void onceTask(void); static void initOnce(void); -static void periodicTask(scan_list *psl); +static void periodicTask(void *arg); static void initPeriodic(void); static void spawnPeriodic(int ind); static void wdPeriodic(long ind); @@ -323,7 +322,7 @@ int scanppl(double rate) /*print periodic list*/ psl = papPeriodic[i]; if(psl==NULL) continue; period = psl->ticks; - period /= vxTicksPerSecond; + period /= clockGetRate(); if(rate>0.0 && (fabs(rate - period) >.05)) continue; sprintf(message,"Scan Period= %f seconds ",period); printList(psl,message); @@ -422,7 +421,7 @@ void scanIoInit(IOSCANPVT *ppioscanpvt) callbackSetPriority(priority,&piosl->callback); callbackSetUser(piosl,&piosl->callback); ellInit(&piosl->scan_list.list); - FASTLOCKINIT(&piosl->scan_list.lock); + piosl->scan_list.lock = semMutexCreate(); piosl->next=iosl_head[priority]; iosl_head[priority]=piosl; } @@ -448,16 +447,16 @@ void scanOnce(void *precord) int lockKey; int nput; - lockKey = intLock(); - nput = rngBufPut(onceQ,(void *)&precord,sizeof(precord)); - intUnlock(lockKey); + lockKey = interruptLock(); + nput = ringPut(onceQ,(char *)&precord,sizeof(precord)); + interruptUnlock(lockKey); if(nput!=sizeof(precord)) { if(newOverflow)errMessage(0,"rngBufPut overflow in scanOnce"); newOverflow = FALSE; }else { newOverflow = TRUE; } - semGive(onceSem); + semBinaryGive(onceSem); } static void onceTask(void) @@ -465,10 +464,12 @@ static void onceTask(void) void *precord=NULL; while(TRUE) { - if(semTake(onceSem,WAIT_FOREVER)!=OK) - errMessage(0,"dbScan: semTake returned error in onceTask"); - while (rngNBytes(onceQ)>=sizeof(precord)){ - if(rngBufGet(onceQ,(void *)&precord,sizeof(precord))!=sizeof(precord)) + if(semBinaryTake(onceSem)!=semTakeOK) + errlogPrintf("dbScan: semBinaryTake returned error in onceTask"); + while(TRUE) { + int nbytes = ringGet(onceQ,(void *)&precord,sizeof(precord)); + if(nbytes==0) break; + if(nbytes!=sizeof(precord)) errMessage(0,"dbScan: rngBufGet returned error in onceTask"); dbScanLock(precord); dbProcess(precord); @@ -485,32 +486,38 @@ int scanOnceSetQueueSize(int size) static void initOnce(void) { - if((onceQ = rngCreate(sizeof(void *) * onceQueueSize))==NULL){ - errMessage(0,"dbScan: initOnce failed"); - exit(1); + if((onceQ = ringCreate(sizeof(void *) * onceQueueSize))==NULL){ + cantProceed("dbScan: initOnce failed"); } - if((onceSem=semBCreate(SEM_Q_FIFO,SEM_EMPTY))==NULL) + if((onceSem=semBinaryCreate(semEmpty))==0) errMessage(0,"semBcreate failed in initOnce"); - onceTaskId = taskSpawn(SCANONCE_NAME,SCANONCE_PRI,SCANONCE_OPT, - SCANONCE_STACK,(FUNCPTR)onceTask, - 0,0,0,0,0,0,0,0,0,0); + onceTaskId = threadCreate("scanOnce",threadPriorityScanHigh, + threadGetStackSize(threadStackBig), + (THREADFUNC)onceTask,0); taskwdInsert(onceTaskId,NULL,0L); } -static void periodicTask(scan_list *psl) +static void periodicTask(void *arg) { + scan_list *psl = (scan_list *)arg; - unsigned long start_time,end_time; - long delay; + unsigned long start_time,end_time,diff; + double delay; - start_time = tickGet(); + start_time = clockGetCurrentTick(); while(TRUE) { if(interruptAccept)scanList(psl); - end_time = tickGet(); - delay = psl->ticks - (end_time - start_time); - if(delay<=0) delay=1; - taskDelay(delay); - start_time = tickGet(); + end_time = clockGetCurrentTick(); + if(end_time>=start_time) { + diff = end_time - start_time; + } else { + /*unsigned long overflow*/ + diff = (UINT_MAX - start_time) + end_time; + } + delay = psl->ticks - diff; + delay = (delay<=0.0) ? .1 : delay/clockGetRate(); + threadSleep(delay); + start_time = clockGetCurrentTick(); } } @@ -529,28 +536,30 @@ static void initPeriodic() } nPeriodic = pmenu->nChoice - SCAN_1ST_PERIODIC; papPeriodic = dbCalloc(nPeriodic,sizeof(scan_list*)); - periodicTaskId = dbCalloc(nPeriodic,sizeof(int)); + periodicTaskId = dbCalloc(nPeriodic,sizeof(void *)); for(i=0; ilock); + psl->lock = semMutexCreate(); ellInit(&psl->list); sscanf(pmenu->papChoiceValue[i+SCAN_1ST_PERIODIC],"%f",&temp); - psl->ticks = temp * vxTicksPerSecond; + psl->ticks = temp * clockGetRate(); } } static void spawnPeriodic(int ind) { scan_list *psl; - char taskName[20]; + char taskName[20]; psl = papPeriodic[ind]; sprintf(taskName,"scan%ld",psl->ticks); - periodicTaskId[ind] = taskSpawn(taskName,PERIODSCAN_PRI-ind, - PERIODSCAN_OPT,PERIODSCAN_STACK, - (FUNCPTR )periodicTask,(int)psl, - 0,0,0,0,0,0,0,0,0); + periodicTaskId[ind] = threadCreate( + taskName, + threadPriorityScanLow + ind, + threadGetStackSize(threadStackBig), + periodicTask, + (void *)psl); taskwdInsert(periodicTaskId[ind],wdPeriodic,(void *)(long)ind); } @@ -562,7 +571,7 @@ static void wdPeriodic(long ind) psl = papPeriodic[ind]; taskwdRemove(periodicTaskId[ind]); /*Unlock so that task can be resumed*/ - FASTUNLOCK(&psl->lock); + semMutexGive(psl->lock); spawnPeriodic(ind); } @@ -579,21 +588,21 @@ static void printList(scan_list *psl,char *message) { scan_element *pse; - FASTLOCK(&psl->lock); + semMutexTakeAssert(psl->lock); pse = (scan_element *)ellFirst(&psl->list); - FASTUNLOCK(&psl->lock); + semMutexGive(psl->lock); if(pse==NULL) return; printf("%s\n",message); while(pse!=NULL) { printf(" %-28s\n",pse->precord->name); - FASTLOCK(&psl->lock); + semMutexTakeAssert(psl->lock); if(pse->pscan_list != psl) { - FASTUNLOCK(&psl->lock); + semMutexGive(psl->lock); printf("Returning because list changed while processing."); return; } pse = (scan_element *)ellNext((void *)pse); - FASTUNLOCK(&psl->lock); + semMutexGive(psl->lock); } } @@ -605,19 +614,19 @@ static void scanList(scan_list *psl) scan_element *pse,*prev; scan_element *next=0; - FASTLOCK(&psl->lock); - psl->modified = FALSE; - pse = (scan_element *)ellFirst(&psl->list); - prev = NULL; - if(pse) next = (scan_element *)ellNext((void *)pse); - FASTUNLOCK(&psl->lock); + semMutexTakeAssert(psl->lock); + psl->modified = FALSE; + pse = (scan_element *)ellFirst(&psl->list); + prev = NULL; + if(pse) next = (scan_element *)ellNext((void *)pse); + semMutexGive(psl->lock); while(pse) { struct dbCommon *precord = pse->precord; dbScanLock(precord); dbProcess(precord); dbScanUnlock(precord); - FASTLOCK(&psl->lock); + semMutexTakeAssert(psl->lock); if(!psl->modified) { prev = pse; pse = (scan_element *)ellNext((void *)pse); @@ -644,10 +653,10 @@ static void scanList(scan_list *psl) psl->modified = FALSE; } else { /*Too many changes. Just wait till next period*/ - FASTUNLOCK(&psl->lock); + semMutexGive(psl->lock); return; } - FASTUNLOCK(&psl->lock); + semMutexGive(psl->lock); } } @@ -675,7 +684,7 @@ static void addToList(struct dbCommon *precord,scan_list *psl) { scan_element *pse,*ptemp; - FASTLOCK(&psl->lock); + semMutexTakeAssert(psl->lock); pse = precord->spvt; if(pse==NULL) { pse = dbCalloc(1,sizeof(scan_element)); @@ -694,7 +703,7 @@ static void addToList(struct dbCommon *precord,scan_list *psl) } if(ptemp==NULL) ellAdd(&psl->list,(void *)pse); psl->modified = TRUE; - FASTUNLOCK(&psl->lock); + semMutexGive(psl->lock); return; } @@ -702,20 +711,20 @@ static void deleteFromList(struct dbCommon *precord,scan_list *psl) { scan_element *pse; - FASTLOCK(&psl->lock); + semMutexTakeAssert(psl->lock); if(precord->spvt==NULL) { - FASTUNLOCK(&psl->lock); + semMutexGive(psl->lock); return; } pse = precord->spvt; if(pse==NULL || pse->pscan_list!=psl) { - FASTUNLOCK(&psl->lock); + semMutexGive(psl->lock); errMessage(-1,"deleteFromList failed"); return; } pse->pscan_list = NULL; ellDelete(&psl->list,(void *)pse); psl->modified = TRUE; - FASTUNLOCK(&psl->lock); + semMutexGive(psl->lock); return; } diff --git a/src/db/dbTest.c b/src/db/dbTest.c index 6569cfd39..7beb96847 100644 --- a/src/db/dbTest.c +++ b/src/db/dbTest.c @@ -58,19 +58,16 @@ long dbtpf(char *pname,char *pvalue); /*test put field*/ long dbior(char *pdrvName,int type); /*I/O report */ int dbhcr(char *filename); /*Hardware Configuration Report*/ -#include #include +#include #include #include -#include - -/*for open and close*/ -#include +#include #include "dbDefs.h" #include "errlog.h" #include "ellLib.h" -#include "fast_lock.h" +#include "osiSem.h" #include "dbAccess.h" #include "dbBase.h" #include "dbCommon.h" @@ -443,7 +440,8 @@ long dbtr(char *pname) printf("record active\n"); return(1); } - if(FASTLOCKTEST(&precord->mlok)) { + if(semMutexTakeNoWait(precord->mlok)==semTakeOK) { + semBinaryGive(precord->mlok); printf("record locked\n"); return(1); } @@ -1294,53 +1292,3 @@ static void dbpr_msg_flush(TAB_BUFFER *pMsgBuff,int tab_size) pMsgBuff->pNexTab = pMsgBuff->out_buff + tab_size; return; } - -/* - * Call dbProcess() 100 times to make - * sure Measurement is accurate, since - * timexN() makes use of the 60Hz clock - */ -static void timing_routine(precord) -struct dbCommon *precord; -{ - int i; - - for (i = 0; i <100; i++) { - dbProcess(precord); - } -} - -/* - * Time execution of record "record_name" - */ -long dbt(record_name) -char *record_name; -{ - DBADDR address; - struct dbCommon *precord; - long status = 0; - - /* - * Convert Name To Address - */ - status = dbNameToAddr(record_name, &address); - - if (status != 0) { - errMessage(status," dbNameToAddr failed"); - return(status); - } - - precord = address.precord; - - printf("!! Time for 100 executions of %s: !!\n", record_name); - - /* - * Time the record - */ - dbScanLock(precord); - timexN((FUNCPTR)timing_routine, (int)precord, - 0,0,0,0,0,0,0); - dbScanUnlock(precord); - - return(0); -} diff --git a/src/db/db_access.c b/src/db/db_access.c index 390716e54..242ef4b88 100644 --- a/src/db/db_access.c +++ b/src/db/db_access.c @@ -45,11 +45,9 @@ *** the presumed order in dbAccess.c's dbGetField() routine ***/ -#include #include #include #include -#include #include #include diff --git a/src/db/db_test.c b/src/db/db_test.c index bd169ad43..c76a24d03 100644 --- a/src/db/db_test.c +++ b/src/db/db_test.c @@ -33,7 +33,7 @@ * .04 02-02-94 mrk added tpn (test put notify) * .05 02-03-94 mrk gft was overrunning its buffer for arrays */ -#include +#include #include #include #include @@ -655,11 +655,14 @@ static void tpnCallback(PUTNOTIFY *ppn) { struct dbAddr *pdbaddr = (struct dbAddr *)ppn->paddr; long status = ppn->status; + char *pname; + /*This is really cheating. It only works because first field is name*/ + pname = (char *)pdbaddr->precord; if(status==0) - printf("tpnCallback: success record=%s\n",ppn->paddr->precord); + printf("tpnCallback: success record=%s\n",pname); else - recGblRecordError(status,pdbaddr->precord,"tpnCallback"); + recGblRecordError(status,pname,"tpnCallback"); free((void *)pdbaddr); free(ppn); } diff --git a/src/db/dbcar.c b/src/db/dbcar.c index 55c616bcf..08b20b36a 100644 --- a/src/db/dbcar.c +++ b/src/db/dbcar.c @@ -22,12 +22,10 @@ of this distribution. * .01 10APR96 mrk list db to CA links ****************************************************************/ -#include #include #include #include #include -#include #include "dbStaticLib.h" #include "link.h" diff --git a/src/db/devLib.c b/src/db/devLib.c deleted file mode 100644 index f05e52128..000000000 --- a/src/db/devLib.c +++ /dev/null @@ -1,1103 +0,0 @@ -/* devLib.c - support for allocation of common device resources */ -/* @(#)$Id$*/ - -/* - * Original Author: Marty Kraimer - * Author: Jeff Hill - * Date: 03-10-93 - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * Modification Log: - * ----------------- - * .01 03-10-93 joh original - * .02 03-18-93 joh index address alloc array by fundamental type - * .03 03-23-93 joh changed input parameter to be a fund - * address type in favor of the argument - * that the BSP will be reconfigured - * to use an EPICS standard address - * mode - * .04 04-08-93 joh made unsolicitedHandlerEPICS() external - * .05 04-08-92 joh better diagnostic if we cant find - * a default interrupt handler - * .06 05-06-93 joh added new parameter to devDisconnectInterrupt(). - * See comment below. - * .07 05-28-93 joh Added block probe routines - * .08 05-28-93 joh Added an argument to devRegisterAddress() - * .09 05-28-93 joh Added devAddressMap() - * .10 06-14-93 joh Added devAllocAddress() - * .11 02-21-95 joh Fixed warning messages - * - * NOTES: - * .01 06-14-93 joh needs devAllocInterruptVector() routine - */ - -static char *sccsID = "@(#) $Id$"; - -#include -#include -#include - -#include "dbDefs.h" -#include "errlog.h" -#include "fast_lock.h" -#include "epicsDynLink.h" -#define devLibGlobal -#include "devLib.h" - -LOCAL ELLLIST addrAlloc[atLast]; -LOCAL ELLLIST addrFree[atLast]; - -LOCAL size_t addrLast[atLast] = { - 0xffff, - 0xffffff, - 0xffffffff, - 0xffffff - }; - -LOCAL unsigned addrHexDig[atLast] = { - 4, - 6, - 8, - 6 - }; - -LOCAL long addrFail[atLast] = { - S_dev_badA16, - S_dev_badA24, - S_dev_badA32, - S_dev_badA24 - }; - -LOCAL FAST_LOCK addrListLock; -LOCAL char devLibInitFlag; - -const char *epicsAddressTypeName[] - = { - "VME A16", - "VME A24", - "VME A32", - "ISA" - }; - -typedef struct{ - ELLNODE node; - const char *pOwnerName; - volatile void *pPhysical; - /* - * first, last is used here instead of base, size - * so that we can store a block that is the maximum size - * available in type size_t - */ - size_t begin; - size_t end; -}rangeItem; - -/* - * These routines are not exported - */ - -LOCAL long devLibInit(void); - -LOCAL long addrVerify( - epicsAddressType addrType, - size_t base, - size_t size); - -LOCAL long blockFind ( - epicsAddressType addrType, - const rangeItem *pRange, - /* size needed */ - size_t requestSize, - /* n ls bits zero in base addr */ - unsigned alignment, - /* base address found */ - size_t *pFirst); - -LOCAL void report_conflict( - epicsAddressType addrType, - size_t base, - size_t size, - const char *pOwnerName); - -LOCAL void report_conflict_device( - epicsAddressType addrType, - const rangeItem *pRange); - -LOCAL void devInsertAddress( - ELLLIST *pRangeList, - rangeItem *pNewRange); - -LOCAL long devListAddressMap( - ELLLIST *pRangeList); - -LOCAL long devCombineAdjacentBlocks( - ELLLIST *pRangeList, - rangeItem *pRange); - -LOCAL long devInstallAddr( - rangeItem *pRange, /* item on the free list to be split */ - const char *pOwnerName, - epicsAddressType addrType, - size_t base, - size_t size, - volatile void **ppPhysicalAddress); - -LOCAL struct devLibVirtualOS *pVirtOS; - -#define SUCCESS 0 - -/* - * devRegisterAddress() - */ -long devRegisterAddress( - const char *pOwnerName, - epicsAddressType addrType, - size_t base, - size_t size, - volatile void **ppPhysicalAddress) -{ - rangeItem *pRange; - long s; - - if (!devLibInitFlag) { - s = devLibInit(); - if(s){ - return s; - } - } - - s = addrVerify (addrType, base, size); - if (s) { - return s; - } - - if (size == 0) { - return S_dev_lowValue; - } - -#ifdef DEBUG - printf ("Req Addr 0X%X Size 0X%X\n", base, size); -#endif - - FASTLOCK(&addrListLock); - pRange = (rangeItem *) ellFirst(&addrFree[addrType]); - while (TRUE) { - if (pRange->begin > base) { - pRange = NULL; -# ifdef DEBUG - printf ("Unable to locate a free block\n"); - devListAddressMap (&addrFree[addrType]); -# endif - break; - } - else if (base + (size - 1) <= pRange->end) { -# ifdef DEBUG - printf ("Found free block Begin 0X%X End 0X%X\n", - pRange->begin, pRange->end); -# endif - break; - } - - pRange = (rangeItem *) ellNext (&pRange->node); - } - FASTUNLOCK(&addrListLock); - - if (pRange==NULL) { - report_conflict (addrType, base, size, pOwnerName); - return S_dev_addressOverlap; - } - - s = devInstallAddr( - pRange, /* item on the free list to be split */ - pOwnerName, - addrType, - base, - size, - ppPhysicalAddress); - - return s; -} - -/* - * devReadProbe() - * - * a bus error safe "wordSize" read at the specified address which returns - * unsuccessful status if the device isnt present - */ -long devReadProbe (unsigned wordSize, volatile const void *ptr, void *pValue) -{ - long status; - - if (!devLibInitFlag) { - status = devLibInit(); - if (status) { - return status; - } - } - - return (*pVirtOS->pDevReadProbe) (wordSize, ptr, pValue); -} - -/* - * devWriteProbe - * - * a bus error safe "wordSize" write at the specified address which returns - * unsuccessful status if the device isnt present - */ -long devWriteProbe (unsigned wordSize, volatile void *ptr, const void *pValue) -{ - long status; - - if (!devLibInitFlag) { - status = devLibInit(); - if (status) { - return status; - } - } - - return (*pVirtOS->pDevWriteProbe) (wordSize, ptr, pValue); -} - -/* - * devInstallAddr() - */ -LOCAL long devInstallAddr ( - rangeItem *pRange, /* item on the free list to be split */ - const char *pOwnerName, - epicsAddressType addrType, - size_t base, - size_t size, - volatile void **ppPhysicalAddress) -{ - volatile void *pPhysicalAddress; - rangeItem *pNewRange; - size_t reqEnd = base + (size-1); - long status; - - /* - * does it start below the specified block - */ - if (base < pRange->begin) { - return S_dev_badArgument; - } - - /* - * does it end above the specified block - */ - if (reqEnd > pRange->end) { - return S_dev_badArgument; - } - - /* - * always map through the virtual os in case the memory - * management is set up there - */ - status = (*pVirtOS->pDevMapAddr) (addrType, 0, base, - size, &pPhysicalAddress); - if (status) { - errPrintf (status, __FILE__, __LINE__, "%s base=0X%X size = 0X%X", - epicsAddressTypeName[addrType], base, size); - return status; - } - - /* - * set the callers variable if the pointer is supplied - */ - if (ppPhysicalAddress) { - *ppPhysicalAddress = pPhysicalAddress; - } - - /* - * does it start at the beginning of the block - */ - if (pRange->begin == base) { - if (pRange->end == reqEnd) { - FASTLOCK(&addrListLock); - ellDelete(&addrFree[addrType], &pRange->node); - FASTUNLOCK(&addrListLock); - free ((void *)pRange); - } - else { - pRange->begin = base + size; - } - } - /* - * does it end at the end of the block - */ - else if (pRange->end == reqEnd) { - pRange->end = base-1; - } - /* - * otherwise split the item on the free list - */ - else { - - pNewRange = (rangeItem *) calloc (1, sizeof(*pRange)); - if(!pNewRange){ - return S_dev_noMemory; - } - - pNewRange->begin = base + size; - pNewRange->end = pRange->end; - pNewRange->pOwnerName = ""; - pNewRange->pPhysical = NULL; - pRange->end = base - 1; - - /* - * add the node after the old item on the free list - * (blocks end up ordered by address) - */ - FASTLOCK(&addrListLock); - ellInsert(&addrFree[addrType], &pRange->node, &pNewRange->node); - FASTUNLOCK(&addrListLock); - } - - /* - * allocate a new address range entry and add it to - * the list - */ - pNewRange = (rangeItem *)calloc (1, sizeof(*pRange)); - if (!pNewRange) { - return S_dev_noMemory; - } - - pNewRange->begin = base; - pNewRange->end = reqEnd; - pNewRange->pOwnerName = pOwnerName; - pNewRange->pPhysical = pPhysicalAddress; - - devInsertAddress (&addrAlloc[addrType], pNewRange); - - return SUCCESS; -} - -/* - * report_conflict() - */ -LOCAL void report_conflict ( - epicsAddressType addrType, - size_t base, - size_t size, - const char *pOwnerName -) -{ - const rangeItem *pRange; - - errPrintf ( - S_dev_addressOverlap, - __FILE__, - __LINE__, - "%10s 0X%08X - OX%08X Requested by %s", - epicsAddressTypeName[addrType], - base, - base+size-1, - pOwnerName); - - pRange = (rangeItem *) ellFirst(&addrAlloc[addrType]); - while (pRange) { - - if (pRange->begin <= base + (size-1) && pRange->end >= base) { - report_conflict_device (addrType, pRange); - } - - pRange = (rangeItem *) pRange->node.next; - } -} - -/* - * report_conflict_device() - */ -LOCAL void report_conflict_device(epicsAddressType addrType, const rangeItem *pRange) -{ - errPrintf ( - S_dev_identifyOverlap, - __FILE__, - __LINE__, - "%10s 0X%08X - 0X%08X Owned by %s", - epicsAddressTypeName[addrType], - pRange->begin, - pRange->end, - pRange->pOwnerName); -} - -/* - * devUnregisterAddress() - */ -long devUnregisterAddress( - epicsAddressType addrType, - size_t baseAddress, - const char *pOwnerName) -{ - rangeItem *pRange; - int s; - - if (!devLibInitFlag) { - s = devLibInit(); - if(s) { - return s; - } - } - - s = addrVerify (addrType, baseAddress, 1); - if (s != SUCCESS) { - return s; - } - - FASTLOCK(&addrListLock); - pRange = (rangeItem *) ellFirst(&addrAlloc[addrType]); - while (pRange) { - if (pRange->begin == baseAddress) { - break; - } - if (pRange->begin > baseAddress) { - pRange = NULL; - break; - } - pRange = (rangeItem *) ellNext(&pRange->node); - } - FASTUNLOCK(&addrListLock); - - if (!pRange) { - return S_dev_addressNotFound; - } - - if (strcmp(pOwnerName,pRange->pOwnerName)) { - s = S_dev_addressOverlap; - errPrintf ( - s, - __FILE__, - __LINE__, - "unregister address for %s at 0X%X failed because %s owns it", - pOwnerName, - baseAddress, - pRange->pOwnerName); - return s; - } - - FASTLOCK (&addrListLock); - ellDelete (&addrAlloc[addrType], &pRange->node); - FASTUNLOCK (&addrListLock); - - pRange->pOwnerName = ""; - devInsertAddress (&addrFree[addrType], pRange); - s = devCombineAdjacentBlocks (&addrFree[addrType], pRange); - if(s){ - errMessage (s, NULL); - return s; - } - - return SUCCESS; -} - -/* - * devCombineAdjacentBlocks() - */ -LOCAL long devCombineAdjacentBlocks( - ELLLIST *pRangeList, - rangeItem *pRange) -{ - rangeItem *pBefore; - rangeItem *pAfter; - - pBefore = (rangeItem *) ellPrevious (&pRange->node); - pAfter = (rangeItem *) ellNext (&pRange->node); - - /* - * combine adjacent blocks - */ - if (pBefore) { - if (pBefore->end == pRange->begin-1) { - FASTLOCK(&addrListLock); - pRange->begin = pBefore->begin; - ellDelete (pRangeList, &pBefore->node); - FASTUNLOCK(&addrListLock); - free ((void *)pBefore); - } - } - - if (pAfter) { - if (pAfter->begin == pRange->end+1) { - FASTLOCK(&addrListLock); - pRange->end = pAfter->end; - ellDelete (pRangeList, &pAfter->node); - FASTUNLOCK(&addrListLock); - free((void *)pAfter); - } - } - - return SUCCESS; -} - -/* - * devInsertAddress() - */ -LOCAL void devInsertAddress( -ELLLIST *pRangeList, -rangeItem *pNewRange) -{ - rangeItem *pBefore; - rangeItem *pAfter; - - FASTLOCK(&addrListLock); - pAfter = (rangeItem *) ellFirst (pRangeList); - while (pAfter) { - if (pNewRange->end < pAfter->begin) { - break; - } - pAfter = (rangeItem *) ellNext (&pAfter->node); - } - - if (pAfter) { - pBefore = (rangeItem *) ellPrevious (&pAfter->node); - ellInsert (pRangeList, &pBefore->node, &pNewRange->node); - } - else { - ellAdd (pRangeList, &pNewRange->node); - } - FASTUNLOCK(&addrListLock); -} - -/* - * devAllocAddress() - */ -long devAllocAddress( - const char *pOwnerName, - epicsAddressType addrType, - size_t size, - unsigned alignment, /* n ls bits zero in base addr*/ - volatile void **pLocalAddress) -{ - int s; - rangeItem *pRange; - size_t base; - - if (!devLibInitFlag) { - s = devLibInit(); - if(s){ - return s; - } - } - - s = addrVerify (addrType, 0, size); - if(s){ - return s; - } - - if (size == 0) { - return S_dev_lowValue; - } - - FASTLOCK(&addrListLock); - pRange = (rangeItem *) ellFirst (&addrFree[addrType]); - while (pRange) { - if ((pRange->end - pRange->begin) + 1 >= size){ - s = blockFind ( - addrType, - pRange, - size, - alignment, - &base); - if (s==SUCCESS) { - break; - } - } - pRange = (rangeItem *) pRange->node.next; - } - FASTUNLOCK(&addrListLock); - - if(!pRange){ - s = S_dev_deviceDoesNotFit; - errMessage(s, epicsAddressTypeName[addrType]); - return s; - } - - s = devInstallAddr (pRange, pOwnerName, addrType, base, - size, NULL); - - return s; -} - -/* - * addrVerify() - * - * care has been taken here not to overflow type size_t - */ -LOCAL long addrVerify(epicsAddressType addrType, size_t base, size_t size) -{ - if (addrType>=atLast) { - return S_dev_uknAddrType; - } - - if (size == 0) { - return addrFail[addrType]; - } - - if (size-1 > addrLast[addrType]) { - return addrFail[addrType]; - } - - if (base > addrLast[addrType]) { - return addrFail[addrType]; - } - - if (size - 1 > addrLast[addrType] - base) { - return addrFail[addrType]; - } - - return SUCCESS; -} - -/* - * devLibInit() - */ -LOCAL long devLibInit (void) -{ - rangeItem *pRange; - - - if (!devLibInitFlag) { - unsigned i; - SYM_TYPE stype; - const char *pSymName = "_devLibVirtualOS"; - - /* - * dynamic bind to the virtual os layer for devLib - */ - if (symFindByNameEPICS (sysSymTbl, "_devLibVirtualOS", - (char**)&pVirtOS, &stype)==ERROR) - { - epicsPrintf ("unable to locate symbol \"%s\" - unable to initialize devLib\n", pSymName); - return S_dev_internal; - } - - if (NELEMENTS(addrAlloc) != NELEMENTS(addrFree)) { - return S_dev_internal; - } - - FASTLOCKINIT(&addrListLock); - - FASTLOCK(&addrListLock); - for (i=0; ipOwnerName = ""; - pRange->pPhysical = NULL; - pRange->begin = 0; - pRange->end = addrLast[i]; - ellAdd (&addrFree[i], &pRange->node); - } - FASTUNLOCK(&addrListLock); - devLibInitFlag = TRUE; - } - - return SUCCESS; -} - -/* - * devAddressMap() - */ -long devAddressMap(void) -{ - return devListAddressMap(addrAlloc); -} - -/* - * devListAddressMap() - */ -LOCAL long devListAddressMap(ELLLIST *pRangeList) -{ - rangeItem *pri; - int i; - long s; - - if (!devLibInitFlag) { - s = devLibInit (); - if (s) { - return s; - } - } - - FASTLOCK(&addrListLock); - for (i=0; ibegin, - addrHexDig[i], - (unsigned long) pri->end, - pri->pPhysical, - pri->pOwnerName); - pri = (rangeItem *) ellNext (&pri->node); - } - } - FASTUNLOCK(&addrListLock); - - return SUCCESS; -} - - -/* - * - * blockFind() - * - * Find unoccupied block in a large block - * - */ -LOCAL long blockFind ( - epicsAddressType addrType, - const rangeItem *pRange, - /* size needed */ - size_t requestSize, - /* n ls bits zero in base addr */ - unsigned alignment, - /* base address found */ - size_t *pBase) -{ - int s = SUCCESS; - size_t bb; - size_t mask; - size_t newBase; - size_t newSize; - - /* - * align the block base - */ - mask = devCreateMask (alignment); - newBase = pRange->begin; - if ( mask & newBase ) { - newBase |= mask; - newBase++; - } - - if ( requestSize == 0) { - return S_dev_badRequest; - } - - /* - * align size of block - */ - newSize = requestSize; - if (mask & newSize) { - newSize |= mask; - newSize++; - } - - if (pRange->end - pRange->begin + 1 < newSize) { - return S_dev_badRequest; - } - - bb = pRange->begin; - while (bb <= (pRange->end + 1) - newSize) { - s = devNoResponseProbe (addrType, bb, newSize); - if (s==SUCCESS) { - *pBase = bb; - return SUCCESS; - } - bb += newSize; - } - - return s; -} - -/* - * devNoResponseProbe() - */ -long devNoResponseProbe (epicsAddressType addrType, - size_t base, size_t size) -{ - volatile void *pPhysical; - size_t probe; - size_t byteNo; - unsigned wordSize; - union { - char charWord; - short shortWord; - int intWord; - long longWord; - }allWordSizes; - long s; - - if (!devLibInitFlag) { - s = devLibInit(); - if (s) { - return s; - } - } - - byteNo = 0; - while (byteNo < size) { - - probe = base + byteNo; - - /* - * for all word sizes - */ - for (wordSize=1; wordSize<=sizeof(allWordSizes); wordSize <<= 1) { - /* - * only check naturally aligned words - */ - if ( (probe&(wordSize-1)) != 0 ) { - break; - } - - if (byteNo+wordSize>size) { - break; - } - - /* - * every byte in the block must - * map to a physical address - */ - s = (*pVirtOS->pDevMapAddr) (addrType, 0, probe, wordSize, &pPhysical); - if (s!=SUCCESS) { - return s; - } - - /* - * verify that no device is present - */ - s = (*pVirtOS->pDevReadProbe)(wordSize, pPhysical, &allWordSizes); - if (s==SUCCESS) { - return S_dev_addressOverlap; - } - } - byteNo++; - } - return SUCCESS; -} - -/* - * devConnectInterrupt () - * - * !! DEPRECATED !! - */ -long devConnectInterrupt( -epicsInterruptType intType, -unsigned vectorNumber, -void (*pFunction)(), -void *parameter) -{ - long status; - - if (!devLibInitFlag) { - status = devLibInit(); - if (status) { - return status; - } - } - - switch(intType){ - case intVME: - case intVXI: - return (*pVirtOS->pDevConnectInterruptVME) (vectorNumber, - pFunction, parameter); - default: - return S_dev_uknIntType; - } -} - -/* - * - * devDisconnectInterrupt() - * - * !! DEPRECATED !! - */ -long devDisconnectInterrupt( -epicsInterruptType intType, -unsigned vectorNumber, -void (*pFunction)() -) -{ - long status; - - if (!devLibInitFlag) { - status = devLibInit(); - if (status) { - return status; - } - } - - switch(intType){ - case intVME: - case intVXI: - return (*pVirtOS->pDevDisconnectInterruptVME) (vectorNumber, - pFunction); - break; - default: - return S_dev_uknIntType; - } -} - -/* - * devEnableInterruptLevel() - * - * !! DEPRECATED !! - */ -long devEnableInterruptLevel( -epicsInterruptType intType, -unsigned level) -{ - long status; - - if (!devLibInitFlag) { - status = devLibInit(); - if (status) { - return status; - } - } - - switch(intType){ - case intVME: - case intVXI: - return (*pVirtOS->pDevEnableInterruptLevelVME) (level); - default: - return S_dev_uknIntType; - } -} - -/* - * devDisableInterruptLevel() - * - * !! DEPRECATED !! - */ -long devDisableInterruptLevel ( -epicsInterruptType intType, -unsigned level) -{ - long status; - - if (!devLibInitFlag) { - status = devLibInit(); - if (status) { - return status; - } - } - - switch(intType){ - case intVME: - case intVXI: - return (*pVirtOS->pDevDisableInterruptLevelVME) (level); - default: - return S_dev_uknIntType; - } -} - -/* - * locationProbe - * - * !! DEPRECATED !! - */ -long locationProbe (epicsAddressType addrType, char *pLocation) -{ - return devNoResponseProbe (addrType, (size_t) pLocation, sizeof(long)); -} - -/****************************************************************************** - * - * The follwing may, or may not be present in the BSP for the CPU in use. - * - */ -void *sysA24Malloc(size_t size); -STATUS sysA24Free(void *pBlock); - -/****************************************************************************** - * - * Routines to use to allocate and free memory present in the A24 region. - * - ******************************************************************************/ - -static void * (*A24MallocFunc)(size_t) = NULL; -static void (*A24FreeFunc)(void *) = NULL; -int devLibA24Debug = 0; /* Debugging flag */ - -void *devLibA24Calloc(size_t size) -{ - void *ret; - - ret = devLibA24Malloc(size); - - if (ret == NULL) - return (NULL); - - memset(ret, 0x00, size); - return(ret); -} - -void *devLibA24Malloc(size_t size) -{ - SYM_TYPE stype; - static int UsingBSP = 0; - void *ret; - - if (devLibA24Debug) - epicsPrintf ("devLibA24Malloc(%d) entered\n", size); - - if (A24MallocFunc == NULL) - { - /* See if the sysA24Malloc() function is present. */ - if(symFindByNameEPICS (sysSymTbl,"_sysA24Malloc", (char**)&A24MallocFunc, &stype)==ERROR) - { /* Could not find sysA24Malloc... use the malloc one and hope we are OK */ - if (devLibA24Debug) - epicsPrintf ("devLibA24Malloc() using regular malloc\n"); - A24MallocFunc = malloc; - A24FreeFunc = free; - } - else - { - if(symFindByNameEPICS(sysSymTbl,"_sysA24Free", (char**)&A24FreeFunc, &stype) == ERROR) - { /* That's strange... we have malloc, but no free! */ - if (devLibA24Debug) - epicsPrintf ("devLibA24Malloc() using regular malloc\n"); - A24MallocFunc = malloc; - A24FreeFunc = free; - } - else - UsingBSP = 1; - } - } - ret = A24MallocFunc(size); - - if ((ret == NULL) && (UsingBSP)) - errMessage(S_dev_noMemory, "devLibA24Malloc ran out of A24 memory, try sysA24MapRam(size)"); - - return(ret); -} - -void devLibA24Free(void *pBlock) -{ - if (devLibA24Debug) - epicsPrintf("devLibA24Free(%p) entered\n", pBlock); - - A24FreeFunc(pBlock); -} diff --git a/src/db/devLib.h b/src/db/devLib.h deleted file mode 100644 index 8dcdcbf9c..000000000 --- a/src/db/devLib.h +++ /dev/null @@ -1,444 +0,0 @@ -/* devLib.h */ -/* $Id$ */ - -/* - * Original Author: Marty Kraimer - * Author: Jeff Hill - * Date: 03-10-93 - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * Modification Log: - * ----------------- - * .01 03-10-93 joh original - * .02 03-18-93 joh added fundamental address type mapping - * .03 03-23-93 joh changed input parameter to be a fund - * address type in favor of the argument - * that the BSP will be reconfigured - * to use an EPICS standard address - * mode - * .04 05-06-93 joh added new parameter to devDisconnectInterrupt(). - * See comment below. - * .05 05-28-93 joh Added an argument to devRegisterAddress() - * .06 05-28-93 joh Added devAddressMap() - * .07 06-14-93 joh Added devAllocAddress() - * - * Notes: - * ------ - * .01 03-23-93 joh We will only have problems with mod .03 - * above if the CPU maintains the different - * address modes in different address spaces - * and we have a card or a user that insists - * on not using the default address type - * .02 06-14-93 joh needs devAllocInterruptVector() routine - */ - -#ifndef INCdevLibh -#define INCdevLibh 1 - -#include - -/* - * epdevAddressType & EPICStovxWorksAddrType - * devLib.c must change in unison - */ -typedef enum { - atVMEA16, - atVMEA24, - atVMEA32, - atISA, /* memory mapped ISA access (until now only on PC) */ - atLast /* atLast must be the last enum in this list */ - } epicsAddressType; - -/* - * pointer to an array of strings for each of - * the above address types - */ -extern const char *epicsAddressTypeName[]; - -long devAddressMap(void); /* print an address map */ - -/* - * devReadProbe() - * - * a bus error safe "wordSize" read at the specified address which returns - * unsuccessful status if the device isnt present - */ -long devReadProbe (unsigned wordSize, volatile const void *ptr, void *pValueRead); - -/* - * devNoResponseProbe() - * - * Verifies that no devices respond at naturally aligned words - * within the specified address range. Return success if no devices - * respond. Returns an error if a device does respond or if - * a physical address for a naturally aligned word cant be mapped. - * Checks all naturally aligned word sizes between char and long for - * the entire specified range of bytes. - */ -long devNoResponseProbe( - epicsAddressType addrType, - size_t base, - size_t size -); - -/* - * devWriteProbe - * - * a bus error safe "wordSize" write at the specified address which returns - * unsuccessful status if the device isnt present - */ -long devWriteProbe (unsigned wordSize, volatile void *ptr, const void *pValueWritten); - -long devRegisterAddress( - const char *pOwnerName, - epicsAddressType addrType, - size_t logicalBaseAddress, - size_t size, /* bytes */ - volatile void **pPhysicalAddress); - -long devUnregisterAddress( - epicsAddressType addrType, - size_t logicalBaseAddress, - const char *pOwnerName); - -/* - * allocate and register an unoccupied address block - */ -long devAllocAddress( - const char *pOwnerName, - epicsAddressType addrType, - size_t size, - unsigned alignment, /*n ls bits zero in addr*/ - volatile void **pLocalAddress); - -/* - * connect ISR to a VME interrupt vector - */ -long devConnectInterruptVME( - unsigned vectorNumber, - void (*pFunction)(void *), - void *parameter); - -/* - * connect ISR to an ISA interrupt level - * (not implemented) - * (API should be reviewed) - */ -long devConnectInterruptISA( - unsigned interruptLevel, - void (*pFunction)(void *), - void *parameter); - -/* - * connect ISR to a PCI interrupt - * (not implemented) - * (API should be reviewed) - */ -long devConnectInterruptPCI( - unsigned bus, - unsigned device, - unsigned function, - void (*pFunction)(void *), - void *parameter); - -/* - * disconnect ISR from a VME interrupt vector - * - * The parameter pFunction should be set to the C function pointer that - * was connected. It is used as a key to prevent a driver from inadvertently - * removing an interrupt handler that it didn't install - */ -long devDisconnectInterruptVME( - unsigned vectorNumber, - void (*pFunction)(void *)); - -/* - * disconnect ISR from an ISA interrupt level - * (not implemented) - * (API should be reviewed) - * - * The parameter pFunction should be set to the C function pointer that - * was connected. It is used as a key to prevent a driver from inadvertently - * removing an interrupt handler that it didn't install - */ -long devDisconnectInterruptISA( - unsigned interruptLevel, - void (*pFunction)(void *)); - -/* - * disconnect ISR from a PCI interrupt - * (not implemented) - * (API should be reviewed) - * - * The parameter pFunction should be set to the C function pointer that - * was connected. It is used as a key to prevent a driver from inadvertently - * removing an interrupt handler that it didn't install - */ -long devDisconnectInterruptPCI( - unsigned bus, - unsigned device, - unsigned function, - void (*pFunction)(void *)); - -/* - * determine if a VME interrupt vector is in use - * - * returns boolean - */ -int devInterruptInUseVME (unsigned vectorNumber); - -/* - * determine if an ISA interrupt level is in use - * (not implemented) - * - * returns boolean - */ -int devInterruptLevelInUseISA (unsigned interruptLevel); - -/* - * determine if a PCI interrupt is in use - * (not implemented) - * - * returns boolean - */ -int devInterruptInUsePCI (unsigned bus, unsigned device, - unsigned function); - -typedef enum {intVME, intVXI, intISA} epicsInterruptType; - -/* - * enable VME interrupt level - */ -long devEnableInterruptLevelVME (unsigned level); - -/* - * enable ISA interrupt level - */ -long devEnableInterruptLevelISA (unsigned level); - -/* - * not implemented - API needs to be reviewed - */ -long devEnableInterruptLevelPCI (unsigned level, - unsigned bus, unsigned device, unsigned function); - -/* - * disable VME interrupt level - */ -long devDisableInterruptLevelVME (unsigned level); - -/* - * disable ISA interrupt level - */ -long devDisableInterruptLevelISA (unsigned level); - -/* - * not implemented - API needs to be reviewed - */ -long devDisableInterruptLevelPCI (unsigned level, - unsigned bus, unsigned device, unsigned function); - -/* - * Routines to allocate and free memory in the A24 memory region. - * - */ -void *devLibA24Malloc(size_t); -void *devLibA24Calloc(size_t); -void devLibA24Free(void *pBlock); - -/* - * Normalize a digital value and convert it to type TYPE - * - * Ex: - * float f; - * int d; - * f = devNormalizeDigital(d,12) - * - */ -#define devCreateMask(NBITS) ((1<<(NBITS))-1) -#define devDigToNml(DIGITAL,NBITS) \ - (((double)(DIGITAL))/devCreateMask(NBITS)) -#define devNmlToDig(NORMAL,NBITS) \ - (((long)(NORMAL)) * devCreateMask(NBITS)) - -/* - * - * Alignment mask - * (for use when testing to see if the proper number of least - * significant bits are zero) - * - */ -#define devCreateAlignmentMask(CTYPE)\ -(sizeof(CTYPE)>sizeof(double)?sizeof(double)-1:sizeof(CTYPE)-1) - -/* - * pointer aligned test - * (returns true if the pointer is on the worst case alignemnt - * boundary for its type) - */ -#define devPtrAlignTest(PTR) (!(devCreateAlignmentMask(*PTR)&(long)(PTR))) - -/* - * virtual OS layer for devLib.c - */ -struct devLibVirtualOS { - /* - * maps logical address to physical address, but does not detect - * two device drivers that are using the same address range - */ - long (*pDevMapAddr) (epicsAddressType addrType, unsigned options, - size_t logicalAddress, size_t size, volatile void **ppPhysicalAddress); - - /* - * a bus error safe "wordSize" read at the specified address which returns - * unsuccessful status if the device isnt present - */ - long (*pDevReadProbe) (unsigned wordSize, volatile const void *ptr, void *pValueRead); - - /* - * a bus error safe "wordSize" write at the specified address which returns - * unsuccessful status if the device isnt present - */ - long (*pDevWriteProbe) (unsigned wordSize, volatile void *ptr, const void *pValueWritten); - - /* - * connect ISR to a VME interrupt vector - * (required for backwards compatibility) - */ - long (*pDevConnectInterruptVME) (unsigned vectorNumber, - void (*pFunction)(), void *parameter); - - /* - * disconnect ISR from a VME interrupt vector - * (required for backwards compatibility) - */ - long (*pDevDisconnectInterruptVME) (unsigned vectorNumber, - void (*pFunction)(void *)); - - /* - * enable VME interrupt level - */ - long (*pDevEnableInterruptLevelVME) (unsigned level); - - /* - * disable VME interrupt level - */ - long (*pDevDisableInterruptLevelVME) (unsigned level); -}; - -/* - * error codes (and messages) associated with devLib.c - */ -#define S_dev_success 0 -#define S_dev_vectorInUse (M_devLib| 1) /*interrupt vector in use*/ -#define S_dev_vecInstlFail (M_devLib| 2) /*interrupt vector install failed*/ -#define S_dev_uknIntType (M_devLib| 3) /*Unrecognized interrupt type*/ -#define S_dev_vectorNotInUse (M_devLib| 4) /*Interrupt vector not in use by caller*/ -#define S_dev_badA16 (M_devLib| 5) /*Invalid VME A16 address*/ -#define S_dev_badA24 (M_devLib| 6) /*Invalid VME A24 address*/ -#define S_dev_badA32 (M_devLib| 7) /*Invalid VME A32 address*/ -#define S_dev_uknAddrType (M_devLib| 8) /*Unrecognized address space type*/ -#define S_dev_addressOverlap (M_devLib| 9) /*Specified device address overlaps another device*/ -#define S_dev_identifyOverlap (M_devLib| 10) /*This device already owns the address range*/ -#define S_dev_addrMapFail (M_devLib| 11) /*unable to map address*/ -#define S_dev_intDisconnect (M_devLib| 12) /*Interrupt at vector disconnected from an EPICS device*/ -#define S_dev_internal (M_devLib| 13) /*Internal failure*/ -#define S_dev_intEnFail (M_devLib| 14) /*unable to enable interrupt level*/ -#define S_dev_intDissFail (M_devLib| 15) /*unable to disable interrupt level*/ -#define S_dev_noMemory (M_devLib| 16) /*Memory allocation failed*/ -#define S_dev_addressNotFound (M_devLib| 17) /*Specified device address unregistered*/ -#define S_dev_noDevice (M_devLib| 18) /*No device at specified address*/ -#define S_dev_wrongDevice (M_devLib| 19) /*Wrong device type found at specified address*/ -#define S_dev_badSignalNumber (M_devLib| 20) /*Signal number (offset) to large*/ -#define S_dev_badSignalCount (M_devLib| 21) /*Signal count to large*/ -#define S_dev_badRequest (M_devLib| 22) /*Device does not support requested operation*/ -#define S_dev_highValue (M_devLib| 23) /*Parameter to high*/ -#define S_dev_lowValue (M_devLib| 24) /*Parameter to low*/ -#define S_dev_multDevice (M_devLib| 25) /*Specified address is ambiguous (more than one device responds)*/ -#define S_dev_badSelfTest (M_devLib| 26) /*Device self test failed*/ -#define S_dev_badInit (M_devLib| 27) /*Device failed during initialization*/ -#define S_dev_hdwLimit (M_devLib| 28) /*Input exceeds Hardware Limit*/ -#define S_dev_deviceDoesNotFit (M_devLib| 29) /*Unable to locate address space for device*/ -#define S_dev_deviceTMO (M_devLib| 30) /*device timed out*/ -#define S_dev_badFunction (M_devLib| 31) /*bad function pointer*/ -#define S_dev_badVector (M_devLib| 32) /*bad interrupt vector*/ -#define S_dev_badArgument (M_devLib| 33) /*bad function argument*/ -#define S_dev_vxWorksIntEnFail S_dev_intEnFail - -/* - * NOTE: this routine has been deprecated. It exists - * for backwards compatibility purposes only. - * - * Please use one of devConnectInterruptVME, devConnectInterruptPCI, - * devConnectInterruptISA etc. devConnectInterrupt will be removed - * in a future release. - */ -long devConnectInterrupt( - epicsInterruptType intType, - unsigned vectorNumber, - void (*pFunction)(), - void *parameter); - -/* - * NOTE: this routine has been deprecated. It exists - * for backwards compatibility purposes only. - * - * Please use one of devDisconnectInterruptVME, devDisconnectInterruptPCI, - * devDisconnectInterruptISA etc. devDisconnectInterrupt will be removed - * in a future release. - */ -long devDisconnectInterrupt( - epicsInterruptType intType, - unsigned vectorNumber, - void (*pFunction)()); - -/* - * NOTE: this routine has been deprecated. It exists - * for backwards compatibility purposes only. - * - * Please use one of devEnableInterruptLevelVME, devEnableInterruptLevelPCI, - * devEnableInterruptLevelISA etc. devEnableInterruptLevel will be removed - * in a future release. - */ -long devEnableInterruptLevel(epicsInterruptType intType, unsigned level); - -/* - * NOTE: this routine has been deprecated. It exists - * for backwards compatibility purposes only. - * - * Please use one of devDisableInterruptLevelVME, devDisableInterruptLevelISA, - * devDisableInterruptLevelPCI etc. devDisableInterruptLevel will be removed - * in a future release. - */ -long devDisableInterruptLevel (epicsInterruptType intType, unsigned level); - -/* - * NOTE: this routine has been deprecated. It exists - * for backwards compatibility purposes only. - * - * Please use devNoResponseProbe(). locationProbe() will be removed - * in a future release. - */ -long locationProbe (epicsAddressType addrType, char *pLocation); - -#endif /* devLib.h*/ diff --git a/src/db/devLibVxWorks.c b/src/db/devLibVxWorks.c deleted file mode 100644 index c9591649b..000000000 --- a/src/db/devLibVxWorks.c +++ /dev/null @@ -1,430 +0,0 @@ -/* - * devLibVxWorks.c - * @(#)$Id$ - * - * Archictecture dependent support for common device driver resources - * - * Author: Jeff Hill - * Date: 10-30-98 - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - */ - -static char *sccsID = "@(#) $Id$"; - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "devLib.h" -#include "epicsDynLink.h" - -/* - * A list of the names of the unexpected interrupt handlers - * ( some of these are provided by wrs ) - */ -LOCAL char *defaultHandlerNames[] = { - "_excStub", - "_excIntStub", - "_unsolicitedHandlerEPICS"}; - -typedef void myISR (void *pParam); -LOCAL myISR *defaultHandlerAddr[NELEMENTS(defaultHandlerNames)]; - -LOCAL myISR *isrFetch(unsigned vectorNumber); - -/* - * this routine needs to be in the symbol table - * for this code to work correctly - */ -void unsolicitedHandlerEPICS(int vectorNumber); - -/* - * this is in veclist.c - */ -int cISRTest(void (*)(), void (**)(), void **); - -/* - * we use a translation between an EPICS encoding - * and a vxWorks encoding here - * to reduce dependency of drivers on vxWorks - * - * we assume that the BSP are configured to use these - * address modes by default - */ -#define EPICSAddrTypeNoConvert -1 -int EPICStovxWorksAddrType[] - = { - VME_AM_SUP_SHORT_IO, - VME_AM_STD_SUP_DATA, - VME_AM_EXT_SUP_DATA, - EPICSAddrTypeNoConvert - }; - -LOCAL void initHandlerAddrList(void); - -/* - * maps logical address to physical address, but does not detect - * two device drivers that are using the same address range - */ -LOCAL long vxDevMapAddr (epicsAddressType addrType, unsigned options, - size_t logicalAddress, size_t size, volatile void **ppPhysicalAddress); - -/* - * a bus error safe "wordSize" read at the specified address which returns - * unsuccessful status if the device isnt present - */ -long vxDevReadProbe (unsigned wordSize, volatile const void *ptr, void *pValue); - -/* - * a bus error safe "wordSize" write at the specified address which returns - * unsuccessful status if the device isnt present - */ -long vxDevWriteProbe (unsigned wordSize, volatile void *ptr, const void *pValue); - -/* - * used by dynamic bind in devLib.c - */ -const struct devLibVirtualOS devLibVirtualOS = - {vxDevMapAddr, vxDevReadProbe, vxDevWriteProbe, - devConnectInterruptVME, devDisconnectInterruptVME, - devEnableInterruptLevelVME, devDisableInterruptLevelVME}; - -#define SUCCESS 0 - -/* - * devConnectInterruptVME - * - * wrapper to minimize driver dependency on vxWorks - */ -long devConnectInterruptVME ( - unsigned vectorNumber, - void (*pFunction)(), - void *parameter) -{ - int status; - - - if (devInterruptInUseVME(vectorNumber)) { - return S_dev_vectorInUse; - } - status = intConnect( - (void *)INUM_TO_IVEC(vectorNumber), - pFunction, - (int) parameter); - if (status<0) { - return S_dev_vecInstlFail; - } - - return SUCCESS; -} - -/* - * - * devDisconnectInterruptVME() - * - * wrapper to minimize driver dependency on vxWorks - * - * The parameter pFunction should be set to the C function pointer that - * was connected. It is used as a key to prevent a driver from removing - * an interrupt handler that was installed by another driver - * - */ -long devDisconnectInterruptVME ( - unsigned vectorNumber, - void (*pFunction)() -) -{ - void (*psub)(); - int status; - - /* - * If pFunction not connected to this vector - * then they are probably disconnecting from the wrong vector - */ - psub = isrFetch(vectorNumber); - if(psub != pFunction){ - return S_dev_vectorNotInUse; - } - - status = intConnect( - (void *)INUM_TO_IVEC(vectorNumber), - unsolicitedHandlerEPICS, - (int) vectorNumber); - if(status<0){ - return S_dev_vecInstlFail; - } - - return SUCCESS; -} - -/* - * enable VME interrupt level - */ -long devEnableInterruptLevelVME (unsigned level) -{ - int s; - - s = sysIntEnable (level); - if (s!=OK) { - return S_dev_intEnFail; - } - - return SUCCESS; -} - -/* - * enable ISA interrupt level - */ -long devEnableInterruptLevelISA (unsigned level) -{ -# if CPU == I80386 - int s; - s = sysIntEnablePIC (level); - if (s!=OK) { - return S_dev_intEnFail; - } - return SUCCESS; -# else - return S_dev_intEnFail; -# endif -} - -/* - * disable ISA interrupt level - */ -long devDisableInterruptLevelISA (unsigned level) -{ -# if CPU == I80386 - int s; - s = sysIntDisablePIC (level); - if (s!=OK) { - return S_dev_intEnFail; - } -# else - return S_dev_intEnFail; -# endif - - return SUCCESS; -} - -/* - * disable VME interrupt level - */ -long devDisableInterruptLevelVME (unsigned level) -{ - int s; - - s = sysIntDisable (level); - if (s!=OK) { - return S_dev_intDissFail; - } - - return SUCCESS; -} - -/* - * vxDevMapAddr () - */ -LOCAL long vxDevMapAddr (epicsAddressType addrType, unsigned options, - size_t logicalAddress, size_t size, volatile void **ppPhysicalAddress) -{ - long status; - - if (ppPhysicalAddress==NULL) { - return S_dev_badArgument; - } - - if (EPICStovxWorksAddrType[addrType] == EPICSAddrTypeNoConvert) - { - *ppPhysicalAddress = (void *) logicalAddress; - } - else - { - status = sysBusToLocalAdrs (EPICStovxWorksAddrType[addrType], - (char *) logicalAddress, (char **)ppPhysicalAddress); - if (status) { - return S_dev_addrMapFail; - } - } - - return SUCCESS; -} - -/* - * a bus error safe "wordSize" read at the specified address which returns - * unsuccessful status if the device isnt present - */ -long vxDevReadProbe (unsigned wordSize, volatile const void *ptr, void *pValue) -{ - long status; - - /* - * this global variable exists in the nivxi library - */ - status = vxMemProbe ((char *)ptr, VX_READ, wordSize, (char *) pValue); - if (status!=OK) { - return S_dev_noDevice; - } - - return SUCCESS; -} - -/* - * a bus error safe "wordSize" write at the specified address which returns - * unsuccessful status if the device isnt present - */ -long vxDevWriteProbe (unsigned wordSize, volatile void *ptr, const void *pValue) -{ - long status; - - /* - * this global variable exists in the nivxi library - */ - status = vxMemProbe ((char *)ptr, VX_READ, wordSize, (char *) pValue); - if (status!=OK) { - return S_dev_noDevice; - } - - return SUCCESS; -} - -/* - * isrFetch() - */ -LOCAL myISR *isrFetch(unsigned vectorNumber) -{ - myISR *psub; - myISR *pCISR; - void *pParam; - int s; - - /* - * fetch the handler or C stub attached at this vector - */ - psub = (myISR *) intVecGet((FUNCPTR *)INUM_TO_IVEC(vectorNumber)); - - /* - * from libvxWorks/veclist.c - * - * checks to see if it is a C ISR - * and if so finds the function pointer and - * the parameter passed - */ - s = cISRTest(psub, &pCISR, &pParam); - if(!s){ - psub = pCISR; - } - - return psub; -} - -/* - * determine if a VME interrupt vector is in use - */ -int devInterruptInUseVME (unsigned vectorNumber) -{ - static int init; - int i; - myISR *psub; - - if (!init) { - initHandlerAddrList(); - init = TRUE; - } - - psub = isrFetch (vectorNumber); - - /* - * its a C routine. Does it match a default handler? - */ - for (i=0; i LOCAL for debugging and many changes - * to the parser for resource.def so that we - * allow white space between tokens in env var - * - * Revision 1.7 1995/02/02 17:15:55 jbk - * Removed the stinking message "Cannot contact master timing IOC ". - * - * Revision 1.6 1995/02/01 15:29:54 winans - * Added a type field to the configure command to disable the use of the event - * system hardware if desired. - * - * Revision 1.5 1994/12/16 15:51:21 winans - * Changed error message in the event system error handler & added a conditional - * based on a debug flag to print it... defaults to off. (Per request from MRK.) - * - * Revision 1.4 1994/10/28 20:15:10 jbk - * increased the USP packet time-out to 250ms, added a parm to the configure() - * routine to let user specify it. - * - */ - -/************************************************************************** - * - * Author: Jim Kowalkowski - * - * Modification Log: - * ----------------- - * .01 01-06-94 jbk initial version - * .02 03-01-94 jbk magic # in packets, network byte order check - * .03 03-02-94 jbk current time always uses 1 tick watch dog update - * .04 17MAR98 mrk Make safe to year 2104 - * .05 17MAR98 mrk change nanosec conversion - * .06 04AUG98 mrk make TSsetClockFromUnix external - sync master - * - ***********************************************************************/ - -#define MAKE_DEBUG TSdriverDebug -#define TS_DRIVER 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "envDefs.h" -#include "envLib.h" -#include "dbDefs.h" -#include "epicsPrint.h" -#include "errMdef.h" -#include "drvSup.h" -#include "drvTS.h" -#include "bsdSocketResource.h" - -#define TSprintf epicsPrintf - -#define DEFAULT_TIME 0 -#define NO_EVENT_SYSTEM 1 - -/* functions used by this driver */ -static long TSgetUnixTime(struct timespec*); -static long TSgetMasterTime(struct timespec*); -static long TSgetBroadcastAddr(int soc, struct sockaddr*); -static int TSgetSocket(int port, struct sockaddr_in* sin); -static int TSgetBroadcastSocket(int port, struct sockaddr_in* sin); -static void TSsyncServer(); -static void TSsyncClient(); -static long TSasyncClient(); -static long TSsyncTheTime(struct timespec* cts, struct timespec* ts); -static long TSgetData(char* buf, int buf_size, int soc, - struct sockaddr* to_sin, struct sockaddr* from_sin, - struct timespec* round_trip); -static void TSaddStamp( struct timespec* result, - struct timespec* op1, struct timespec* op2); -static void TSwdIncTime(); -static void TSwdIncTimeSync(); -static void TSstampServer(); -static void TSeventHandler(int Card,int EventNum,unsigned long Ticks); -static void TSerrorHandler(int Card, int ErrorNum); -static long TSsetClockFromMaster(); -static void TSstartSoftClock(); -static long TScalcDiff(struct timespec* a, struct timespec* b, - struct timespec* diff); - -static long TSgetCurrentTime(struct timespec* ts); -static long TSforceSoftSync(int Card); -static long TSstartSyncServer(); -static long TSstartSyncClient(); -static long TSstartAsyncClient(); -static long TSstartStampServer(); -static long TSuserGetJunk(int event_number,struct timespec* sp); - -/* event system and time clock functions */ -static long (*TSregisterEventHandler)(int Card, void(*func)()); -static long (*TSregisterErrorHandler)(int Card, void(*func)()); -static long (*TSgetTicks)(int Card, unsigned long *Ticks); -static long (*TShaveReceiver)(int Card); -static long (*TSforceSync)(int Card); -static long (*TSgetTime)(struct timespec*); -static long (*TSsyncEvent)(); -static long (*TSdirectTime)(); -static long (*TSdriverInit)(); -static long (*TSuserGet)(int event_number,struct timespec* sp); - -/* global functions */ -#ifdef __cplusplus -extern "C" { -#endif - long TSinit(void); /* called by iocInit currently */ - long TSreport(); /* callable from vxWorks shell */ - - /* test functions */ - void TSprintRealTime(); - void TSprintUnixTime(); - void TSprintMasterTime(); - void TSprintTimeStamp(int event_number); - void TSprintCurrentTime(); -#ifdef __cplusplus -} -#endif - -/* data used by all */ -TSinfo TSdata = -{ TS_master_dead, TS_async_slave, TS_async_none, -0,NULL, -TS_SYNC_RATE_SEC,TS_CLOCK_RATE_HZ,0,TS_TIME_OUT_MS,0, -TS_MASTER_PORT,TS_SLAVE_PORT,1,0,0,0,0, -NULL, {NULL}, {NULL} -}; - -extern char* sysBootLine; - -int TSdirectTimeVar = 0; /* aother way to indicate direct time */ -int TSgoodTimeStamps = 0; /* a way to force use of accurate time stamps */ - -static WDOG_ID wd; -static long correction_factor = 0; -static long correction_count = 0; - - -/* static long TSreturnError() { return -1; } */ -static long TSdirectTimeError() { return -1; } -static long TShaveReceiverError(int i) { return -1; } -static long TSgetTicksError(int i,unsigned long* t) { return -1; } - -static long TSregisterErrorHandlerError(int i, void(*f)()) -{ if(TSdata.has_direct_time==1) return 0; else return -1; } -static long TSregisterEventHandlerError(int i, void(*f)()) -{ if(TSdata.has_direct_time==1) return 0; else return -1; } - - -long TSdriverInitError() -{ - struct timespec ts; - time_t t; - - clock_gettime(CLOCK_REALTIME,&ts); - time(&t); - Debug(1,"vxWorks time = %s\n",ctime(&t)); - - return 0; -} - -unsigned long TSepochNtpToUnix(struct timespec* ts) -{ - unsigned long nfssecs = (unsigned long)ts->tv_sec; - unsigned long secs = 0; - - /*If high order bit is not set then nfssecs has overflowed */ - if(!(nfssecs & 0x80000000ul)) { - /*secs = nfssecs - TS_1900_TO_VXWORKS_EPOCH + 2**32 */ - /* in order to prevent overflows rearrange as */ - /* secs = (2**32 -1) - TS_1900_TO_VXWORKS_EPOCH + nfssecs +1 */ - secs = 0xffffffffUL - TS_1900_TO_VXWORKS_EPOCH + nfssecs +1; - } else { - secs = nfssecs - TS_1900_TO_VXWORKS_EPOCH; - } - return(secs); -} - -unsigned long TSfractionToNano(unsigned long fraction) -{ - double value; - - /*value = 1e9 * fraction / 2**32 */ - value = (1e9 * (double)fraction)/4294967296.0; - return((unsigned long)value); -} - -unsigned long TSepochNtpToEpics(struct timespec* ts) -{ - unsigned long nfssecs = (unsigned long)ts->tv_sec; - unsigned long secs = 0; - - /*If high order bit is not set then nfssecs has overflowed */ - if(!(nfssecs & 0x80000000ul)) { - /*secs = nfssecs - TS_1900_TO_EPICS_EPOCH + 2**32 */ - /* in order to prevent overflows rearrange as */ - /* secs = (2**32 -1) - TS_1900_TO_EPICS_EPOCH + nfssecs +1 */ - secs = 0xffffffffUL - TS_1900_TO_EPICS_EPOCH + nfssecs +1; - } else { - secs = nfssecs - TS_1900_TO_EPICS_EPOCH; - } - return(secs); -} - -unsigned long TSepochUnixToEpics(struct timespec* ts) -{ - unsigned long unixsecs = (unsigned long)ts->tv_sec; - unsigned long secs; - - secs = unixsecs - TS_VXWORKS_TO_EPICS_EPOCH; - return(secs); -} - -unsigned long TSepochEpicsToUnix(struct timespec* ts) -{ - unsigned long epicssecs = (unsigned long)ts->tv_sec; - unsigned long secs; - - secs = epicssecs + TS_VXWORKS_TO_EPICS_EPOCH; - return(secs); -} - -/*-----------------------------------------------------------------------*/ -/* -TSreport() - report information about the state of the time stamp -support software -*/ -long TSreport() -{ - char buf[64]; - - switch(TSdata.type) - { - case TS_direct_master: TSprintf("Direct timing master\n"); break; - case TS_sync_master: TSprintf("Event timing master\n"); break; - case TS_async_master: TSprintf("Soft timing master\n"); break; - case TS_direct_slave: TSprintf("Direct timing slave\n"); break; - case TS_sync_slave: TSprintf("Event timing slave\n"); break; - case TS_async_slave: TSprintf("Soft timing slave\n"); break; - default: break; - } - switch(TSdata.state) - { - case TS_master_alive: TSprintf("Master timing IOC alive\n"); break; - case TS_master_dead: TSprintf("Master timing IOC dead\n"); break; - default: break; - } - switch(TSdata.async_type) - { - case TS_async_none: TSprintf("No clock synchronization\n"); break; - case TS_async_private: TSprintf("Sync protocol with master\n"); break; - case TS_async_ntp: TSprintf("NTP sync with unix server\n"); break; - case TS_async_time: TSprintf("Time protocol sync with unix\n"); break; - default: break; - } - TSprintf("Clock Rate in Hertz = %lu\n",TSdata.clock_hz); - TSprintf("Sync Rate in Seconds = %lu\n",TSdata.sync_rate); - TSprintf("Master communications port = %d\n",TSdata.master_port); - TSprintf("Slave communications port = %d\n",TSdata.slave_port); - TSprintf("Total events supported = %d\n",TSdata.total_events); - TSprintf("Request Time Out = %lu milliseconds\n",TSdata.time_out); - - ipAddrToA ((struct sockaddr_in*)&TSdata.hunt, buf, sizeof(buf)); - TSprintf("Broadcast address: %s\n", buf); - ipAddrToA ((struct sockaddr_in*)&TSdata.master, buf, sizeof(buf)); - TSprintf("Master address: %s\n", buf); - - if(TSdata.UserRequestedType) - TSprintf("\nForced to not use the event system\n"); - - if(TSdata.has_direct_time) - TSprintf("Event system has time directly available\n"); - return 0; -} - -/*-----------------------------------------------------------------------*/ -/* -TSconfigure() - This is the configuration routine which is meant to -be called from the vxWorks startup.cmd script before iocInit. -It's job is to set operating parameters for the time stamp support code. - - JRW -- if type = 0, then try to config using event system - if type = 1, then permanantly inhibit use of the event system -*/ -void TSconfigure(int master, int sync_rate_sec, int clock_rate_hz, - int master_port, int slave_port, unsigned long time_out, int type) -{ - if(master) TSdata.master_timing_IOC=1; - else TSdata.master_timing_IOC=0; - - if(sync_rate_sec) TSdata.sync_rate=sync_rate_sec; - else TSdata.sync_rate=TS_SYNC_RATE_SEC; - - if(clock_rate_hz) TSdata.clock_hz=clock_rate_hz; - else TSdata.clock_hz=TS_CLOCK_RATE_HZ; - - TSdata.clock_conv= TS_BILLION / TSdata.clock_hz; - - if(master_port) TSdata.master_port=master_port; - else TSdata.master_port=TS_MASTER_PORT; - - if(slave_port) TSdata.slave_port=slave_port; - else TSdata.slave_port=TS_SLAVE_PORT; - - if(time_out) TSdata.time_out=time_out; - else TSdata.time_out=TS_TIME_OUT_MS; - - switch(type) - { - case DEFAULT_TIME: - case NO_EVENT_SYSTEM: - TSdata.UserRequestedType = type; - break; - default: - TSprintf("Invalid type parameter <%d> must be:\n",type); - TSprintf(" 0 = default time system\n"); - TSprintf(" 1 = force no event system\n"); - TSdata.UserRequestedType = 0; - break; - } - - return; -} - -/* -this sucks, but who cares, user should not be using event number if not -prepared to handle them by defining an ErUserGetTimeStamp() routine. -*/ -static long TSuserGetJunk(int event_number,struct timespec* sp) -{ - return TSgetTimeStamp(0,sp); -} - -/*-----------------------------------------------------------------------*/ -/* -TSgetTimeStamp() - This routine returns the time stamp which represents -the time when an event event_number occurred. Soft timing will always -return the current time. Event zero will always return the current time -also. -*/ -long TSgetTimeStamp(int event_number,struct timespec* sp) -{ -/* this is questionable, a sync slave with a dead master will have -an invalid time stamp, so use the vxworks clock. Also remember that -the IOC vxWorks clock may not be in sync with time stamps if - default TSgetTime() in use and master failure is detected */ - - switch(TSdata.type) - { - case TS_async_master: - case TS_async_slave: - if(event_number<=0) - *sp = TSdata.event_table[TSdata.sync_event]; - else - return TSuserGet(event_number,sp); - break; - case TS_direct_slave: - case TS_direct_master: - TSgetTime(sp); - break; - case TS_sync_slave: - case TS_sync_master: - switch(event_number) - { - case 0: - if(TSgoodTimeStamps==0) - { - /* one tick watch dog maintains */ - *sp = TSdata.event_table[0]; - break; - } - case -1: - { - struct timespec ts; - unsigned long ticks; - - TSgetTicks(0,&ticks); /* add in the board time */ - *sp = TSdata.event_table[TSdata.sync_event]; - - /* calculate a time stamp from the tick count */ - ts.tv_sec = ticks / TSdata.clock_hz; - ts.tv_nsec=(ticks-(ts.tv_sec*TSdata.clock_hz))* - TSdata.clock_conv; - - sp->tv_sec += ts.tv_sec; - sp->tv_nsec += ts.tv_nsec; - - /* adjust seconds if needed */ - if(sp->tv_nsec >= TS_BILLION) - { - sp->tv_sec++; - sp->tv_nsec -= TS_BILLION; - } - } - break; - default: - if(TSdata.state==TS_master_dead) - TSgetTime(sp); - else - *sp = TSdata.event_table[event_number]; - break; - } - break; - default: - if(event_number==0) - *sp = TSdata.event_table[TSdata.sync_event]; - else - *sp = TSdata.event_table[event_number]; - } - return 0; -} - -/*-----------------------------------------------------------------------*/ -/* -TSinit() - initialize the driver, determine mode. -*/ -long TSinit(void) -{ - SYM_TYPE stype; - char tz[100],min_west[20]; - - Debug0(5,"In TSinit()\n"); - - /* 0=default, 1=none, 2=direct */ - - if( TSdata.UserRequestedType==DEFAULT_TIME) - { - /* default configuration probe */ - /* ------------------------------------------------------------- */ - /* find the lower level event system functions */ - if(symFindByNameEPICS(sysSymTbl,"_ErHaveReceiver", - (char**)&TShaveReceiver,&stype)==ERROR) - TShaveReceiver = TShaveReceiverError; - if(symFindByNameEPICS(sysSymTbl,"_ErGetTicks", - (char**)&TSgetTicks,&stype)==ERROR) - TSgetTicks = TSgetTicksError; - - if(symFindByNameEPICS(sysSymTbl,"_ErRegisterEventHandler", - (char**)&TSregisterEventHandler,&stype)==ERROR) - TSregisterEventHandler = TSregisterEventHandlerError; - - if(symFindByNameEPICS(sysSymTbl,"_ErRegisterErrorHandler", - (char**)&TSregisterErrorHandler,&stype)==ERROR) - TSregisterErrorHandler = TSregisterErrorHandlerError; - - if(symFindByNameEPICS(sysSymTbl,"_ErForceSync", - (char**)&TSforceSync,&stype)==ERROR) - TSforceSync = TSforceSoftSync; - - if(symFindByNameEPICS(sysSymTbl,"_ErDirectTime", - (char**)&TSdirectTime,&stype)==ERROR) - TSdirectTime = TSdirectTimeError; - - if(symFindByNameEPICS(sysSymTbl,"_ErDriverInit", - (char**)&TSdriverInit,&stype)==ERROR) - TSdriverInit = TSdriverInitError; - - if(symFindByNameEPICS(sysSymTbl,"_ErGetTime", - (char**)&TSgetTime,&stype)==ERROR) - TSgetTime = TSgetCurrentTime; - - if(symFindByNameEPICS(sysSymTbl,"_ErUserGetTimeStamp", - (char**)&TSuserGet,&stype)==ERROR) - TSuserGet = TSuserGetJunk; - - if(symFindByNameEPICS(sysSymTbl,"_ErSyncEvent", - (char**)&TSsyncEvent,&stype)==ERROR) - TSdata.sync_event=ER_EVENT_RESET_TICK; - else - TSdata.sync_event=TSsyncEvent(); - - /* ------------------------------------------------------------- */ - } - else - { - /* inhibit probe and use of the event system */ - TSprintf("WARNING: drvTS event hardware probe inhibited by user\n"); - TShaveReceiver = TShaveReceiverError; - TSgetTicks = TSgetTicksError; - TSregisterEventHandler = TSregisterEventHandlerError; - TSregisterErrorHandler = TSregisterErrorHandlerError; - TSforceSync = TSforceSoftSync; - TSgetTime = TSgetCurrentTime; - TSdriverInit = TSdriverInitError; - TSdirectTime = TSdirectTimeError; - TSdata.sync_event=ER_EVENT_RESET_TICK; - } - - /* set all the known information about the system */ - TSdata.event_table=NULL; - TSdata.ts_sync_valid=0; /* the sync time stamp invalid */ - TSdata.state=TS_master_dead; - TSdata.sync_occurred = semBCreate(SEM_Q_PRIORITY,SEM_EMPTY); - TSdata.has_event_system = 0; - TSdata.has_direct_time = 0; - TSdata.async_type=TS_async_none; - - if( (TSdata.total_events=TShaveReceiver(0))<=0) - { - Debug0(5,"TSinit() - no event receiver\n"); - TSdata.total_events=1; - TSdata.sync_event=0; - TSdata.clock_hz=sysClkRateGet(); - TSdata.clock_conv=TS_BILLION / TSdata.clock_hz; - TSdata.has_event_system = 0; - } - else - TSdata.has_event_system = 1; - - if(TSdirectTime()>0 || TSdirectTimeVar>0) TSdata.has_direct_time=1; - - /* allocate the event table */ - TSdata.event_table=(struct timespec*)malloc( - TSdata.total_events*sizeof(struct timespec)); - - if(TSdata.master_timing_IOC) - { - /* master */ - Debug0(5,"TSinit() - I am master\n"); - if(TSdata.has_direct_time) - { - TSdata.type=TS_direct_master; - } - else - { - if(TSdata.has_event_system) - TSdata.type=TS_sync_master; - else - TSdata.type=TS_async_master; - } - } - else - { - /* slave */ - Debug0(5,"TSinit() - I am slave\n"); - if(TSdata.has_direct_time) - { - TSdata.type=TS_direct_slave; - } - else - { - if(TSdata.has_event_system) - TSdata.type=TS_sync_slave; - else - TSdata.type=TS_async_slave; - } - } - - /* set up the event system hooks */ - if(TSdata.has_event_system) - { - /* register the event handler function */ - if(TSregisterEventHandler(0,TSeventHandler)!=0) - { - TSprintf("Failed to register event handler\n"); - return -1; - } - - /* register the error handler function */ - if(TSregisterErrorHandler(0,TSerrorHandler)!=0) - { - TSprintf("Failed to register error handler\n"); - return -1; - } - } - - /* always start the soft clock */ - if(TSdata.has_direct_time==0) TSstartSoftClock(); - - /* get time from boot server Unix system */ - if(TSdata.master_timing_IOC) - { - /* master */ - if(TSsetClockFromUnix()<0) - { - /* bad, cannot get time - accessing starts ticking */ - struct timespec tp; - clock_gettime(CLOCK_REALTIME,&tp); - TSprintf("Failed to set clock from Unix server\n"); - } - Debug0(5,"TSinit() - tried to get clock from unix\n"); - - /* start the time stamp info server */ - if(TSstartStampServer()==ERROR) - { - TSprintf("Failed to start stamp server\n"); - return -1; - } - Debug0(5,"TSinit() - stamp server started \n"); - - TSdata.state = TS_master_alive; - - /* a direct master may be capable of delivering sync time stamps? */ - if(TSdata.type==TS_sync_master) - { - /* start the sync udp server */ - if(TSstartSyncServer()==ERROR) - { - TSprintf("Failed to start sync server\n"); - return -1; - } - Debug0(5,"TSinit() - sync server started \n"); - } - } - else - { - /* slave */ - if(TSsetClockFromUnix()<0) - { - struct timespec tp; - clock_gettime(CLOCK_REALTIME,&tp); - /* this should work */ - TSprintf("Failed to set time from Unix server\n"); - } - - if( TSsetClockFromMaster()<0 ) - { - /* do nothing here */ - /* TSprintf("Could not contact a master timing IOC\n"); */ - } - else - TSdata.state = TS_master_alive; - - if(TSdata.type==TS_async_slave) - { - /* this task syncs with master or unix */ - if(TSstartAsyncClient()==ERROR) - { - TSprintf("Failed to start async client\n"); - return -1; - } - Debug0(5,"TSinit() - async client started \n"); - } - else - { - /* this task sync with master */ - if(TSstartSyncClient()==ERROR) - { - TSprintf("Failed to start sync client\n"); - return -1; - } - Debug0(5,"TSinit() - sync client started \n"); - } - } - - /* - This section sets up the vxWorks clock for use with the ansiLib - functions. The TIMEZONE environment variable for vxWorks is only - overwritten if it has not been set. It seems as though the day - light saving time does not work (at least following the directions - in ansiLib). - - The EPICS environment variable EPICS_TS_MIN_WEST holds the minutes - west of GMT (UTC) time. This variable should be preset by the EPICS - administrator for your site. - */ - - if(getenv("TIMEZONE")==(char*)NULL) - { - if(envGetConfigParam(&EPICS_TS_MIN_WEST,sizeof(min_west),min_west)==NULL - || strlen(min_west)==0) - { - TSprintf("TS initialization: No Time Zone Information\n"); - } - else - { - sprintf(tz,"TIMEZONE=UTC::%s:040102:100102",min_west); - if(putenv(tz)==ERROR) - { - TSprintf("TS initialization: TIMEZONE putenv failed\n"); - } - } - } - - TSdriverInit(); /* Call the user's driver initialization if supplied */ - return 0; -} - -/* following are watch dog routines for soft time support */ - -static void TSstartSoftClock() /*start the soft clock watch dog*/ -{ - /* simple watch dog to fire off syncs to slaves */ - Debug(5,"start watch dog at rate %ld\n", - (long) sysClkRateGet()*TSdata.sync_rate); - wd = wdCreate(); - if(TSdata.has_event_system) - { - Debug0(8,"Starting sync time watch dog\n"); - wdStart(wd,1,(FUNCPTR)TSwdIncTimeSync,NULL); - } - else - { - Debug0(8,"Starting async time watch dog\n"); - wdStart(wd,1,(FUNCPTR)TSwdIncTime,NULL); - } - return; -} - -/* NOTE: TSwdIncTime called at interrupt level! */ -static void TSwdIncTime() /*increment the time stamp at a 60 Hz rate*/ -{ - int key; - - wdStart(wd,1, (FUNCPTR)TSwdIncTime,NULL); - /* update the event table */ - key=intLock(); - - if(correction_count) - { - long nsec = TSdata.event_table[TSdata.sync_event].tv_nsec - + TSdata.clock_conv; - nsec += correction_factor; - if(nsec<0) { - nsec += TS_BILLION; - TSdata.event_table[TSdata.sync_event].tv_sec--; - } - TSdata.event_table[TSdata.sync_event].tv_nsec = nsec; - if(--correction_count == 0) correction_factor = 0; - } - else - TSdata.event_table[TSdata.sync_event].tv_nsec += - TSdata.clock_conv; - - /* adjust seconds if needed */ - if(TSdata.event_table[TSdata.sync_event].tv_nsec >= TS_BILLION) - { - TSdata.event_table[TSdata.sync_event].tv_sec++; - TSdata.event_table[TSdata.sync_event].tv_nsec -= TS_BILLION; - } - intUnlock(key); - return; -} - -static void TSwdIncTimeSync() -{ - wdStart(wd,1, (FUNCPTR)TSwdIncTimeSync,NULL); - TSaccurateTimeStamp(&TSdata.event_table[0]); -} - -/* following are all interrupt service routines */ - -/* -TSeventHandler() - receive events from event system; update the event table - - Note: called at interrupt level! -*/ -static void TSeventHandler(int Card,int EventNum,unsigned long Ticks) -{ - struct timespec ts; - struct timespec* st; - int key; - -#ifdef DIRECT_WITH_EVENTS - if(TSdata.has_direct_time==1) - { - TSgetTime(&ts); - key=intLock(); - TSdata.event_table[EventNum].tv_sec = ts.tv_sec; - TSdata.event_table[EventNum].tv_nsec = ts.tv_nsec; - intUnlock(key); - return; - } -#endif - - /* calculate a time stamp from the Tick count */ - ts.tv_sec = Ticks / TSdata.clock_hz; - ts.tv_nsec = (Ticks - (ts.tv_sec * TSdata.clock_hz)) * TSdata.clock_conv; - /* obtain a copy of the last sync time */ - st = &TSdata.event_table[TSdata.sync_event]; - /* update the event table */ - key=intLock(); - TSdata.event_table[EventNum].tv_sec = st->tv_sec + ts.tv_sec; - TSdata.event_table[EventNum].tv_nsec = st->tv_nsec + ts.tv_nsec; - /* adjust seconds if needed */ - if(TSdata.event_table[EventNum].tv_nsec >= TS_BILLION) - { - TSdata.event_table[EventNum].tv_sec++; - TSdata.event_table[EventNum].tv_nsec -= TS_BILLION; - } - intUnlock(key); - /* signal a time stamp sync if this is sync event */ - if(TSdata.type==TS_sync_master && EventNum==TSdata.sync_event) - { - /* validate the soft time for back off in case of event system - failure, this will not be done in first implementation */ - - /* tell broadcast server to send out sync */ - semGive(TSdata.sync_occurred); - } - return; -} - -/* TSerrorHandler() - receive errors from event system -Note: called at interrupt level! -*/ -static void TSerrorHandler(int Card, int ErrorNum) -{ - /* - probably should do the following: - mark a "bad" state - timestamp is invalid, - send a request for sync to master, - if sync doesn't come when in bad state, then install - clock hook to increment time stamp until event system back up - keep a count of errors - Could put the slave on the vxworks timer until next sync - */ - - if(MAKE_DEBUG) - { - switch(ErrorNum) - { - case 1: - logMsg("***TSerrorHandler: event system error: TAXI violation", - 0,0,0,0,0,0); - break; - case 2: - logMsg("***TSerrorHandler: event system error: lost heartbeat", - 0,0,0,0,0,0); - break; - case 3: - logMsg("***TSerrorHandler: event system error: lost events", - 0,0,0,0,0,0); - break; - default: - logMsg("***TSerrorHandler: unknown error %d from event system", - ErrorNum,0,0,0,0,0); - } - } - return; -} - -/**************************************************************************/ -/* the following are utilities for initially getting and setting the time */ -/**************************************************************************/ -/* -TSgetUnixTime() - ask the boot server for the time using the -time protocol. This is only the time to the nearest second -A better way would be to use the NTP transactions to boot server -*/ - -static long TSgetUnixTime(struct timespec* ts) -{ - BOOT_PARAMS bootParms; - unsigned long buf_data,timeValue; - TS_NTP buf_ntp; - struct sockaddr_in sin; - int soc; - char host_addr[BOOT_ADDR_LEN]; - int status; - - Debug0(2,"in TSgetUnixTime()\n"); - if(envGetConfigParam(&EPICS_TS_NTP_INET,BOOT_ADDR_LEN,host_addr)==NULL || - strlen(host_addr)==0) - { - /* use boot host if the environment variable not set */ - bootStringToStruct(sysBootLine,&bootParms); - /* bootParms.had = host IP address */ - strncpy(host_addr,bootParms.had,BOOT_ADDR_LEN); - } - if( (soc=TSgetSocket(0,&sin)) <0) - { Debug0(1,"TSgetsocket failed\n"); return -1; } - - /* set up for ntp transaction to boot server */ - Debug(5,"host addr = %s\n",host_addr); - - /* well known registered NTP port - or whatever port they specify */ - status = aToIPAddr (host_addr, UDP_NTP_PORT, &sin); - if (status) { - Debug0(2,"bad host name or IP address\n"); - TSdata.async_type=TS_async_none; - close(soc); - return -1; - } - - TSdata.async_type=TS_async_ntp; - memset(&buf_ntp,0,sizeof(buf_ntp)); - buf_ntp.info[0]=0x0b; - if(TSgetData((char*)&buf_ntp,sizeof(buf_ntp),soc, - (struct sockaddr*)&sin,NULL,NULL)<0) - { - Debug0(2,"no reply from NTP server\n"); - /* well known registered time port */ - sin.sin_port = htons(UDP_TIME_PORT); - TSdata.async_type=TS_async_time; - buf_data=0; - if(TSgetData((char*)&buf_data,sizeof(buf_data),soc, - (struct sockaddr*)&sin,NULL,NULL)<0) - { - Debug0(2,"no reply from Time server\n"); - TSdata.async_type=TS_async_none; - close(soc); - return -1; - } - } - /* remember: time and NTP protocol return seconds since 1900, not 1970 */ - /* to convert sec = timeValue - TS_1900_TO_EPICS_EPOCH */ - if(TSdata.async_type==TS_async_time) - { - /* this is time protocol */ - timeValue=ntohl(buf_data); - ts->tv_sec = timeValue; - ts->tv_nsec = 0; - Debug(2,"got the Time protocol time %lu= \n",timeValue); - } - else - { - /* this is ntp - need to convert to ns */ - ts->tv_sec=ntohl(buf_ntp.transmit_ts.tv_sec); - timeValue=ntohl(buf_ntp.transmit_ts.tv_nsec); - ts->tv_nsec = TSfractionToNano(timeValue); - if(MAKE_DEBUG>=2) - TSprintf("got the NTP time %9.9lu.%9.9lu\n",ts->tv_sec,timeValue); - } - close(soc); - return 0; -} - -/* -TSgetMasterTime() - query the master timing IOC for it's current time -This routine will be converted to a task and block on a semaphore, -when it gets the semaphore, it will go to the master timing IOC -and get a time stamp, the time stamp will be used to adjust the -vxworks clock. To use it for software timing, just put a watchdog -out there that pokes the semaphore. Another way to manage soft -timing is to catch broadcasts from the master, round trip -calculations cannot be made when doing this. -*/ -static long TSgetMasterTime(struct timespec* tsp) -{ - TSstampTrans stran; - struct timespec curr_time,tran_time,send_time,recv_time; - struct sockaddr_in sin; - struct sockaddr fs; - int soc; - - Debug0(3,"TSgetMasterTime() called\n"); - - if( (soc=TSgetBroadcastSocket(0,&sin)) <0) - { Debug0(1,"TSgetBroadcastSocket failed\n"); return -1; } - sin.sin_port = htons(TSdata.master_port); - memcpy(&TSdata.hunt,&sin,sizeof(sin)); - stran.type=(TStype)htonl(TS_time_request); - stran.magic=htonl(TS_MAGIC); - - if(TSgetData((char*)&stran,sizeof(stran),soc, - (struct sockaddr*)&sin,&fs,&tran_time)<0) - { Debug0(2,"no reply from master server\n"); close(soc); return -1; } - - /* check the magic number */ - if(ntohl(stran.magic)!=(TS_MAGIC)) - { - - TSprintf("TSgetMasterTime: invalid packet received\n"); - close(soc); - return -1; - } - /* we now have several pieces of information: - the master's address, - the approximate round trip time, - and the master's processing time. */ - /* set the global data structure for information from master */ - Debug(8,"master port=%d\n",ntohs(((struct sockaddr_in*)&fs)->sin_port)); - TSdata.master = fs; - TSdata.state = TS_master_alive; - if(TSdata.type==TS_sync_slave) - { - TSdata.clock_hz = ntohl(stran.clock_hz); - TSdata.sync_rate = ntohl(stran.sync_rate); - TSdata.clock_conv = TS_BILLION / TSdata.clock_hz; - } - /* how long did it take to give transaction? */ - TScalcDiff(&send_time,&recv_time,&tran_time); - if(MAKE_DEBUG>=6) - { - TSprintf("round trip time: %9.9lu.%9.9lu\n", - tran_time.tv_sec,tran_time.tv_nsec); - TSprintf("master time: %9.9lu.%9.9lu\n", - stran.master_time.tv_sec,stran.master_time.tv_nsec); - } - tran_time.tv_nsec >>= 2; - tran_time.tv_sec >>= 2; - /* add half the round trip estimate to the time stamp from master */ - curr_time.tv_sec = ntohl(stran.current_time.tv_sec); - curr_time.tv_nsec = ntohl(stran.current_time.tv_nsec); - TSaddStamp(tsp,&curr_time,&tran_time); - close(soc); - return 0; -} - -/* -TSsetClockFromUnix() - query the time from boot server and set the -vxworks clock. -*/ -long TSsetClockFromUnix(void) -{ - struct timespec tp; - unsigned long ulongtemp; - - Debug0(3,"in TSsetClockFromUnix()\n"); - - if(TSgetUnixTime(&tp)!=0) return -1; - - ulongtemp = TSepochNtpToUnix(&tp); - tp.tv_sec = (long)ulongtemp; - - if(MAKE_DEBUG>=9) - TSprintf("set time: %9.9lu.%9.9lu\n", tp.tv_sec,tp.tv_nsec); - - /* set the vxWorks clock to the correct time */ - if(clock_settime(CLOCK_REALTIME,&tp)<0) - { Debug0(1,"clock_settime failed\n"); } - - /* adjust time to use the EPICS EPOCH of 1990 */ - /* this is wrong if leap seconds accounted for */ - ulongtemp = TSepochUnixToEpics(&tp); - tp.tv_sec = ulongtemp; - - /* set the EPICS event time table sync entry (current time) */ - TSdata.event_table[TSdata.sync_event]=tp; - - if(MAKE_DEBUG>=9) - TSprintf("epics time: %9.9lu.%9.9lu\n", - TSdata.event_table[TSdata.sync_event].tv_sec, - TSdata.event_table[TSdata.sync_event].tv_nsec); - - return 0; -} - -/* -TSsetClockFromMaster() - set the vxworks clock using the time from -the master timing IOC -*/ -static long TSsetClockFromMaster() -{ - struct timespec tp; - int key; - unsigned long secs; - - Debug0(3,"in TSsetClockFromMaster()\n"); - - if(TSgetMasterTime(&tp)<0) return -1; - - key=intLock(); - TSdata.event_table[TSdata.sync_event]=tp; - intUnlock(key); - - /* adjust time to use the Unix EPOCH of 1900 - not to good */ - /* making this adjustment is not so good */ - secs = TSepochEpicsToUnix(&tp); - tp.tv_sec = secs; - clock_settime(CLOCK_REALTIME,&tp); - - return 0; -} - -/**************************************************************************/ -/* broadcast socket creation utilites */ -/**************************************************************************/ - -/* -TSgetBroadcastSocket() - return a broadcast socket for a port, return -a sockaddr also. -*/ -static int TSgetBroadcastSocket(int port, struct sockaddr_in* sin) -{ - int on=1; - int soc; - - sin->sin_port=htons(port); - sin->sin_family=AF_INET; - sin->sin_addr.s_addr=htonl(INADDR_ANY); - if( (soc=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0 ) - { perror("socket create failed"); return -1; } - - setsockopt(soc,SOL_SOCKET,SO_BROADCAST,(char*)&on,sizeof(on)); - - if( bind(soc,(struct sockaddr*)sin,sizeof(struct sockaddr_in)) < 0 ) - { perror("socket bind failed"); close(soc); return -1; } - - if( TSgetBroadcastAddr(soc,(struct sockaddr*)sin) < 0 ) return -1; - return soc; -} - -/* -TSgetBroadcastAddr() - Determine the broadcast address, this is -directly from the Sun Network Programmer's guide. -*/ -static long TSgetBroadcastAddr(int soc, struct sockaddr* sin) -{ - struct ifconf ifc; - struct ifreq* ifr; - struct ifreq* save; - char buf[BUFSIZ]; - int tot,i; - - ifc.ifc_len = sizeof(buf); - ifc.ifc_buf = buf; - if(ioctl(soc,SIOCGIFCONF,(int)&ifc) < 0) - { perror("ioctl SIOCGIFCONF failed"); return -1; } - - ifr = ifc.ifc_req; - tot = ifc.ifc_len/sizeof(struct ifreq); - save=(struct ifreq*)NULL; - i=0; - do - { - if(ifr[i].ifr_addr.sa_family==AF_INET) - { - if(ioctl(soc,SIOCGIFFLAGS,(int)&ifr[i])<0) - { perror("ioctl SIOCGIFFLAGS failed"); return -1; } - - if( (ifr[i].ifr_flags&IFF_UP) && - !(ifr[i].ifr_flags&IFF_LOOPBACK) && - (ifr[i].ifr_flags&IFF_BROADCAST)) - { save=&ifr[i]; } - } - } while( !save && ++iifr_broadaddr, - sizeof(save->ifr_broadaddr)); - } - else - { Debug0(1,"no broadcast address found\n"); return -1; } - return 0; -} - -/**************************************************************************/ -/* time stamp utility routines */ -/**************************************************************************/ - -/* -TSsyncTheTime - given the current time (cts), and a compare time -stamp (ts), correct the current time clock to match ts. -*/ -static long TSsyncTheTime(struct timespec* cts, struct timespec* ts) -{ - int key; - long diffSec; - long diffNsec; - long diffSecAbs; - - diffSec = (long)ts->tv_sec -(long) cts->tv_sec; - diffNsec = (long)ts->tv_nsec - (long)cts->tv_nsec; - diffSecAbs = (diffSec<0) ? -diffSec : diffSec; - /* see if clock can be corrected in sync window - up to 1 secs per tick */ - if(diffSecAbs <= TSdata.sync_rate) - { - long diff; - long count; - count=sysClkRateGet()*TSdata.sync_rate; - diff = (TS_BILLION/count)*diffSec + diffNsec/count; - if(diff) { - key=intLock(); - correction_count = count; - correction_factor = diff; - intUnlock(key); - } - Debug(5,"Correction Factor=.%9.9ld\n",correction_factor); - } - else - { - /* clock can not be corrected - jam it for now */ - TSdata.event_table[TSdata.sync_event]=*ts; - if(MAKE_DEBUG>=7) - { - TSprintf("Slave not in sync: mine=%9.9lu.%9.9lu!=%lu.%lu=other\n", - cts->tv_sec, cts->tv_nsec, ts->tv_sec, ts->tv_nsec); - TSprintf("slave diff time: %9.9ld.%9.9ld\n", - diffSec,diffNsec); - } - } - return 0; -} - -/**************************************************************************/ -/* varies server that can be running */ -/**************************************************************************/ - -long TSstartSyncServer() -{ - /* run at priority just above CA */ - return taskSpawn("ts_syncS",TS_SYNC_SERVER_PRI,VX_FP_TASK|VX_STDIO,5000, - (FUNCPTR)TSsyncServer,0,0,0,0,0,0,0,0,0,0); -} - -/* -TSsyncServer() - Server task that broadcasts the sync time stamp every -time a sync event is receive by the event system. -*/ -static void TSsyncServer() -{ - TSstampTrans stran; - struct sockaddr_in sin; - int soc; - - if( (soc=TSgetBroadcastSocket(0,&sin)) <0) - { Debug0(1,"TSgetBroadcastSocket failed\n"); return; } - sin.sin_port = htons(TSdata.slave_port); - stran.type=(TStype)htonl(TS_sync_msg); - stran.magic=htonl(TS_MAGIC); - stran.sync_rate=htonl(TSdata.sync_rate); - stran.clock_hz=htonl(TSdata.clock_hz); - while(1) - { - /* wait for a sync to occur */ - semTake(TSdata.sync_occurred,WAIT_FOREVER); - - if(!TSdata.ts_sync_valid) - { - int key; - struct timespec ts; - /* remember, the ts table has only an approximation to the - correct time before the event is actually up and running, - so validate the ts if this is the first sync - the vxWorks - clock has a good time in it - */ - if(TSgetTime(&ts)==0) TSdata.ts_sync_valid=1; - key=intLock(); - /* don't adjust time from getTime() to EPICS epoch */ - TSdata.event_table[TSdata.sync_event].tv_nsec=ts.tv_nsec; - TSdata.event_table[TSdata.sync_event].tv_sec=ts.tv_sec; - intUnlock(key); - } - stran.master_time.tv_sec= - htonl(TSdata.event_table[TSdata.sync_event].tv_sec); - stran.master_time.tv_nsec= - htonl(TSdata.event_table[TSdata.sync_event].tv_nsec); - if(sendto(soc,(char*)&stran,sizeof(stran),0, - (struct sockaddr*)&sin,sizeof(sin))<0) - { perror("sendto failed"); } - Debug(8,"time send secs = %lu\n",stran.master_time.tv_sec); - Debug(8,"time send nsecs = %lu\n",stran.master_time.tv_nsec); - } - close(soc); - return; -} - -/*-----------------------------------------------------------------------*/ -long TSstartAsyncClient() -{ - /* run at priority just above CA */ - return taskSpawn("ts_Casync",TS_ASYNC_CLIENT_PRI,VX_FP_TASK|VX_STDIO,5000, - (FUNCPTR)TSasyncClient,0,0,0,0,0,0,0,0,0,0); -} - -/* -TSasyncClient() - keep the async slave in sync with ntp server -while checking for master timing IOC to come up - - algorithm: - - sync with master if available - - sync with unix if no master, checking every so often for master - - sync with unix if master goes away until master comes back - - continually check for master if no unix sync available -*/ -static long TSasyncClient() -{ - BOOT_PARAMS bootParms; - TSstampTrans stran; - TS_NTP buf_ntp; - struct sockaddr_in sin_unix,sin_bc,sin_master; - int count,soc_unix,soc_master,soc_bc,buf_size; - struct timespec ts,diff_time,cts,curr_time; - unsigned long nsecs; - char host_addr[BOOT_ADDR_LEN]; - int status; - - Debug0(2,"in TSasyncClient()\n"); - - /* could open two sockets here, one to contact unix, one to find master */ - - /*------socket for unix server----------*/ - if(envGetConfigParam(&EPICS_TS_NTP_INET,BOOT_ADDR_LEN,host_addr)==NULL - || strlen(host_addr)==0) - { - /* use boot host if the environment variable not set */ - bootStringToStruct(sysBootLine,&bootParms); - /* bootParms.had = host IP address */ - strncpy(host_addr,bootParms.had,BOOT_ADDR_LEN); - } - - if( (soc_unix=TSgetSocket(0,&sin_unix)) <0) - { Debug0(1,"TSgetSocket failed\n"); return -1; } - - status = aToIPAddr (host_addr, UDP_NTP_PORT, &sin_unix); - if (status) { - Debug0(2,"bad host name or IP address\n"); - close (soc_unix); - return -1; - } - - /*------socket for finding master----------*/ - if( (soc_bc=TSgetBroadcastSocket(0,&sin_bc)) <0) - { Debug0(1,"TSgetBroadcastSocket failed\n"); close(soc_unix); return -1; } - - sin_bc.sin_port = htons(TSdata.master_port); - /*-----------------------------------------*/ - - while(1) - { - /* stop the clock from correcting here - probably better to use - a watch dog to stop the clock correction */ - - if(TSdata.state==TS_master_alive) - { - /* get socket to master */ - Debug0(5,"async_client(): master_alive\n"); - if( (soc_master=TSgetSocket(0,&sin_master)) <0) - { Debug0(1,"TSgetSocket failed\n"); } - - while(TSdata.state==TS_master_alive) - { - /* sync with the master as long as it is up */ - Debug0(5,"async_client(): syncing with master\n"); - stran.type=(TStype)htonl(TS_time_request); - stran.magic=htonl(TS_MAGIC); - - if(TSgetData((char*)&stran,sizeof(stran),soc_master, - &TSdata.master,NULL,&diff_time)<0) - { - Debug0(2,"no reply from master server\n"); - TSdata.state=TS_master_dead; - close(soc_master); - } - else - { - if(ntohl(stran.magic)==TS_MAGIC) - { - /* sync the time with master's here - 2 ticks */ - cts=TSdata.event_table[TSdata.sync_event]; - curr_time.tv_sec=ntohl(stran.current_time.tv_sec); - curr_time.tv_nsec=ntohl(stran.current_time.tv_nsec); - TSsyncTheTime(&cts,&curr_time); - Debug(8,"master sec = %lu\n",curr_time.tv_sec); - Debug(8,"my sec = %lu\n", cts.tv_sec); - } - else - { - TSprintf("TSasyncClient: invalid packet recved\n"); - } - taskDelay(sysClkRateGet()*TSdata.sync_rate); - } - } - } - else if(TSdata.async_type==TS_async_ntp) - { - /* sync with unix server using NTP - master check now and then */ - Debug0(5,"async_client(): using NTP sync\n"); - count=0; - while(TSdata.state==TS_master_dead) - { - Debug0(5,"async_client(): syncing with unix\n"); - memset(&buf_ntp,0,sizeof(buf_ntp)); - buf_ntp.info[0]=0x0b; - buf_size=sizeof(buf_ntp); - - if(TSgetData((char*)&buf_ntp,sizeof(buf_ntp),soc_unix, - (struct sockaddr*)&sin_unix,NULL,&diff_time)<0) - { - Debug0(2,"no reply from NTP server\n"); - } - else - { - unsigned long ulongtemp; - /* get the current time */ - cts=TSdata.event_table[TSdata.sync_event]; - /* adjust the ntp time */ - ts.tv_sec = ntohl(buf_ntp.transmit_ts.tv_sec); - ulongtemp = TSepochNtpToEpics(&ts); - ts.tv_sec = (long)ulongtemp; - nsecs=ntohl(buf_ntp.transmit_ts.tv_nsec); - ts.tv_nsec = TSfractionToNano(nsecs); - TSsyncTheTime(&cts,&ts); - } - if(count==0) - { - stran.type=(TStype)htonl(TS_time_request); - stran.magic=htonl(TS_MAGIC); - - if(TSgetData((char*)&stran,sizeof(stran),soc_bc, - (struct sockaddr*)&sin_bc,&TSdata.master,&diff_time)<0) - { Debug0(2,"no reply from master server\n"); } - else - { - TSdata.state=TS_master_alive; - Debug(8,"master port = %d\n", - ntohs( ((struct sockaddr_in*) - &TSdata.master)->sin_port)); - } - - count=(TSdata.sync_rate>TS_SECS_ASYNC_TRY_MASTER)? -TS_SECS_ASYNC_TRY_MASTER: - TS_SECS_ASYNC_TRY_MASTER/TSdata.sync_rate; - } - else count--; - taskDelay(sysClkRateGet()*TSdata.sync_rate); - } - } - else - { - /* try to find a master */ - while(TSdata.state==TS_master_dead) - { - stran.type=(TStype)htonl(TS_time_request); - stran.magic=htonl(TS_MAGIC); - - if(TSgetData((char*)&stran,sizeof(stran),soc_bc, - (struct sockaddr*)&sin_bc,&TSdata.master,&diff_time)<0) - { Debug0(2,"no reply from master server\n"); } - else - TSdata.state=TS_master_alive; - taskDelay(sysClkRateGet()*TS_SECS_SYNC_TRY_MASTER); - } - } - } -} - -static long TSstartSyncClient() -{ - return taskSpawn("ts_syncC",TS_SYNC_CLIENT_PRI,VX_FP_TASK|VX_STDIO,5000, - (FUNCPTR)TSsyncClient,0,0,0,0,0,0,0,0,0,0); -} - -/* -TSsyncClient() - Client task that listens for sync time stamp on a port -and verifies with this IOC sync time stamp. This is only to be used -with event system timing. -*/ -static void TSsyncClient() -{ - TSstampTrans stran; - struct sockaddr_in sin; - struct sockaddr fs; - int num,mlen,soc,fl; - struct timespec mast_time; - fd_set readfds; - int key; - - /* if no master then use unix and ntp to sync time - all aync slaves will operate in polled mode */ - - if(TSdata.type!=TS_sync_slave) return; - - /* check for master to be there every so many minutes */ - if(TSdata.state != TS_master_alive) - while( TSsetClockFromMaster()<0 ) - taskDelay(sysClkRateGet()*TS_SECS_SYNC_TRY_MASTER); - if( (soc=TSgetSocket(TSdata.slave_port,&sin)) <0) - { Debug0(1,"TSgetSocket failed\n"); return; } - while(1) - { - FD_ZERO(&readfds); - FD_SET(soc,&readfds); - - /* could set up timeout for (sync_rate + epsilon) - to see if one is missed */ - - num=select(FD_SETSIZE,&readfds,(fd_set*)NULL,(fd_set*)NULL,NULL); - if(num==ERROR) { perror("select failed"); continue; } - - if((mlen=recvfrom(soc,(char*)&stran,sizeof(stran),0,&fs,&fl))<0) - { perror("recvfrom failed"); continue; } - - if(ntohl(stran.magic)!=TS_MAGIC) - { - TSprintf("TSsyncClient: invalid packet received\n"); - continue; - } - - /* get the master time out of packet */ - mast_time.tv_sec=ntohl(stran.master_time.tv_sec); - mast_time.tv_nsec=ntohl(stran.master_time.tv_nsec); - - Debug0(6,"Received sync request from master\n"); - if(MAKE_DEBUG>=8) - { - TSprintf("time received=%9.9lu.%9.9lu\n", - mast_time.tv_sec,mast_time.tv_nsec); - } - - /* verify the sync event with this one */ - if( TSdata.event_table[TSdata.sync_event].tv_sec!=mast_time.tv_sec - || TSdata.event_table[TSdata.sync_event].tv_nsec!=mast_time.tv_nsec) - { - TSprintf("sync Slave not in sync: %lu,%lu != %lu,%lu\n", - TSdata.event_table[TSdata.sync_event].tv_sec, - TSdata.event_table[TSdata.sync_event].tv_nsec, - mast_time.tv_sec, mast_time.tv_nsec); - key=intLock(); - TSdata.event_table[TSdata.sync_event].tv_sec=mast_time.tv_sec; - TSdata.event_table[TSdata.sync_event].tv_nsec=mast_time.tv_nsec; - intUnlock(key); - } - } - close(soc); - return; -} - -static long TSstartStampServer() -{ - return taskSpawn("ts_stamp",TS_STAMP_SERVER_PRI,VX_FP_TASK|VX_STDIO,5000, - (FUNCPTR)TSstampServer,0,0,0,0,0,0,0,0,0,0); -} - -/* -TSstampServer() - Server task on master timing IOC that listens for -time stamp requests and sync request from slaves. -*/ -static void TSstampServer() -{ - TSstampTrans stran; - struct sockaddr_in sin; - struct sockaddr fs; - struct timespec ts; - int mlen,soc,fl; - TStype type; - - if( (soc=TSgetSocket(TSdata.master_port,&sin)) <0) - { Debug0(1,"TSgetSocket failed\n"); return; } - - stran.type=(TStype)htonl(TS_time_request); - stran.magic=htonl(TS_MAGIC); - - while(1) - { - fl=sizeof(fs); - if((mlen=recvfrom(soc,(char*)&stran,sizeof(stran),0,&fs,&fl))<0) - { perror("recvfrom failed"); continue; } - - if(ntohl(stran.magic)!=TS_MAGIC) - { - TSprintf("TSstampServer(): invalid packet received\n"); - continue; - } - - type=(TStype)ntohl(stran.type); - switch(type) - { - case TS_time_request: - TSgetTimeStamp(TSdata.sync_event,&ts); - stran.master_time.tv_sec=htonl(ts.tv_sec); - stran.master_time.tv_nsec=htonl(ts.tv_nsec); - - if(TSdata.has_event_system) - TSaccurateTimeStamp(&ts); - else - TScurrentTimeStamp(&ts); - stran.current_time.tv_sec=htonl(ts.tv_sec); - stran.current_time.tv_nsec=htonl(ts.tv_nsec); - stran.sync_rate = htonl(TSdata.sync_rate); - stran.clock_hz = htonl(TSdata.clock_hz); - Debug0(4,"Slave requesting time\n"); - if(sendto(soc,(char*)&stran,sizeof(stran),0,&fs,fl)<0) - { perror("sendto to slave failed"); } - break; - case TS_sync_request: TSforceSync(0); break; - default: - Debug0(1,"Unknown transaction type from slave\n"); - } - } - close(soc); - return; -} - -/*************************************************************************/ -/* utility routines for managing time retrieval */ -/*************************************************************************/ - -/* get the current time from time stamp support software */ -long TScurrentTimeStamp(struct timespec* sp) -{ - TSgetTimeStamp(0,sp); - return 0; -} - -/* get the current time from time stamp support software */ -long TSaccurateTimeStamp(struct timespec* sp) -{ - struct timespec ts; - unsigned long ticks; - - if(TSdata.has_direct_time==1) - { - TSgetTime(sp); - return 0; - } - - TSgetTicks(0,&ticks); /* add in the board time */ - *sp = TSdata.event_table[TSdata.sync_event]; - - /* calculate a time stamp from the tick count */ - ts.tv_sec = ticks / TSdata.clock_hz; - ts.tv_nsec=(ticks-(ts.tv_sec*TSdata.clock_hz))*TSdata.clock_conv; - - sp->tv_sec += ts.tv_sec; - sp->tv_nsec += ts.tv_nsec; - - /* adjust seconds if needed */ - if(sp->tv_nsec >= TS_BILLION) - { - sp->tv_sec++; - sp->tv_nsec -= TS_BILLION; - } - return 0; -} - -/* get the current time from vxWorks time clock */ -static long TSgetCurrentTime(struct timespec* ts) -{ - long rc; - rc=clock_gettime(CLOCK_REALTIME,ts); - ts->tv_sec = TSepochUnixToEpics(ts); - return rc; -} - -/* routine for causing sync to occur (not a hardware one) */ -static long TSforceSoftSync(int Card) -{ - semGive(TSdata.sync_occurred); - return 0; -} - -/* -TSaddStamp - Add time stamp op1 to time stamp op2 giving time stamp -result -*/ -static void TSaddStamp( struct timespec* result, - struct timespec* op1, struct timespec* op2) -{ - result->tv_sec = op1->tv_sec + op2->tv_sec; - result->tv_nsec = op1->tv_nsec + op2->tv_nsec; - - /* adjust seconds if needed */ - if(result->tv_nsec >= TS_BILLION) - { - result->tv_sec++; - result->tv_nsec -= TS_BILLION; - } - return; -} - -/* -TScalcDiff() - Calculate the difference between to time stamps. The -difference between arguments 'a' and 'b' is returned in 'diff'. The -return value from this routine is the direction: (1)=a>b, (-1)=atv_sec < b->tv_sec) { dir=-1; big_time=b; small_time=a; } - else if(a->tv_sec > b->tv_sec) { dir=1; small_time=b; big_time=a; } - else if(a->tv_nsec == b->tv_nsec){ dir=0; small_time=b; big_time=a;} - else if(a->tv_nsec < b->tv_nsec) { dir=-1; big_time=b; small_time=a; } - else { dir=1; small_time=b; big_time=a; } - - diff->tv_sec=big_time->tv_sec-small_time->tv_sec; - - if(big_time->tv_nsec>=small_time->tv_nsec) - diff->tv_nsec=big_time->tv_nsec-small_time->tv_nsec; - else - { - diff->tv_nsec = TS_BILLION + big_time->tv_nsec-small_time->tv_nsec; - diff->tv_sec--; - } - /* ---------------------this block sucks--------------------*/ - return dir; -} - -/**************************************************************************/ -/* more routines for managing sockets */ -/**************************************************************************/ - -/* get a UDP socket for a port, return a sockaddr for it. */ -static int TSgetSocket(int port, struct sockaddr_in* sin) -{ - int soc; - - sin->sin_port=htons(port); - sin->sin_family=AF_INET; - sin->sin_addr.s_addr=htonl(INADDR_ANY); - if( (soc=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0 ) - { perror("socket create failed"); return -1; } - Debug(5,"sizeof sin = %d\n", (int) sizeof(struct sockaddr_in)); - if( bind(soc,(struct sockaddr*)sin,sizeof(struct sockaddr_in)) < 0 ) - { perror("socket bind failed"); close(soc); return -1; } - - return soc; -} - -/* attempt to get data from a socket after sending a request to it. -0ptionally return round trip time and the sockaddr of the responsedent. -*/ -static long TSgetData(char* buf, int buf_size, int soc, - struct sockaddr* to_sin, struct sockaddr* from_sin, - struct timespec* round_trip) -{ - int retry_count=0; - int num,mlen,flen; - fd_set readfds; - volatile unsigned long s,us; - struct timeval timeOut; - struct timespec send_time,recv_time; - - /* - * joh 08-26-99 - * added this code which removes responses laying around from - * requests made in the past that timed out - */ - Debug(8,"removing stale responses %s\n", ""); - while (1) { - int status; - - status = ioctl (soc, FIONREAD, (int) &mlen); - if (status<0) { - Debug(1,"ioctl FIONREAD failed because \"%s\"?\n", strerror(errno)); - break; - } - else if (mlen==0) { - break; - } - Debug(1,"removing stale response of %d bytes\n", mlen); - recvfrom(soc,buf,buf_size,0,from_sin,&flen); - } - - /* convert millisecond time out to seconds/microseconds */ - s=TSdata.time_out/1000; us=(TSdata.time_out-(s*1000))*1000; - Debug(6,"time_out Second=%lu\n",s); - Debug(6,"time_out Microsecond=%lu\n",us); - do - { - Debug(8,"sednto port %d\n", - ntohs(((struct sockaddr_in*)to_sin)->sin_port)); - if(round_trip) clock_gettime(CLOCK_REALTIME,&send_time); - if( sendto(soc,buf,buf_size,0,to_sin,sizeof(struct sockaddr)) < 0 ) - { perror("sendto failed"); return -1; } - FD_ZERO(&readfds); FD_SET(soc,&readfds); - timeOut.tv_sec=s; timeOut.tv_usec=us; - num=select(FD_SETSIZE,&readfds,(fd_set*)NULL,(fd_set*)NULL,&timeOut); - if(round_trip) clock_gettime(CLOCK_REALTIME,&recv_time); - if(num==ERROR) { perror("select failed"); return -1; } - } - while(num==0 && ++retry_count= TS_RETRY_COUNT) - { Debug0(5,"TSgetData - retry count exceeded\n"); return -1; } - else - { - /* data available */ - flen=from_sin?sizeof(struct sockaddr):0; - if((mlen=recvfrom(soc,buf,buf_size,0,from_sin,&flen))<0) - { perror("recvfrom failed"); return -1; } - if(from_sin) - { - Debug(8,"recvfrom port %d\n", - ntohs(((struct sockaddr_in*)from_sin)->sin_port)); - Debug(8,"flen = %d\n",flen); - Debug(8,"mlen = %d\n",mlen); - } - if(round_trip) TScalcDiff(&send_time,&recv_time,round_trip); - } - return mlen; -} - -/*************************************************************************/ -/* all the functions that follow are test functions */ -/*************************************************************************/ - -/* test function to print the IOC real time clock value. */ -void TSprintRealTime() -{ - struct timespec tp; - - TSgetTime(&tp); - TSprintf("real time clock = %lu,%lu\n",tp.tv_sec,tp.tv_nsec); - TSprintf("EPICS clock = %lu,%lu\n", - TSdata.event_table[TSdata.sync_event].tv_sec, - TSdata.event_table[TSdata.sync_event].tv_nsec); - return; -} - -/* test function to print an event time stamp */ -void TSprintTimeStamp(int num) -{ - struct timespec tp; - - TSgetTimeStamp(num,&tp); - TSprintf("event %d occurred: %lu.%lu\n",num,tp.tv_sec,tp.tv_nsec); - return; -} - -/* test function to print the current time using event system */ -void TSprintCurrentTime() -{ - struct timespec tp; - - TScurrentTimeStamp(&tp); - TSprintf("Current Event System time: %lu.%lu\n",tp.tv_sec,tp.tv_nsec); - TSaccurateTimeStamp(&tp); - TSprintf("Accurate Event System time: %lu.%lu\n",tp.tv_sec,tp.tv_nsec); - return; -} - -/* test function to query the boot server for the current time. */ -void TSprintUnixTime() -{ - struct timespec ts; - - if(TSgetUnixTime(&ts)!=0) - { - TSprintf("Could not get Unix time\n"); - return; - } - TSprintf("boot server time clock = %lu, %lu\n",ts.tv_sec,ts.tv_nsec); - return; -} - -/* test function to print the master timing IOC time stamp. */ -void TSprintMasterTime() -{ - struct timespec ts; - - if(TSgetMasterTime(&ts)!=0) - { - TSprintf("Could not get Unix time\n"); - return; - } - TSprintf("master time clock = %lu, %lu\n",ts.tv_sec,ts.tv_nsec); - return; -} - -/* gross and horrid example */ -long TSgetFirstOfYearVx(struct timespec* ts) -{ - time_t tloc; - struct tm t; - - time(&tloc); /* retrieve the current time */ - localtime_r(&tloc,&t); - t.tm_sec=0; - t.tm_min=0; - t.tm_hour=t.tm_isdst?1:0; - t.tm_mday=1; - t.tm_mon=0; - tloc=mktime(&t); - ts->tv_sec=tloc; - ts->tv_nsec=0; - return 0; -} diff --git a/src/db/drvTS.h b/src/db/drvTS.h deleted file mode 100644 index 9a5d854af..000000000 --- a/src/db/drvTS.h +++ /dev/null @@ -1,252 +0,0 @@ -#ifndef __DRVTS_h__ -#define __DRVTS_h__ - -/* - * $Log$ - * Revision 1.2 1998/03/19 20:41:16 mrk - * Checked for Y2K complience. It turns out it was even ok when NTP time overflows - * in 2036. However it was modified so that no overflows should occur while convert - * ing between NTP, UNIX, and EPICS epochs. - * In addition the conversion of fractions of a second to nanaoseconds was changed - * Formatting was changed so that interesting code does not run off right side of page. - * Hopefully EPICS base is now fine for Y2K. - * In fact it should be fine (as far as time is converned) until the Unix epoch - * overflows a 32 unsigned integer in the year 2106. - * - * Revision 1.1 1996/01/25 21:11:56 mrk - * moved includes; .ascii=> .db; path changes - * - * Revision 1.12 1995/08/30 15:39:07 jbk - * Added global variables for force accurate time stamps and direct time. - * - * Revision 1.11 1995/08/18 13:18:13 mrk - * Added function prototypes for ansi c - * - * Revision 1.10 1995/08/17 20:35:52 jbk - * fixed the debug macro to work with -pendantic option (yuck) - * - * Revision 1.9 1995/08/17 19:44:08 jbk - * Added a new utility function to get the first of the year time stamp. - * - * Revision 1.8 1995/08/16 19:04:20 jbk - * corrected vxworks time troubles - * - * Revision 1.7 1995/05/22 15:22:24 jbk - * changes TS_EXTERN thing - * - * Revision 1.6 1995/02/01 15:30:17 winans - * Added a type field to the configure command to disable the use of the event - * system hardware if desired. - * - * Revision 1.5 1994/10/31 20:36:17 jbk - * added new stuff - * - */ - -/************************************************************************** - * - * Author: Jim Kowalkowski - * - * Modification Log: - * ----------------- - * .01 01-06-94 jbk initial version - * - ***********************************************************************/ - -/***************************************************************** - COPYRIGHT NOTIFICATION -***************************************************************** - -(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO - -This software was developed under a United States Government license -described on the COPYRIGHT_UniversityOfChicago file included as part -of this distribution. -**********************************************************************/ - -#include -#include -#include -#include -#include - -#include - -#ifdef TS_DRIVER -#define TS_EXTERN -#else -#define TS_EXTERN extern -#endif - -#define ER_EVENT_RESET_TICK 0x7d /* Reset the tick counter */ - -#define TS_MAGIC ('T'<<24|'S'<<16|'d'<<8|'r') -#define TS_SLAVE_PORT 18322 -#define TS_MASTER_PORT 18323 -#define TS_RETRY_COUNT 4 -#define TS_TIME_OUT_MS 250 -#define TS_SECS_ASYNC_TRY_MASTER (60*5) /* every five minutes */ -#define TS_SECS_SYNC_TRY_MASTER (60*1) /* every one minute */ - -#define UDP_TIME_PORT 37 -#define UDP_NTP_PORT 123 - -#define TS_BILLION 1000000000 -#define TS_SYNC_RATE_SEC 10 -#define TS_CLOCK_RATE_HZ 1000 -#define TS_TOTAL_EVENTS 128 -/*Following is (SEC_IN_YEAR*90)+(22*SEC_IN_DAY) */ -/*22 is leap years from 1900 to 1990*/ -#define TS_1900_TO_EPICS_EPOCH 2840140800UL -/*Following is (SEC_IN_YEAR*70)+(17*SEC_IN_DAY) */ -/*17 is leap years from 1900 to 1970*/ -#define TS_1900_TO_VXWORKS_EPOCH 2208988800UL -/*Following is (SEC_IN_YEAR*20)+(5*SEC_IN_DAY) */ -/*5 is leap years from 1970 to 1990*/ -#define TS_VXWORKS_TO_EPICS_EPOCH 631152000UL - -#define TS_STAMP_SERVER_PRI 70 -#define TS_SYNC_SERVER_PRI 70 -#define TS_SYNC_CLIENT_PRI 70 -#define TS_ASYNC_CLIENT_PRI 70 - -typedef enum { TS_time_request, TS_sync_request, TS_sync_msg } TStype; -typedef enum { TS_master_alive, TS_master_dead } TSstate; -typedef enum { TS_async_none, TS_async_private, - TS_async_ntp, TS_async_time } TStime_protocol; -typedef enum { TS_sync_master, TS_async_master, - TS_sync_slave, TS_async_slave, - TS_direct_master, TS_direct_slave} TStime_type; - -struct TSstampTransStruct { - unsigned long magic; /* identifier */ - TStype type; /* transaction type */ - struct timespec master_time; /* master time stamp - last sync time */ - struct timespec current_time; /* master current time stamp 1990 epoch */ - struct timespec unix_time; /* time using 1900 epoch */ - unsigned long sync_rate; /* master sends sync at this rate */ - unsigned long clock_hz; /* master clock this frequency (tick rate) */ -}; -typedef struct TSstampTransStruct TSstampTrans; - -struct TSinfoStruct { - TSstate state; - TStime_type type; - TStime_protocol async_type; - int ts_sync_valid; - - struct timespec *event_table; /* timestamp table */ - - unsigned long sync_rate; /* master send sync at this rate */ - unsigned long clock_hz; /* master clock is this frequency */ - unsigned long clock_conv;/* conversion factor for tick_rate->ns */ - unsigned long time_out; /* udp packet time-out in milliseconds */ - int master_timing_IOC; /* 1=master, 0=slave */ - int master_port; /* port that master listens on */ - int slave_port; /* port that slave listens on */ - int total_events; /* this is the total event in the event system*/ - int sync_event; /* this is the sync event number */ - int has_event_system; /* 1=has event system, 0=no event system */ - int has_direct_time; /* 1=has direct time, 0=no direct time */ - int UserRequestedType; /* let user force the setting of type */ - - SEM_ID sync_occurred; - - struct sockaddr hunt; /* broadcast address info */ - struct sockaddr master; /* socket info for contacting master */ -}; -typedef struct TSinfoStruct TSinfo; - -/* global functions */ -#ifdef __cplusplus -extern "C" { -#endif -TS_EXTERN long TSinit(void); -TS_EXTERN long TSgetTimeStamp(int event_number,struct timespec* ts); -TS_EXTERN unsigned long TSepochNtpToUnix(struct timespec* ts); -TS_EXTERN unsigned long TSfractionToNano(unsigned long fraction); -TS_EXTERN unsigned long TSepochNtpToEpics(struct timespec* ts); -TS_EXTERN unsigned long TSepochUnixToEpics(struct timespec* ts); -TS_EXTERN unsigned long TSepochEpicsToUnix(struct timespec* ts); -TS_EXTERN long TScurrentTimeStamp(struct timespec* ts); -TS_EXTERN long TSaccurateTimeStamp(struct timespec* ts); -TS_EXTERN long TSgetFirstOfYearVx(struct timespec* ts); -TS_EXTERN void TSconfigure(int master, int sync_rate_sec, int clock_rate_hz, - int master_port, int slave_port, - unsigned long millisecond_request_time_out, int type); -TS_EXTERN long TSsetClockFromUnix(void); - -#ifndef TS_DRIVER -TS_EXTERN TSinfo TSdata; -TS_EXTERN TSdirectTimeVar; /* set to !=0 to indicate direct time available*/ -TS_EXTERN TSgoodTimeStamps; /* force best time stamps by setting != 0 */ -#endif - -#ifdef __cplusplus -}; -#endif - -/* NTP information - all this is backwards and documentation only */ -#define VN_SHIFT 2 /* Version - 3 bits */ -#define VN_version 3< -#endif -#ifndef INCLvxLibh -#include -#endif - -/* - * Macro equivalent of vxWorks glue for better performance - */ -#ifdef VRTX_KERNEL -# define semGive(SEMID)\ - { if ((SEMID)->count == 0)vrtxPost (&((SEMID)->count), 1); } - -# define semTake(SEMID)\ - {int dummy; vrtxPend (&((SEMID)->count), 0, &dummy); } -#endif - -typedef struct{ - SEM_ID ppend; /* wait for lock sem */ - unsigned short count; /* cnt of tasks waiting for lock */ - unsigned char lock; /* test and set lock bit */ - char pad; /* structure alignment */ -}FAST_LOCK; - -#define SEM_FAST_LOCK - -#if defined(SEM_FAST_LOCK) /* no lock test */ - -#define FASTLOCKINIT(PFAST_LOCK)\ - (((FAST_LOCK *)(PFAST_LOCK))->ppend = \ - semMCreate(SEM_DELETE_SAFE|SEM_INVERSION_SAFE|SEM_Q_PRIORITY)) -#define FASTLOCKFREE(PFAST_LOCK)\ - semDelete( ((FAST_LOCK *)(PFAST_LOCK))->ppend ) -#define FASTLOCK(PFAST_LOCK)\ - semTake(((FAST_LOCK *)(PFAST_LOCK))->ppend, WAIT_FOREVER); -#define FASTUNLOCK(PFAST_LOCK)\ - semGive(((FAST_LOCK *)(PFAST_LOCK))->ppend); -#define FASTLOCKNOWAIT(PFAST_LOCK) \ - ((semTake(((FAST_LOCK *)(PFAST_LOCK))->ppend,NO_WAIT)==0) ? TRUE : FALSE) -#define FASTLOCKTEST(PFAST_LOCK) \ -(\ - (semTake(((FAST_LOCK *)(PFAST_LOCK))->ppend,NO_WAIT)==0 )\ - ? (semGive(((FAST_LOCK *)(PFAST_LOCK))->ppend),FALSE)\ - : TRUE \ -) - - -#elif defined(TASK_LOCK_FAST_LOCK) - -#define FASTLOCKINIT(PFAST_LOCK)\ - (\ - ((FAST_LOCK *)(PFAST_LOCK))->count =0, \ - ((FAST_LOCK *)(PFAST_LOCK))->lock =0, \ - ((FAST_LOCK *)(PFAST_LOCK))->ppend = \ - semBCreate(SEM_Q_PRIORITY, SEM_EMPTY) \ - ) -#define FASTLOCKFREE(PFAST_LOCK)\ - semDelete( ((FAST_LOCK *)(PFAST_LOCK))->ppend ) - -#define FASTLOCK(PFAST_LOCK)\ - {\ - TASK_LOCK;\ - while( ((FAST_LOCK *)(PFAST_LOCK))->lock ){\ - ((FAST_LOCK *)(PFAST_LOCK))->count++;\ - TASK_UNLOCK;\ - semTake(((FAST_LOCK *)(PFAST_LOCK))->ppend, WAIT_FOREVER);\ - TASK_LOCK;\ - (((FAST_LOCK *)(PFAST_LOCK))->count)--;\ - }\ - ((FAST_LOCK *)(PFAST_LOCK))->lock= TRUE; - TASK_UNLOCK; - } - -#define FASTUNLOCK(PFAST_LOCK)\ - {\ - ((FAST_LOCK *)(PFAST_LOCK))->lock = FALSE;\ - if( ((FAST_LOCK *)(PFAST_LOCK))->count )\ - semGive(((FAST_LOCK *)(PFAST_LOCK))->ppend);\ - }; - -#define FASTLOCKTEST(PFAST_LOCK)\ -( ((FAST_LOCK *)(PFAST_LOCK))->lock ) - -#else /* vxTas() fast lock */ - -/* - * extra paren avoids order of ops problems - * (returns what semBCreate returns on v5 vxWorks) - */ -#define FASTLOCKINIT(PFAST_LOCK)\ - (\ - ((FAST_LOCK *)(PFAST_LOCK))->count =0, \ - ((FAST_LOCK *)(PFAST_LOCK))->lock =0, \ - ((FAST_LOCK *)(PFAST_LOCK))->ppend = \ - semBCreate(SEM_Q_PRIORITY, SEM_EMPTY) \ - ) - -/* - * new requirement with v5 vxWorks - */ -#define FASTLOCKFREE(PFAST_LOCK)\ - semDelete( ((FAST_LOCK *)(PFAST_LOCK))->ppend ) - -#define FASTLOCK(PFAST_LOCK)\ - {\ - ((FAST_LOCK *)(PFAST_LOCK))->count++;\ - while(!vxTas( (char *)&( ((FAST_LOCK *)(PFAST_LOCK))->lock ) ))\ - semTake(((FAST_LOCK *)(PFAST_LOCK))->ppend, WAIT_FOREVER);\ - ( ((FAST_LOCK *)(PFAST_LOCK))->count)--;\ - } - -#define FASTUNLOCK(PFAST_LOCK)\ - {\ - ((FAST_LOCK *)(PFAST_LOCK))->lock = FALSE;\ - if( ((FAST_LOCK *)(PFAST_LOCK))->count )\ - semGive(((FAST_LOCK *)(PFAST_LOCK))->ppend);\ - }; - -#define FASTLOCKNOWAIT(PFAST_LOCK) (vxTas((char *)&(((FAST_LOCK *)(PFAST_LOCK))->lock))) - -#define FASTLOCKTEST(PFAST_LOCK)\ -( ((FAST_LOCK *)(PFAST_LOCK))->lock ) - -#endif - -#endif /* Nothing after this endif */ diff --git a/src/db/initHooks.c b/src/db/initHooks.c index 04a5c39d2..0b9c2eb35 100644 --- a/src/db/initHooks.c +++ b/src/db/initHooks.c @@ -36,12 +36,12 @@ */ -#include -#include -#include -#include -#include -#include +#include +#include +#include + +#include "ellLib.h" +#include "initHooks.h" typedef struct initHookLink { ELLNODE node; diff --git a/src/db/initHooks.h b/src/db/initHooks.h index 6243c6988..b95b8cd2a 100644 --- a/src/db/initHooks.h +++ b/src/db/initHooks.h @@ -39,14 +39,13 @@ typedef enum { initHookAtBeginning, - initHookAfterGetResources, initHookAfterLogInit, initHookAfterCallbackInit, initHookAfterCaLinkInit, initHookAfterInitDrvSup, initHookAfterInitRecSup, initHookAfterInitDevSup, - initHookAfterTS_init, + initHookAfterClockInit, initHookAfterInitDatabase, initHookAfterFinishDevSup, initHookAfterScanInit, diff --git a/src/db/iocInit.c b/src/db/iocInit.c index e0ee80483..d3375d6a0 100644 --- a/src/db/iocInit.c +++ b/src/db/iocInit.c @@ -1,31 +1,14 @@ /* iocInit.c ioc initialization */ /* base/src/db $Id$ */ -/* - * Author: Marty Kraimer - * Date: 06-01-91 - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * Modification Log: +/* Author: Marty Kraimer Date: 06-01-91 */ + +/********************COPYRIGHT NOTIFICATION********************************** +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +****************************************************************************/ + +/* Modification Log: * ----------------- * .01 07-20-91 rac print release data; set env params * .02 08-06-91 mrk parm string length test changed to warning @@ -44,7 +27,7 @@ * .14 04-17-92 mrk Added wait before interruptAccept * .15 05-17-92 rcz moved sdrSum stuff to dbReadWrite.c * .16 05-19-92 mrk Changes for internal database structure changes - * .17 06-16-92 jba Added prset test to call of init_record second time loop + * .17 06-16-92 jba prset test to call of init_record second time * .18 07-31-92 rcz moved database loading to function dbLoad * .19 08-14-92 jba included dblinks with maximize severity in lockset * .20 08-27-92 mrk removed wakeup_init (For old I/O Event scanning) @@ -61,48 +44,39 @@ * .31 02-10-95 joh static => LOCAL */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include /* for sysSymTbl*/ -#include -#include -#include -#include - -#include "dbDefs.h" -#include "epicsPrint.h" -#include "ellLib.h" -#include "fast_lock.h" -#include "dbDefs.h" -#include "dbBase.h" -#include "dbAccess.h" -#include "dbScan.h" -#include "taskwd.h" -#include "callback.h" -#include "dbCommon.h" -#include "dbLock.h" -#include "dbFldTypes.h" -#include "devSup.h" -#include "drvSup.h" -#include "errMdef.h" -#include "recSup.h" -#include "envDefs.h" -#include "dbStaticLib.h" -#include "initHooks.h" -#include "drvTS.h" -#include "asLib.h" - -/*This module will declare and initilize module_type variables*/ -#define MODULE_TYPES_INIT 1 -#include +#include +#include +#include +#include +#include +#include +#include "dbDefs.h" +#include "osiThread.h" +#include "osiClock.h" +#include "osiSem.h" +#include "epicsPrint.h" +#include "ellLib.h" +#include "dbDefs.h" +#include "dbBase.h" +#include "dbAccess.h" +#include "dbScan.h" +#include "taskwd.h" +#include "callback.h" +#include "dbCommon.h" +#include "dbLock.h" +#include "dbFldTypes.h" +#include "devSup.h" +#include "drvSup.h" +#include "registryRecordType.h" +#include "registryDeviceSupport.h" +#include "registryDriverSupport.h" +#include "errMdef.h" +#include "recSup.h" +#include "envDefs.h" +#include "dbStaticLib.h" +#include "initHooks.h" +#include "asLib.h" LOCAL int initialized=FALSE; @@ -112,276 +86,147 @@ volatile int interruptAccept=FALSE; struct dbBase *pdbbase=NULL; /* define forward references*/ -LOCAL long initDrvSup(void); -LOCAL long initRecSup(void); -LOCAL long initDevSup(void); -LOCAL long finishDevSup(void); -LOCAL long initDatabase(void); -LOCAL long initialProcess(void); -LOCAL long getResources(char *fname); -LOCAL int getResourceToken(FILE *fp, char *pToken, unsigned maxToken); -LOCAL int getResourceTokenInternal(FILE *fp, char *pToken, unsigned maxToken); +LOCAL void initDrvSup(void); +LOCAL void initRecSup(void); +LOCAL void initDevSup(void); +LOCAL void finishDevSup(void); +LOCAL void initDatabase(void); +LOCAL void initialProcess(void); /* * Initialize EPICS on the IOC. */ -int iocInit(char * pResourceFilename) +int iocInit() { - long status; - char name[40]; - long rtnval; - void (*pinitHooks)() = NULL; - SYM_TYPE type; - if (initialized) { - epicsPrintf("iocInit can only be called once\n"); + errlogPrintf("iocInit can only be called once\n"); return(-1); } - - epicsPrintf("Starting iocInit\n"); + errlogPrintf("Starting iocInit\n"); if (!pdbbase) { - epicsPrintf("iocInit aborting because No database\n"); + errlogPrintf("iocInit aborting because No database\n"); return(-1); } - - - /* Setup initialization hooks, if initHooks routine has been defined. */ - strcpy(name, "_"); - strcat(name, "initHooks"); - rtnval = symFindByNameEPICS(sysSymTbl, name, (void *) &pinitHooks, &type); - if (pinitHooks) (*pinitHooks)(initHookAtBeginning); - + initHooks(initHookAtBeginning); coreRelease(); - status = getResources(pResourceFilename); - if (pinitHooks) (*pinitHooks)(initHookAfterGetResources); - - status = iocLogInit(); - if (status!=0) { - epicsPrintf("iocInit Failed to Initialize Ioc Log Client \n"); - } - if (pinitHooks) (*pinitHooks)(initHookAfterLogInit); - - - /* After this point, further calls to iocInit() are disallowed. */ + iocLogInit(); initHooks(initHookAfterLogInit); + /* After this point, further calls to iocInit() are disallowed. */ initialized = TRUE; - /* - * Initialize the watchdog task. These is different from vxWorks watchdogs, - * this task is assigned to watching and reporting if the vxWorks tasks - * (that it has been told to watch) are suspended. - */ taskwdInit(); - callbackInit(); + /* let threads start */ + threadSleep(.1); + initHooks(initHookAfterCallbackInit); + dbCaLinkInit(); initHooks(initHookAfterCaLinkInit); + initDrvSup(); initHooks(initHookAfterInitDrvSup); + initRecSup(); initHooks(initHookAfterInitRecSup); + initDevSup(); initHooks(initHookAfterInitDevSup); + clockInit(); initHooks(initHookAfterClockInit); - /* Wait 1/10 second for above initializations to complete*/ - (void)taskDelay(sysClkRateGet()/10); - if (pinitHooks) (*pinitHooks)(initHookAfterCallbackInit); - - /* Initialize Channel Access Link mechanism. */ - dbCaLinkInit(); - if (pinitHooks) (*pinitHooks)(initHookAfterCaLinkInit); - - if (initDrvSup() != 0) - epicsPrintf("iocInit: Drivers Failed during Initialization\n"); - if (pinitHooks) (*pinitHooks)(initHookAfterInitDrvSup); - - if (initRecSup() != 0) - epicsPrintf("iocInit: Record Support Failed during Initialization\n"); - if (pinitHooks) (*pinitHooks)(initHookAfterInitRecSup); - - if (initDevSup() != 0) - epicsPrintf("iocInit: Device Support Failed during Initialization\n"); - if (pinitHooks) (*pinitHooks)(initHookAfterInitDevSup); - - TSinit(); /* new time stamp driver (jbk) */ - if (pinitHooks) (*pinitHooks)(initHookAfterTS_init); - - /* initialize database records */ - if (initDatabase() != 0) - epicsPrintf("iocInit: Database Failed during Initialization\n"); - + initDatabase(); dbLockInitRecords(pdbbase); - if (pinitHooks) (*pinitHooks)(initHookAfterInitDatabase); + initHooks(initHookAfterInitDatabase); - if (finishDevSup() != 0) - epicsPrintf("iocInit: Device Support Failed during Finalization\n"); - if (pinitHooks) (*pinitHooks)(initHookAfterFinishDevSup); + finishDevSup(); initHooks(initHookAfterFinishDevSup); scanInit(); if(asInit()) { - epicsPrintf("iocInit: asInit Failed during initialization\n"); + errlogPrintf("iocInit: asInit Failed during initialization\n"); return(-1); } - (void)taskDelay(sysClkRateGet()/2); - - if (pinitHooks) (*pinitHooks)(initHookAfterScanInit); + threadSleep(.5); + initHooks(initHookAfterScanInit); /* Enable scan tasks and some driver support functions. */ - interruptAccept=TRUE; + interruptAccept=TRUE; initHooks(initHookAfterInterruptAccept); - if (pinitHooks) (*pinitHooks)(initHookAfterInterruptAccept); - - /* - * Process all records that have their "process at initialization" - * field set (pini). - */ - if (initialProcess() != 0) - epicsPrintf("iocInit: initialProcess Failed\n"); - - if (pinitHooks) (*pinitHooks)(initHookAfterInitialProcess); + initialProcess(); initHooks(initHookAfterInitialProcess); /* Start up CA server */ rsrv_init(); - epicsPrintf("iocInit: All initialization complete\n"); - - if (pinitHooks) (*pinitHooks)(initHookAtEnd); - + errlogPrintf("iocInit: All initialization complete\n"); + initHooks(initHookAtEnd); return(0); } -/* - * Initialize Driver Support - * Locate all driver support entry tables. - * Call the initialization routine (init) for each - * driver type. - */ -LOCAL long initDrvSup(void) /* Locate all driver support entry tables */ +LOCAL void initDrvSup(void) /* Locate all driver support entry tables */ { - char name[40]; - SYM_TYPE type; - long status=0; - long rtnval; - STATUS vxstatus; drvSup *pdrvSup; struct drvet *pdrvet; - /* - * For every driver support module, look up the name - * for that function in the vxWorks symbol table. If - * a driver entry table doesn't exist, report that - * fact. - */ for(pdrvSup = (drvSup *)ellFirst(&pdbbase->drvList); pdrvSup; pdrvSup = (drvSup *)ellNext(&pdrvSup->node)) { - strcpy(name,"_"); - strcat(name,pdrvSup->name); - vxstatus = symFindByNameEPICS(sysSymTbl, name, - (void *) &pdrvet, &type); - if (vxstatus != OK) { - status = S_drv_noDrvet; - errPrintf(status,__FILE__,__LINE__,"%s",pdrvSup->name); + pdrvet = registryDriverSupportFind(pdrvSup->name); + if(pdrvet==0) { + errlogPrintf("iocInit: driver %s not found\n",pdrvSup->name); continue; } - pdrvSup->pdrvet = pdrvet; + pdrvSup->pdrvet = pdrvet; /* * If an initialization routine is defined (not NULL), * for the driver support call it. */ - if (!pdrvet->init) continue; - rtnval = (*(pdrvet->init))(); - if (status == 0) status = rtnval; + if(pdrvet->init) (*(pdrvet->init))(); } - return(status); + return; } - -/* - * Initialize Record Support - * Allocate a record support structure for every record type - * plus space for an array of pointers to RSETs. - * Locate all record support entry tables. - * Call the initialization routine (init) for each - * record type. - */ -LOCAL long initRecSup(void) + +LOCAL void initRecSup(void) { - char name[60]; - SYM_TYPE type; - long status=0; - long rtnval; - STATUS vxstatus; - dbRecordType *pdbRecordType; + dbRecordType *pdbRecordType; + recordTypeLocation *precordTypeLocation; struct rset *prset; - for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); pdbRecordType; + for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); + pdbRecordType; pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) { - strcpy(name,"_"); - strcat(name,pdbRecordType->name); - strcat(name,"RSET"); - vxstatus = symFindByNameEPICS(sysSymTbl, name, - (void *)&pdbRecordType->prset, &type); - if (vxstatus != OK) { - status = S_rec_noRSET; - errPrintf(status,__FILE__,__LINE__,"%s",pdbRecordType->name); + precordTypeLocation = registryRecordTypeFind(pdbRecordType->name); + if (precordTypeLocation==0) { + errlogPrintf("iocInit record support for %s not found\n", + pdbRecordType->name); continue; } - prset = pdbRecordType->prset; - /* If an initialization routine exists for a record type, execute it */ - if(!prset->init) { - continue; - } else { - rtnval = (*prset->init)(); - if (status==0) - status = rtnval; - } + prset = precordTypeLocation->prset; + pdbRecordType->prset = prset; + if(prset->init) (*prset->init)(); } - return(status); + return; } -/* Initialize Device Support - * Locate all device support entry tables. - * Call the initialization routine (init) for each - * device type (First Pass). - */ -LOCAL long initDevSup(void) +LOCAL void initDevSup(void) { - char *pname; - char name[40]; - SYM_TYPE type; - long status=0; - long rtnval = 0; - STATUS vxstatus; dbRecordType *pdbRecordType; devSup *pdevSup; struct dset *pdset; - for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); pdbRecordType; + for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); + pdbRecordType; pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) { for(pdevSup = (devSup *)ellFirst(&pdbRecordType->devList); pdevSup; pdevSup = (devSup *)ellNext(&pdevSup->node)) { - if(!(pname = pdevSup->name)) continue; - strcpy(name, "_"); - strcat(name, pname); - vxstatus = (long) symFindByNameEPICS(sysSymTbl, name, - (void *) &pdset, &type); - if (vxstatus != OK) { - status = S_dev_noDSET; - errPrintf(status,__FILE__,__LINE__,"%s",pdevSup->name); + pdset = registryDeviceSupportFind(pdevSup->name); + if (pdset==0) { + errlogPrintf("device support %s not found\n",pdevSup->name); continue; } pdevSup->pdset = pdset; - if(!(pdset->init)) continue; - rtnval = (*pdset->init)(0); - if (status == 0) status = rtnval; + if(pdset->init) (*pdset->init)(0); } } - return(status); + return; } -/* Calls the second pass for each device support - * initialization routine. The second pass is made - * after the database records have been initialized and - * placed into lock sets. - */ -LOCAL long finishDevSup(void) +LOCAL void finishDevSup(void) { dbRecordType *pdbRecordType; devSup *pdevSup; struct dset *pdset; - for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); pdbRecordType; + for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); + pdbRecordType; pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) { for(pdevSup = (devSup *)ellFirst(&pdbRecordType->devList); pdevSup; pdevSup = (devSup *)ellNext(&pdevSup->node)) { @@ -390,14 +235,12 @@ LOCAL long finishDevSup(void) } } - return(0); + return; } -LOCAL long initDatabase(void) +LOCAL void initDatabase(void) { - long status=0; - long rtnval=0; - dbRecordType *pdbRecordType; + dbRecordType *pdbRecordType; dbFldDes *pdbFldDes; dbRecordNode *pdbRecordNode; devSup *pdevSup; @@ -408,7 +251,8 @@ LOCAL long initDatabase(void) DBLINK *plink; int j; - for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); pdbRecordType; + for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); + pdbRecordType; pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) { prset = pdbRecordType->prset; for (pdbRecordNode=(dbRecordNode *)ellFirst(&pdbRecordType->recList); @@ -420,7 +264,7 @@ LOCAL long initDatabase(void) if(!(precord->name[0])) continue; precord->rset = prset; precord->rdes = pdbRecordType; - FASTLOCKINIT(&precord->mlok); + precord->mlok = semMutexCreate(); ellInit(&(precord->mlis)); /* Reset the process active field */ @@ -430,16 +274,14 @@ LOCAL long initDatabase(void) pdevSup = (devSup *)ellNth(&pdbRecordType->devList,precord->dtyp+1); pdset = (pdevSup ? pdevSup->pdset : 0); precord->dset = pdset; - if(!prset->init_record) continue; - rtnval = (*prset->init_record)(precord,0); - if (status==0) status = rtnval; + if(prset->init_record) (*prset->init_record)(precord,0); } } - - /* - * Second pass to resolve links - */ - for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); pdbRecordType; + +/* initDatabse cont. */ + /* Second pass to resolve links */ + for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); + pdbRecordType; pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) { prset = pdbRecordType->prset; for (pdbRecordNode=(dbRecordNode *)ellFirst(&pdbRecordType->recList); @@ -480,7 +322,8 @@ LOCAL long initDatabase(void) } /* Call record support init_record routine - Second pass */ - for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); pdbRecordType; + for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); + pdbRecordType; pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) { prset = pdbRecordType->prset; for (pdbRecordNode=(dbRecordNode *)ellFirst(&pdbRecordType->recList); @@ -491,19 +334,17 @@ LOCAL long initDatabase(void) precord = pdbRecordNode->precord; if(!(precord->name[0])) continue; precord->rset = prset; - if(!prset->init_record) continue; - rtnval = (*prset->init_record)(precord,1); - if (status==0) status = rtnval; + if(prset->init_record) (*prset->init_record)(precord,1); } } - return(status); + return; } /* * Process database records at initialization if * their pini (process at init) field is set. */ -LOCAL long initialProcess(void) +LOCAL void initialProcess(void) { dbRecordType *pdbRecordType; dbRecordNode *pdbRecordNode; @@ -521,366 +362,21 @@ LOCAL long initialProcess(void) (void)dbProcess(precord); } } - return(0); + return; } - int dbLoadDatabase(char *filename,char *path,char *substitutions) { - return(dbReadDatabase(&pdbbase,filename,path,substitutions)); + int status; + status = dbReadDatabase(&pdbbase,filename,path,substitutions); + if(status) return(status); + status = registerRecordDeviceDriver(pdbbase); + return(status); } - -/*Remaining code supplied by Bob Zieman*/ -#define MAX 256 -#define SAME 0 -enum resType { - resDBF_STRING, - resDBF_SHORT, - resDBF_LONG, - resDBF_FLOAT, - resDBF_DOUBLE, - resInvalid}; -LOCAL char *cvt_str[] = { - "DBF_STRING", - "DBF_SHORT", - "DBF_LONG", - "DBF_FLOAT", - "DBF_DOUBLE", - "Invalid", -}; - -#define EPICS_ENV_PREFIX "EPICS_" - -long getResources(char *fname) +int dbLoadRecords(char* pfilename, char* substitutions) { - char s1[MAX]; - char s2[MAX]; - char s3[MAX]; - char name[40]; - FILE *fp; - enum resType cvType = resInvalid; - int epicsFlag; - SYM_TYPE type; - char *pSymAddr; - short n_short; - long n_long; - float n_float; - double n_double; - int status; - - if (!fname) return (0); - - if ((fp = fopen(fname, "r")) == 0) { - errPrintf( - -1L, - __FILE__, - __LINE__, - "No such Resource file - %s", - fname); - return (-1); - } - - while (TRUE) { - status = getResourceToken (fp, s1, sizeof(s1)); - if (status<0) { - /* - * EOF - */ - break; - } - status = getResourceToken (fp, s2, sizeof(s2)); - if (status<0) { - errPrintf ( - -1L, - __FILE__, - __LINE__, - "Missing resource data type field for resource=%s in file=%s", - s1, - fname); - break; - } - status = getResourceToken (fp, s3, sizeof(s3)); - if (status<0) { - errPrintf ( - -1L, - __FILE__, - __LINE__, - "Missing resource value field for resource=%s data type=%s file=%s", - s1, - s2, - fname); - break; /* EOF */ - } - - for (cvType = 0; cvType < resInvalid; cvType++) { - if (strcmp(s2, cvt_str[cvType]) == SAME) { - break; - } - } - - - strcpy(name, "_"); - strcat(name, s1); - status = symFindByNameEPICS(sysSymTbl, name, &pSymAddr, &type); - if (status!= OK) { - errPrintf ( - -1L, - __FILE__, - __LINE__, - "Matching Symbol name not found for resource=%s", - s1); - continue; - } - - status = strncmp ( - s1, - EPICS_ENV_PREFIX, - strlen (EPICS_ENV_PREFIX)); - if (status == SAME) { - epicsFlag = 1; - if (cvType != resDBF_STRING) { - errPrintf ( - -1L, - __FILE__, - __LINE__, -"%s should be set with type DBF_STRING not type %s", - s1, - s2); - continue; - } - } - else { - epicsFlag = 0; - } - - switch (cvType) { - case resDBF_STRING: - if ( epicsFlag ) { - char *pEnv; - - /* - * space for two strings, an '=' character, - * and a null termination - */ - pEnv = malloc (strlen (s3) + strlen (s1) + 2); - if (!pEnv) { - errPrintf( - -1L, - __FILE__, - __LINE__, -"Failed to set environment parameter \"%s\" to \"%s\" because \"%s\"\n", - s1, - s3, - strerror (errnoGet())); - break; - } - strcpy (pEnv, s1); - strcat (pEnv, "="); - strcat (pEnv, s3); - status = putenv (pEnv); - if (status<0) { - errPrintf( - -1L, - __FILE__, - __LINE__, -"Failed to set environment parameter \"%s\" to \"%s\" because \"%s\"\n", - s1, - s3, - strerror (errnoGet())); - } - /* - * vxWorks copies into a private buffer - * (this does not match UNIX behavior) - */ - free (pEnv); - } - else{ - strcpy(pSymAddr, s3); - } - break; - - case resDBF_SHORT: - if (sscanf(s3, "%hd", &n_short) != 1) { - errPrintf ( - -1L, - __FILE__, - __LINE__, - "Resource=%s value=%s conversion to %s failed", - s1, - s3, - cvt_str[cvType]); - continue; - } - *(short *) pSymAddr = n_short; - break; - - case resDBF_LONG: - if (sscanf(s3, "%ld", &n_long) != 1) { - errPrintf ( - -1L, - __FILE__, - __LINE__, - "Resource=%s value=%s conversion to %s failed", - s1, - s3, - cvt_str[cvType]); - continue; - } - *(long *) pSymAddr = n_long; - break; - - case resDBF_FLOAT: - if (sscanf(s3, "%e", &n_float) != 1) { - errPrintf ( - -1L, - __FILE__, - __LINE__, - "Resource=%s value=%s conversion to %s failed", - s1, - s3, - cvt_str[cvType]); - continue; - } - *(float *) pSymAddr = n_float; - break; - - case resDBF_DOUBLE: - if (sscanf(s3, "%le", &n_double) != 1) { - errPrintf ( - -1L, - __FILE__, - __LINE__, - "Resource=%s value=%s conversion to %s failed", - s1, - s3, - cvt_str[cvType]); - continue; - } - *(double *) pSymAddr = n_double; - break; - - default: - errPrintf ( - -1L, - __FILE__, - __LINE__, - "Invalid data type field=%s for resource=%s", - s2, - s1); - continue; - } - } - fclose(fp); - return (0); + return(dbReadDatabase(&pdbbase,pfilename,0,substitutions)); } - - -/* - * getResourceToken - */ -LOCAL int getResourceToken(FILE *fp, char *pToken, unsigned maxToken) -{ - int status; - - /* - * keep reading until we get a token - * (and comments have been stripped) - */ - while (TRUE) { - status = getResourceTokenInternal (fp, pToken, maxToken); - if (status < 0) { - return status; - } - - if (pToken[0] != '\0') { - return status; - } - } -} - - -/* - * getResourceTokenInternal - */ -LOCAL int getResourceTokenInternal(FILE *fp, char *pToken, unsigned maxToken) -{ - char formatString[32]; - char quoteCharString[2]; - int status; - - quoteCharString[0] = '\0'; - status = fscanf (fp, " %1[\"`'!]", quoteCharString); - if (status<0) { - return status; - } - - switch (quoteCharString[0]) { - /* - * its a comment - * (consume everything up to the next new line) - */ - case '!': - { - char tmp[MAX]; - - sprintf(formatString, "%%%d[^\n\r\v\f]", (int)(sizeof(tmp)-1)); - status = fscanf (fp, "%[^\n\r\v\f]",tmp); - pToken[0] = '\0'; - if (status<0) { - return status; - } - break; - } - - /* - * its a plain token - */ - case '\0': - sprintf(formatString, " %%%ds", maxToken-1); - - status = fscanf (fp, formatString, pToken); - if (status!=1) { - if (status < 0){ - pToken[0] = '\0'; - return status; - } - } - break; - - /* - * it was a quoted string - */ - default: - sprintf( - formatString, - "%%%d[^%c]", - maxToken-1, - quoteCharString[0]); - status = fscanf (fp, formatString, pToken); - if (status!=1) { - if (status < 0){ - pToken[0] = '\0'; - return status; - } - } - sprintf(formatString, "%%1[%c]", quoteCharString[0]); - status = fscanf (fp, formatString, quoteCharString); - if (status!=1) { - errPrintf ( - -1L, - __FILE__, - __LINE__, - "Resource file syntax error: unterminated string \"%s\"", - pToken); - pToken[0] = '\0'; - if (status < 0){ - return status; - } - } - break; - } - return 0; -} diff --git a/src/db/recGbl.c b/src/db/recGbl.c index 0b5cbd9f1..3b5b6f933 100644 --- a/src/db/recGbl.c +++ b/src/db/recGbl.c @@ -41,23 +41,23 @@ * .11 03-21-94 mcn Added fast link routines */ -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include -#include "dbDefs.h" -#include "epicsPrint.h" -#include "dbBase.h" -#include "dbEvent.h" -#include "dbAccess.h" -#include "dbConvert.h" -#include "dbScan.h" -#include "devSup.h" -#include "recGbl.h" -#include "dbCommon.h" -#include "drvTS.h" +#include "dbDefs.h" +#include "osiClock.h" +#include "epicsPrint.h" +#include "dbBase.h" +#include "dbEvent.h" +#include "dbAccess.h" +#include "dbConvert.h" +#include "dbScan.h" +#include "devSup.h" +#include "recGbl.h" +#include "dbCommon.h" /* local routines */ @@ -313,10 +313,10 @@ void recGblGetTimeStamp(void* prec) if(pr->tsel.type!=CONSTANT) { dbGetLink(&(pr->tsel), DBR_SHORT,&(pr->tse),0,0); - TSgetTimeStamp((int)pr->tse,(struct timespec*)&pr->time); + clockGetEventTime((int)pr->tse,&pr->time); } else - TSgetTimeStamp((int)pr->tse,(struct timespec*)&pr->time); + clockGetEventTime((int)pr->tse,&pr->time); } diff --git a/src/db/recGbl.h b/src/db/recGbl.h index fe7eefce0..9968bb42c 100644 --- a/src/db/recGbl.h +++ b/src/db/recGbl.h @@ -32,11 +32,7 @@ #define INCrecGblh 1 -#ifdef vxWorks -#ifndef INCdbCommonh #include -#endif -#endif /* * One ABSOLUTELY must include dbAccess.h before the @@ -51,15 +47,6 @@ #endif #include -/************************************************************************* - * The following must match definitions in global menu definitions - *************************************************************************/ - -/* GBL_IVOA */ -#define IVOA_CONTINUE 0 -#define IVOA_NO_OUTPUT 1 -#define IVOA_OUTPUT_IVOV 2 - /*************************************************************************/ #define recGblSetSevr(PREC,NSTA,NSEV) \ diff --git a/src/db/taskwd.c b/src/db/taskwd.c index 32d2be32d..63d77d0e8 100644 --- a/src/db/taskwd.c +++ b/src/db/taskwd.c @@ -32,27 +32,24 @@ * .02 05-04-94 mrk Allow user callback to call taskwdRemove */ -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include -#include "dbDefs.h" -#include "errlog.h" -#include "errMdef.h" -#include "taskwd.h" -#include "task_params.h" -#include "fast_lock.h" +#include "dbDefs.h" +#include "osiThread.h" +#include "osiSem.h" +#include "errlog.h" +#include "ellLib.h" +#include "errMdef.h" +#include "taskwd.h" struct task_list { ELLNODE node; VOIDFUNCPTR callback; void *arg; union { - int tid; + threadId tid; void *userpvt; } id; int suspended; @@ -60,15 +57,18 @@ struct task_list { static ELLLIST list; static ELLLIST anylist; -static FAST_LOCK lock; -static FAST_LOCK anylock; -static FAST_LOCK alloclock; -static int taskwdid=0; +static semId lock; +static semId anylock; +static semId alloclock; +static threadId taskwdid=0; volatile int taskwdOn=TRUE; struct freeList{ struct freeList *next; }; static struct freeList *freeHead=NULL; +/* Task delay times (seconds) */ +#define TASKWD_DELAY 6.0 + /*forward definitions*/ static void taskwdTask(void); @@ -77,59 +77,59 @@ static void freeList(struct task_list *pt); void taskwdInit() { - FASTLOCKINIT(&lock); - FASTLOCKINIT(&anylock); - FASTLOCKINIT(&alloclock); + lock = semMutexCreate(); + anylock = semMutexCreate(); + alloclock = semMutexCreate(); ellInit(&list); ellInit(&anylist); - taskwdid = taskSpawn(TASKWD_NAME,TASKWD_PRI, - TASKWD_OPT,TASKWD_STACK,(FUNCPTR )taskwdTask, - 0,0,0,0,0,0,0,0,0,0); + taskwdid = threadCreate( + "taskwd",threadPriorityLow,threadGetStackSize(threadStackSmall), + (THREADFUNC)taskwdTask,0); } -void taskwdInsert(int tid,VOIDFUNCPTR callback,void *arg) +void taskwdInsert(threadId tid,VOIDFUNCPTR callback,void *arg) { struct task_list *pt; - FASTLOCK(&lock); + semMutexTakeAssert(lock); pt = allocList(); ellAdd(&list,(void *)pt); pt->suspended = FALSE; pt->id.tid = tid; pt->callback = callback; pt->arg = arg; - FASTUNLOCK(&lock); + semMutexGive(lock); } void taskwdAnyInsert(void *userpvt,VOIDFUNCPTR callback,void *arg) { struct task_list *pt; - FASTLOCK(&anylock); + semMutexTakeAssert(anylock); pt = allocList(); ellAdd(&anylist,(void *)pt); pt->id.userpvt = userpvt; pt->callback = callback; pt->arg = arg; - FASTUNLOCK(&anylock); + semMutexGive(anylock); } -void taskwdRemove(int tid) +void taskwdRemove(threadId tid) { struct task_list *pt; - FASTLOCK(&lock); + semMutexTakeAssert(lock); pt = (struct task_list *)ellFirst(&list); while(pt!=NULL) { if (tid == pt->id.tid) { ellDelete(&list,(void *)pt); freeList(pt); - FASTUNLOCK(&lock); + semMutexGive(lock); return; } pt = (struct task_list *)ellNext((ELLNODE *)pt); } - FASTUNLOCK(&lock); + semMutexGive(lock); errMessage(-1,"taskwdRemove failed"); } @@ -137,18 +137,18 @@ void taskwdAnyRemove(void *userpvt) { struct task_list *pt; - FASTLOCK(&anylock); + semMutexTakeAssert(anylock); pt = (struct task_list *)ellFirst(&anylist); while(pt!=NULL) { if (userpvt == pt->id.userpvt) { ellDelete(&anylist,(void *)pt); freeList(pt); - FASTUNLOCK(&anylock); + semMutexGive(anylock); return; } pt = (struct task_list *)ellNext((void *)pt); } - FASTUNLOCK(&anylock); + semMutexGive(anylock); errMessage(-1,"taskwdanyRemove failed"); } @@ -158,20 +158,20 @@ static void taskwdTask(void) while(TRUE) { if(taskwdOn) { - FASTLOCK(&lock); + semMutexTakeAssert(lock); pt = (struct task_list *)ellFirst(&list); while(pt) { next = (struct task_list *)ellNext((void *)pt); - if(taskIsSuspended(pt->id.tid)) { - char *pname; + if(threadIsSuspended(pt->id.tid)) { + const char *pname; char message[100]; - pname = taskName(pt->id.tid); + pname = threadGetName(pt->id.tid); if(!pt->suspended) { struct task_list *ptany; pt->suspended = TRUE; - sprintf(message,"task %x %s suspended",pt->id.tid,pname); + sprintf(message,"task %s suspended",pname); errMessage(-1,message); ptany = (struct task_list *)ellFirst(&anylist); while(ptany) { @@ -183,7 +183,7 @@ static void taskwdTask(void) void *arg = pt->arg; /*Must allow callback to call taskwdRemove*/ - FASTUNLOCK(&lock); + semMutexGive(lock); (pcallback)(arg); /*skip rest because we have unlocked*/ break; @@ -194,9 +194,9 @@ static void taskwdTask(void) } pt = next; } - FASTUNLOCK(&lock); + semMutexGive(lock); } - taskDelay(TASKWD_DELAY*vxTicksPerSecond); + threadSleep(TASKWD_DELAY); } } @@ -205,7 +205,7 @@ static struct task_list *allocList(void) { struct task_list *pt; - FASTLOCK(&alloclock); + semMutexTakeAssert(alloclock); if(freeHead) { pt = (struct task_list *)freeHead; freeHead = freeHead->next; @@ -214,15 +214,15 @@ static struct task_list *allocList(void) errMessage(0,"taskwd failed on call to calloc\n"); exit(1); } - FASTUNLOCK(&alloclock); + semMutexGive(alloclock); return(pt); } static void freeList(struct task_list *pt) { - FASTLOCK(&alloclock); + semMutexTakeAssert(alloclock); ((struct freeList *)pt)->next = freeHead; freeHead = (struct freeList *)pt; - FASTUNLOCK(&alloclock); + semMutexGive(alloclock); } diff --git a/src/db/taskwd.h b/src/db/taskwd.h index 0b84f48b7..14bfe170a 100644 --- a/src/db/taskwd.h +++ b/src/db/taskwd.h @@ -35,11 +35,13 @@ #ifndef INCtaskwdh #define INCtaskwdh 1 +#include "osiThread.h" + #ifdef __STDC__ void taskwdInit(); -void taskwdInsert(int tid, VOIDFUNCPTR callback,void *arg); +void taskwdInsert(threadId tid, VOIDFUNCPTR callback,void *arg); void taskwdAnyInsert(void *userpvt, VOIDFUNCPTR callback,void *arg); -void taskwdRemove(int tid); +void taskwdRemove(threadId tid); void taskwdAnyRemove(void *userpvt); #else void taskwdInit(); diff --git a/src/dbStatic/Makefile b/src/dbStatic/Makefile index 8cca632b9..fe420fc56 100644 --- a/src/dbStatic/Makefile +++ b/src/dbStatic/Makefile @@ -1,7 +1,46 @@ TOP=../.. -include $(TOP)/config/CONFIG_BASE +include $(TOP)/configure/CONFIG -include $(TOP)/config/RULES_ARCHS +# includes to install from this sub-project +# +INC += alarm.h alarmString.h dbBase.h dbFldTypes.h +INC += dbStaticLib.h link.h special.h guigroup.h +# Sources to compile & put into lib: +# +LIBSRCS := dbStaticLib.c dbYacc.c dbPvdLib.c dbStaticNoRun.c + +# Library to build: +# +LIBRARY := Db + +# Products to build: +# +PROD := dbReadTest dbExpand dbToMenuH dbToRecordtypeH + +# libs needed by PROD: +# +PROD_LIBS := Db Com Osi + +#==================================================== + +dbStaticLib_SRCS = \ + dbYacc.c\ + dbPvdLib.c\ + dbStaticRun.c\ + dbStaticLib.c + +IOC_LIBRARY_vxWorks = dbStaticLib + +#==================================================== +include $(TOP)/configure/RULES_BUILD + +# Extra rule since dbLexRoutines.c is included in dbYacc.c +dbYacc$(OBJ): dbLex.c ../dbLexRoutines.c + +clean:: + @$(RM) dbLex.c dbYacc.c + +# EOF Makefile.Host for base/src/dbStatic diff --git a/src/dbStatic/Makefile.Host b/src/dbStatic/Makefile.Host deleted file mode 100644 index 9fbb3521b..000000000 --- a/src/dbStatic/Makefile.Host +++ /dev/null @@ -1,37 +0,0 @@ -# Makefile.Host for base/src/dbStatic -# -# -TOP = ../../.. -include $(TOP)/config/CONFIG_BASE - - -# includes to install from this sub-project -# -INC += alarm.h alarmString.h dbBase.h dbFldTypes.h -INC += dbStaticLib.h link.h special.h guigroup.h - -# Sources to compile & put into lib: -# -LIBSRCS := dbStaticLib.c dbYacc.c dbPvdLib.c dbStaticNoRun.c - -# Library to build: -# -LIBRARY := Db - -# Products to build: -# -PROD := dbReadTest dbExpand dbToMenuH dbToRecordtypeH - -# libs needed by PROD: -# -PROD_LIBS := Db Com - -include $(TOP)/config/RULES.Host - -# Extra rule since dbLexRoutines.c is included in dbYacc.c -dbYacc$(OBJ): dbLex.c ../dbLexRoutines.c - -clean:: - @$(RM) dbLex.c dbYacc.c - -# EOF Makefile.Host for base/src/dbStatic diff --git a/src/dbStatic/Makefile.Vx b/src/dbStatic/Makefile.Vx deleted file mode 100644 index cb2939749..000000000 --- a/src/dbStatic/Makefile.Vx +++ /dev/null @@ -1,29 +0,0 @@ -TOP = ../../.. -include $(TOP)/config/CONFIG_BASE - -SRCS.c = \ - dbYacc.c \ - ../dbPvdLib.c\ - ../dbStaticRun.c\ - ../dbStaticLib.c - -OBJSdbLib = \ - dbYacc.o\ - dbPvdLib.o\ - dbStaticRun.o\ - dbStaticLib.o - -PROD = dbStaticLib - -include $(TOP)/config/RULES.Vx - -# Extra rule since dbLexRoutines.c is included in dbYacc.c -dbYacc.o: dbLex.c ../dbLexRoutines.c - -clean:: - @$(RM) dbLex.c dbYacc.c - -dbStaticLib: $(OBJSdbLib) - $(RM) $@ - $(LINK.c) $@ $(OBJSdbLib) $(LDLIBS) - diff --git a/src/dbStatic/alarm.h b/src/dbStatic/alarm.h index de780deab..de8cbb277 100644 --- a/src/dbStatic/alarm.h +++ b/src/dbStatic/alarm.h @@ -34,6 +34,9 @@ * .02 08-11-92 jba added new status DISABLE_ALARM, SIMM_ALARM * .03 05-11-94 jba added new status READ_ACCESS_ALARM, WRITE_ACCESS_ALARM * $Log$ + * Revision 1.3 1998/03/12 20:43:35 jhill + * fixed string defs + * * Revision 1.2 1996/06/19 19:59:31 jhill * added missing defines/enums, corrected defines * @@ -43,8 +46,8 @@ #ifndef INCalarmh #define INCalarmh 1 -#include -#include +#include "shareLib.h" +#include "epicsTypes.h" /* defines for the choice fields */ /* ALARM SEVERITIES - NOTE: must match defs in choiceGbl.ascii GBL_ALARM_SEV */ diff --git a/src/dbStatic/dbBase.h b/src/dbStatic/dbBase.h index a15c159b5..d5a9f637c 100644 --- a/src/dbStatic/dbBase.h +++ b/src/dbStatic/dbBase.h @@ -34,9 +34,9 @@ #ifndef INCdbBaseh #define INCdbBaseh 1 -#include -#include -#include +#include "dbFldTypes.h" +#include "ellLib.h" +#include "dbDefs.h" typedef struct dbMenu { ELLNODE node; diff --git a/src/dbStatic/dbLexRoutines.c b/src/dbStatic/dbLexRoutines.c index a1402fafa..73957d270 100644 --- a/src/dbStatic/dbLexRoutines.c +++ b/src/dbStatic/dbLexRoutines.c @@ -19,9 +19,6 @@ of this distribution. /*The routines in this module are serially reusable NOT reentrant*/ -#ifdef vxWorks -#include -#endif #include #include #include @@ -668,7 +665,6 @@ static void dbRecordtypeBody(void) pgphentry->userPvt = pdbRecordType; } ellAdd(&pdbbase->recordTypeList,&pdbRecordType->node); - dbGetRecordtypeSizeOffset(pdbRecordType); } static void dbDevice(char *recordtype,char *linktype, diff --git a/src/dbStatic/dbPvdLib.c b/src/dbStatic/dbPvdLib.c index bfeb0efd7..7fa749cd9 100644 --- a/src/dbStatic/dbPvdLib.c +++ b/src/dbStatic/dbPvdLib.c @@ -9,10 +9,7 @@ This software was developed under a United States Government license described on the COPYRIGHT_UniversityOfChicago file included as part of this distribution. **********************************************************************/ -#ifdef vxWorks -#include -#include -#endif +#include #include #include #include diff --git a/src/dbStatic/dbStaticLib.c b/src/dbStatic/dbStaticLib.c index 7e2d2d429..e262d29be 100644 --- a/src/dbStatic/dbStaticLib.c +++ b/src/dbStatic/dbStaticLib.c @@ -19,10 +19,6 @@ of this distribution. * .03 02-23-94 mrk dbPutString to DEV_CHOICE. Ok if no INP or OUT */ -#ifdef vxWorks -#include -#include -#endif #include #include #include @@ -30,6 +26,7 @@ of this distribution. #include #include +#include "cantProceed.h" #define DBFLDTYPES_GBLSOURCE #define GUIGROUPS_GBLSOURCE #define SPECIAL_GBLSOURCE @@ -527,29 +524,15 @@ void * epicsShareAPI dbCalloc(size_t nobj,size_t size) { void *p; - p=calloc(nobj,size); - if(p) return(p); - printf("dbCalloc: Can't allocate memory\n"); -#ifdef vxWorks - taskSuspend(0); -#else - abort(); -#endif - return(NULL); + p=callocMustSucceed(nobj,size,"dbCalloc"); + return(p); } void * epicsShareAPI dbMalloc(size_t size) { void *p; - p=malloc(size); - if(p) return(p); - printf("dbMalloc: Can't allocate memory\n"); -#ifdef vxWorks - taskSuspend(0); -#else - abort(); -#endif - return(NULL); + p=mallocMustSucceed(size,"dbMalloc"); + return(p); } #define INC_SIZE 256 @@ -2096,7 +2079,7 @@ long epicsShareAPI dbPutString(DBENTRY *pdbentry,char *pstring) status = putPvLink(pdbentry,ppOpt|msOpt,pstr); goto done; } - break; + /*break; is unnecessary*/ case VME_IO: { char *end; diff --git a/src/dbStatic/dbStaticNoRun.c b/src/dbStatic/dbStaticNoRun.c index 5d01e293f..f3a1a0cb9 100644 --- a/src/dbStatic/dbStaticNoRun.c +++ b/src/dbStatic/dbStaticNoRun.c @@ -314,11 +314,6 @@ long dbPutStringNum(DBENTRY *pdbentry,char *pstring) return(0); } -void dbGetRecordtypeSizeOffset(dbRecordType *pdbRecordType) -{ /*For no run cant and dont need to set size and offset*/ - return; -} - int epicsShareAPI dbGetMenuIndex(DBENTRY *pdbentry) { dbFldDes *pflddes = pdbentry->pflddes; diff --git a/src/dbStatic/dbStaticPvt.h b/src/dbStatic/dbStaticPvt.h index 6480a6ce6..e83358a06 100644 --- a/src/dbStatic/dbStaticPvt.h +++ b/src/dbStatic/dbStaticPvt.h @@ -48,8 +48,6 @@ char *dbRecordName(DBENTRY *pdbentry); char *dbGetStringNum(DBENTRY *pdbentry); long dbPutStringNum(DBENTRY *pdbentry,char *pstring); -void dbGetRecordtypeSizeOffset(dbRecordType *pdbRecordType); - /* The following is for path */ typedef struct dbPathNode { ELLNODE node; diff --git a/src/dbStatic/dbStaticRun.c b/src/dbStatic/dbStaticRun.c index caecfb049..4139b2016 100644 --- a/src/dbStatic/dbStaticRun.c +++ b/src/dbStatic/dbStaticRun.c @@ -15,20 +15,17 @@ of this distribution. * .01 06-12-95 mrk Initial */ -#ifdef vxWorks -#include -#include -#endif +#include #include #include #include #include #include -#include -#include /* for sysSymTbl*/ #include "dbDefs.h" #include "errMdef.h" +#include "dbBase.h" +#include "registryRecordType.h" #include "epicsPrint.h" #include "ellLib.h" #include "dbDefs.h" @@ -648,24 +645,3 @@ long dbPutMenuIndex(DBENTRY *pdbentry,int index) } return (S_dbLib_badField); } - -void dbGetRecordtypeSizeOffset(dbRecordType *pdbRecordType) -{ - char name[60]; - SYM_TYPE type; - STATUS vxstatus; - long status; - int (*sizeOffset)(dbRecordType *pdbRecordType); - - strcpy(name,"_"); - strcat(name,pdbRecordType->name); - strcat(name,"RecordSizeOffset"); - vxstatus = symFindByNameEPICS(sysSymTbl, name, - (void *)&sizeOffset, &type); - if (vxstatus != OK) { - status = S_dbLib_noSizeOffset; - errPrintf(status,__FILE__,__LINE__,"%s",name); - return; - } - sizeOffset(pdbRecordType); -} diff --git a/src/dbStatic/dbToRecordtypeH.c b/src/dbStatic/dbToRecordtypeH.c index 7725ba64f..6c572d1d3 100644 --- a/src/dbStatic/dbToRecordtypeH.c +++ b/src/dbStatic/dbToRecordtypeH.c @@ -112,10 +112,8 @@ int main(int argc,char **argv) fprintf(stderr,"Terminal error For input file %s\n",argv[1]); exit(-1); } - fprintf(outFile,"#include \n"); - fprintf(outFile,"#include \n"); fprintf(outFile,"#include \"ellLib.h\"\n"); - fprintf(outFile,"#include \"fast_lock.h\"\n"); + fprintf(outFile,"#include \"osiSem.h\"\n"); fprintf(outFile,"#include \"link.h\"\n"); fprintf(outFile,"#include \"tsDefs.h\"\n"); pdbMenu = (dbMenu *)ellFirst(&pdbbase->menuList); diff --git a/src/dbStatic/link.h b/src/dbStatic/link.h index 2865347fd..cb075804a 100644 --- a/src/dbStatic/link.h +++ b/src/dbStatic/link.h @@ -37,7 +37,7 @@ * .06 01-10-96 lrd added ca_link structure fields */ -#include +#include "dbDefs.h" #ifndef INClinkh #define INClinkh 1