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:
-
--
-TSgetTimeStamp(event_number, struct timespec* time_stamp)
-
--
-TScurrentTimeStamp(struct timespec* time_stamp)
-
--
-TSgetFirstOfYearVx(struct timespec* time_stamp)
-
--
-tsLocalTime(TS_STAMP*)
-
-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.
-
--
-TSreport(): Display all the information about the current configuration
-and status of this time stamp driver.
-
--
-TSprintRealTime(): Call the ErGetTime() function described below
-(if present) and print the time stamp returned from it. Also print the
-current EPICS time stamp.
-
--
-TSprintTimeStamp(event_number): Print the EPICS time stamp for the
-given event_number.
-
--
-TSprintCurrentTime(): Print the EPICS time stamp representing the
-current time.
-
--
-TSprintUnixTime(): Send a time stamp query transaction to the boot
-server or NTP server and print the time stamp returned.
-
--
-TSprintMasterTime(): Send a time stamp query transaction to the
-master time server and print the time stamp returned.
-
-
-
-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:
-
--
-recGblGetTimeStamp((dbCommon*)prec).
-
-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:
-
--
-master_indicator: 1=master timing IOC, 0=slave timing IOC, default
-is slave.
-
--
-sync_rate_seconds: The clock sync rate in seconds. This rate tells
-how often the synchronous time stamp support software will confirm that
-an IOC clock is synchronized. The default is 10 seconds.
-
--
-clock_rate_hz: The frequency in hertz of the clock, the default
-is 1000Hz for the event system. The value will be set to the IOC's internal
-clock rate when soft timing is used.
-
--
-master_port: The UDP port which a master timing IOC will use to
-receive time stamp requests. The default is 18233.
-
--
-slave_port: The UDP port which a slave will use to receive time
-stamp information from a master.
-
--
-time_out: UDP information request time out in milliseconds, if zero
-is entered here, the default will be used which is 250ms.
-
--
-type: 0=normal operation, 1=force soft timing type.
-
-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:
-
--
-long ErHaveReceiver(int event_card_number)
-
--
-long ErGetTicks(int event_card_number, unsigned long* ticks)
-
--
-long ErRegisterEventHandler(int event_card_num,EVENT_FUNC event_func)
-
--
-long ErRegisterErrorHandler(int event_card_num,ERROR_FUNC error_func)
-
--
-long ErForceSync(int event_card_number)
-
--
-long ErGetTime(struct timespec* time_stamp)
-
--
-long ErSyncEvent()
-
--
-long ErDirectTime()
-
--
-long ErDriverInit()
-
-The definition are as follows:
-
--
-ErHaveReceiver(): Returns -1 if no event (timing) hardware present,
-else returns the number of supported events.
-
--
-ErGetTicks(): Returns the number of ticks since the last hardware
-tick counter reset.
-
--
-ErRegisterEventHandler(): Informs the event system of a function
-to call when an event occurs, the format of the function will be defined
-below.
-
--
-ErRegisterErrorHandler(): Informs the event system of a function
-to call when an error occurs, the format of the function will be defined
-below.
-
--
-ErForceSync(): This function will force an event generator to generate
-a tick reset event and send it.
-
--
-ErGetTime(): This function returns the actual time. The intention
-here is that this function will retrieve the actual time from GPS system
-or equivalent and return is in time stamp format.
-
--
-ErSyncEvent(): Return the event number for the tick reset event.
-
--
-ErDirectTime(): Return 0 for normal operation, return value not
-= 0 for systems that has direct time access, such as a GPS.
-
--
-ErDriverInit(): The time stamp driver initialization function will
-call this user supplied function before it returns and after it sets up
-the vxWorks clock and attempts to set up the TIMEZONE variable. This can
-be useful to initialize a system such as a GPS (the year can be determined
-using the vxWorks ansiTime library).
-
-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:
-
--
-TSeventHandler(int Card,int EventNum,unsigned long Ticks)
-
--
-TSerrorHandler(int Card, int ErrorNum)
-
-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