changes for 3.14

This commit is contained in:
Marty Kraimer
1999-09-13 18:28:08 +00:00
parent 9ac1e36d7a
commit e37bd9fac8
50 changed files with 973 additions and 6790 deletions

View File

@@ -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) $<

View File

@@ -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) $<

View File

@@ -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) $<

View File

@@ -1,466 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="GENERATOR" CONTENT="Mozilla/4.06 [en] (X11; U; SunOS 5.6 sun4u) [Netscape]">
<TITLE>Synchronized Time Stamp Support</TITLE>
</HEAD>
<BODY>
<H1>
Synchronized Time Stamp Support</H1>
Author: Jim Kowalkowski
<H2>
MODIFICATION: 04AUG1998 (Marty Kraimer)</H2>
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.
<H2>
Introduction</H2>
<H3>
Purpose</H3>
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.
<H3>
Definitions</H3>
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.
<P>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.
<P>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.
<P>Soft Time: Each IOC increments the time stamps using it's own internal
clock.
<P>Master Timing IOC: The IOC which knows the actual time and is the source
of the actual time to all those who inquire.
<P>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.
<P>Soft Slave: An IOC which uses Soft Time and synchronizes it's time stamp
with a master.
<P>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.
<P>Soft Master: A Master Timing IOC that maintains it's time stamp using
a private clock.
<P>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.
<H3>
Overview</H3>
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.
<H4>
Event System Support</H4>
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.
<H4>
Soft Time Support</H4>
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.
<H4>
Role of a Master Timing IOC</H4>
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.
<H4>
Role of a Slave Timing IOC</H4>
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.
<H3>
Design Specifications Summary</H3>
<H4>
Event System Synchronized Time</H4>
All IOCs will have identical event times. In addition, all IOCs will maintain
the same current time.
<P>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.
<P>An optional event can be used as a "heartbeat" event. This event can
be used to signal errors.
<H4>
Soft Time</H4>
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.
<H2>
User Level Interface</H2>
<H3>
General Use Functions</H3>
Three functions exist in the synchronous time stamp support software for
the user to retrieve time stamps:
<UL>
<LI>
TSgetTimeStamp(event_number, struct timespec* time_stamp)</LI>
<LI>
TScurrentTimeStamp(struct timespec* time_stamp)</LI>
<LI>
TSgetFirstOfYearVx(struct timespec* time_stamp)</LI>
<LI>
tsLocalTime(TS_STAMP*)</LI>
</UL>
To retrieve the time stamp which represents the time that an event occurred,
use <B>TSgetTimeStamp()</B>. <B>TScurrentTimeStamp()</B> can be used to
retrieve the time stamp which represents the time of day. <B>TsLocalTime()</B>
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 <B>TSgetFirstOfYear()</B> attempts to give the caller a time stamp
representing January 1 of the current year relative to the vxWorks epoch
1970.
<P>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.
<H4>
Test Functions</H4>
The following functions can be run from the vxWorks shell to give information
about the time stamp driver.
<UL>
<LI>
<B>TSreport()</B>: Display all the information about the current configuration
and status of this time stamp driver.</LI>
<LI>
<B>TSprintRealTime()</B>: Call the ErGetTime() function described below
(if present) and print the time stamp returned from it. Also print the
current EPICS time stamp.</LI>
<LI>
<B>TSprintTimeStamp(event_number)</B>: Print the EPICS time stamp for the
given event_number.</LI>
<LI>
<B>TSprintCurrentTime()</B>: Print the EPICS time stamp representing the
current time.</LI>
<LI>
<B>TSprintUnixTime()</B>: Send a time stamp query transaction to the boot
server or NTP server and print the time stamp returned.</LI>
<LI>
<B>TSprintMasterTime()</B>: Send a time stamp query transaction to the
master time server and print the time stamp returned.</LI>
</UL>
<H4>
Debugging Information</H4>
A global variable exists named <B>TSdriverDebug</B>. 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.
<H3>
Record Support</H3>
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.
<P>To facilitate the use of the time stamp support software, a new record
support function will be added:
<UL>
<LI>
recGblGetTimeStamp((dbCommon*)prec).</LI>
</UL>
This routine uses TSgetTimeStamp(prec->tse, &amp;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.
<H2>
Driver Configuration</H2>
The synchronous time stamp support software is configured by calling TSconfigure()
from the "startup.cmd" file. The parameters to this routine are:
<UL>
<LI>
<B>master_indicator</B>: 1=master timing IOC, 0=slave timing IOC, default
is slave.</LI>
<LI>
<B>sync_rate_seconds</B>: 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.</LI>
<LI>
<B>clock_rate_hz</B>: 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.</LI>
<LI>
<B>master_port</B>: The UDP port which a master timing IOC will use to
receive time stamp requests. The default is 18233.</LI>
<LI>
<B>slave_port</B>: The UDP port which a slave will use to receive time
stamp information from a master.</LI>
<LI>
<B>time_out</B>: UDP information request time out in milliseconds, if zero
is entered here, the default will be used which is 250ms.</LI>
<LI>
<B>type</B>: 0=normal operation, 1=force soft timing type.</LI>
</UL>
This routine must be run before iocInit(). The synchronous time stamp support
software is initialized as part of iocInit. Running <B>TSreport()</B> after
iocInit() will produce a report which shows the current state of the driver.
<H2>
Event System interface</H2>
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:
<UL>
<LI>
long ErHaveReceiver(int event_card_number)</LI>
<LI>
long ErGetTicks(int event_card_number, unsigned long* ticks)</LI>
<LI>
long ErRegisterEventHandler(int event_card_num,EVENT_FUNC event_func)</LI>
<LI>
long ErRegisterErrorHandler(int event_card_num,ERROR_FUNC error_func)</LI>
<LI>
long ErForceSync(int event_card_number)</LI>
<LI>
long ErGetTime(struct timespec* time_stamp)</LI>
<LI>
long ErSyncEvent()</LI>
<LI>
long ErDirectTime()</LI>
<LI>
long ErDriverInit()</LI>
</UL>
The definition are as follows:
<UL>
<LI>
<B>ErHaveReceiver()</B>: Returns -1 if no event (timing) hardware present,
else returns the number of supported events.</LI>
<LI>
<B>ErGetTicks()</B>: Returns the number of ticks since the last hardware
tick counter reset.</LI>
<LI>
<B>ErRegisterEventHandler()</B>: Informs the event system of a function
to call when an event occurs, the format of the function will be defined
below.</LI>
<LI>
<B>ErRegisterErrorHandler()</B>: Informs the event system of a function
to call when an error occurs, the format of the function will be defined
below.</LI>
<LI>
<B>ErForceSync()</B>: This function will force an event generator to generate
a tick reset event and send it.</LI>
<LI>
<B>ErGetTime()</B>: 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.</LI>
<LI>
<B>ErSyncEvent()</B>: Return the event number for the tick reset event.</LI>
<LI>
<B>ErDirectTime()</B>: Return 0 for normal operation, return value not
= 0 for systems that has direct time access, such as a GPS.</LI>
<LI>
<B>ErDriverInit()</B>: 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).</LI>
</UL>
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:
<UL>
<LI>
TSeventHandler(int Card,int EventNum,unsigned long Ticks)</LI>
<LI>
TSerrorHandler(int Card, int ErrorNum)</LI>
</UL>
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.
<P>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 <B>TSdirectTimeVar</B> to a nonzero value has the same effect
as providing the ErDirectTime() function.
<H3>
Creating Direct Time Support</H3>
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.
<H2>
Operation</H2>
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.
<H3>
Synchronous Time</H3>
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.
<H4>
Master</H4>
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.
<P>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.
<P>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).
<H4>
Slave</H4>
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.
<P>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.
<P>The slave experiences the same problems as the master upon boot.
<H3>
Soft Time</H3>
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.
<H4>
Master</H4>
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.
<H4>
Slave</H4>
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.&nbsp;
<HR>
<P>Home page for <A HREF="http://www.aps.anl.gov/asd/controls/hideos/jimk.html">Jim
Kowalkowski</A> .
<BR>Argonne National Laboratory <A HREF="http://www.aps.anl.gov/asd/controls/epics_copyright.html">Copyright</A>
Information
<ADDRESS>
jbk@aps.anl.gov (Jim Kowalkowski)</ADDRESS>
<BR>updated 8/10/95
</BODY>
</HTML>

View File

@@ -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 <vxWorks.h>
#include <stdlib.h>
#include <stdio.h>
#include <semLib.h>
#include <rngLib.h>
#include <logLib.h>
#include <intLib.h>
#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 <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#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);
}

View File

@@ -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*/

View File

@@ -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 <vxWorks.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <taskLib.h>
#include <vxLib.h>
#include <tickLib.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#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);
}

View File

@@ -33,9 +33,7 @@ of this distribution.
#include <dbBase.h>
#include <dbFldTypes.h>
#include <link.h>
#ifdef vxWorks
#include <dbCommon.h>
#endif
#include <dbLock.h>
#include <tsDefs.h>
#include <callback.h>

View File

@@ -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 <vxWorks.h>
#include <lstLib.h>
#include <types.h>
#include <memLib.h>
#include <stdarg.h>
#include <stdioLib.h>
#include <string.h>
#include <taskLib.h>
#include <vxLib.h>
#include <tickLib.h>
#include <sysLib.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#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);
}

View File

@@ -32,7 +32,9 @@
#ifndef INCdbBkptsh
#define INCdbBkptsh 1
#include <lstLib.h>
#include <ellLib.h>
#include <osiSem.h>
#include <osiThread.h>
/* 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 */
};

View File

@@ -24,21 +24,21 @@ of this distribution.
* .01 26MAR96 lrd rewritten for simplicity, robustness and flexibility
****************************************************************/
#include <vxWorks.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <taskLib.h>
#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*/
}
}

View File

@@ -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;

View File

@@ -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")

View File

@@ -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 <vxWorks.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
*/
#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 <stddef.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#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 */

View File

@@ -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 <vxWorks.h>
#include <types.h>
#include <wdLib.h>
#include <semLib.h>
#include <stdioLib.h>
#include <vxLib.h>
#include <ellLib.h>
#include <sysLib.h>
#include <string.h>
#include <logLib.h>
#include <taskLib.h>
#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 <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#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

View File

@@ -41,6 +41,7 @@
#endif /*caClient*/
#include <db_field_log.h>
#include <osiThread.h>
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);

View File

@@ -28,35 +28,26 @@
* Modification Log:
* -----------------
*/
#include <vxWorks.h>
#include <lstLib.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <taskLib.h>
#include <vxLib.h>
#include <tickLib.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#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:

View File

@@ -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 <vxWorks.h>
#include <lstLib.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <semLib.h>
#include <tickLib.h>
#include <sysLib.h>
#include <taskLib.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#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

View File

@@ -31,26 +31,22 @@
* .01 03-30-95 mrk Extracted from dbLink.c
*/
#include <vxWorks.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <taskLib.h>
#include <semLib.h>
#include <sysLib.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#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);
}

View File

@@ -42,47 +42,46 @@
* .12 05-02-96 mrk Allow multiple priority event scan
*/
#include <vxWorks.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <semLib.h>
#include <rngLib.h>
#include <ellLib.h>
#include <vxLib.h>
#include <tickLib.h>
#include <sysLib.h>
#include <intLib.h>
#include <math.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <math.h>
#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; i<nPeriodic; i++) {
psl = dbCalloc(1,sizeof(scan_list));
papPeriodic[i] = psl;
FASTLOCKINIT(&psl->lock);
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;
}

View File

@@ -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 <vxWorks.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <timexLib.h>
/*for open and close*/
#include <ioLib.h>
#include <fcntl.h>
#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);
}

View File

@@ -45,11 +45,9 @@
*** the presumed order in dbAccess.c's dbGetField() routine
***/
#include <vxWorks.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdarg.h>
#include <fioLib.h>
#include <string.h>
#include <types.h>

View File

@@ -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 <vxWorks.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -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);
}

View File

@@ -22,12 +22,10 @@ of this distribution.
* .01 10APR96 mrk list db to CA links
****************************************************************/
#include <vxWorks.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <taskLib.h>
#include "dbStaticLib.h"
#include "link.h"

File diff suppressed because it is too large Load Diff

View File

@@ -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 <dbDefs.h>
/*
* 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*/

View File

@@ -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 <vxWorks.h>
#include <types.h>
#include <iv.h>
#include <vme.h>
#include <sysLib.h>
#include <memLib.h>
#include <intLib.h>
#include <logLib.h>
#include <vxLib.h>
#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<NELEMENTS(defaultHandlerAddr); i++) {
if (defaultHandlerAddr[i] == psub) {
return FALSE;
}
}
return TRUE;
}
/*
* unsolicitedHandlerEPICS()
* what gets called if they disconnect from an
* interrupt and an interrupt arrives on the
* disconnected vector
*
*/
void unsolicitedHandlerEPICS(int vectorNumber)
{
/*
* call logMsg() and not errMessage()
* so we are certain that printf()
* does not get called at interrupt level
*/
logMsg(
"%s: line=%d: Interrupt to EPICS disconnected vector = 0X %X",
(int)__FILE__,
__LINE__,
vectorNumber,
NULL,
NULL,
NULL);
}
/*
*
* initHandlerAddrList()
* init list of interrupt handlers to ignore
*
*/
LOCAL
void initHandlerAddrList(void)
{
int i;
SYM_TYPE type;
int status;
for (i=0; i<NELEMENTS(defaultHandlerNames); i++) {
status = symFindByNameEPICS (sysSymTbl,
defaultHandlerNames[i],
(char **)&defaultHandlerAddr[i],
&type);
if (status != OK) {
errPrintf(
S_dev_internal,
__FILE__,
__LINE__,
"initHandlerAddrList() %s not in sym table",
defaultHandlerNames[i]);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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 <vxWorks.h>
#include <timers.h>
#include <semLib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <tsDefs.h>
#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<<VN_SHIFT
#define LI_SHIFT 0 /* Leap Indicator LI - 2 bits */
#define LI_no_warning (0x00<<LI_SHIFT)
#define LI_61_sec_minute (0x01<<LI_SHIFT)
#define LI_59_sec_minute (0x02<<LI_SHIFT)
#define LI_alarm_condition (0x03<<LI_SHIFT)
#define MODE_SHIFT 5 /* Mode MODE - 3 bits */
#define MODE_reserved (0x00<<MODE_SHIFT)
#define MODE_sym_active (0x01<<MODE_SHIFT)
#define MODE_sym_passive (0x02<<MODE_SHIFT)
#define MODE_client (0x03<<MODE_SHIFT)
#define MODE_server (0x04<<MODE_SHIFT)
#define MODE_broadcast (0x05<<MODE_SHIFT)
#define MODE_reserved_NTP (0x06<<MODE_SHIFT)
#define MODE_reserved_pvt (0x07<<MODE_SHIFT)
#define STRAT_SHIFT 8 /* Stratum STRAT - 8 bits */
#define STRAT_unspecified (0x00<<STRAT_SHIFT)
#define STRAT_ascii (0x00<<STRAT_SHIFT)
#define STRAT_GPS (0x01<<STRAT_SHIFT)
#define STRAT_ATOM (0x01<<STRAT_SHIFT)
#define STRAT_address (0x02<<STRAT_SHIFT)
#define POLL_SHIFT 16 /* eight bits */
#define PREC_SHIFT 24 /* eight bits */
struct TS_ntp {
/* unsigned int info; */
unsigned char info[4];
unsigned int root_delay;
unsigned int root_disp;
unsigned int reference_id;
struct timespec reference_ts;
struct timespec originate_ts;
struct timespec receive_ts;
struct timespec transmit_ts;
/* char authenticator[96]; (optional) */
};
typedef struct TS_ntp TS_NTP;
/* debug macro creation */
#ifdef NODEBUG
#define Debug(l,f,v) ;
#else
#ifdef MAKE_DEBUG
volatile int MAKE_DEBUG = 0;
#define Debug(l,f,v) { if(l<= MAKE_DEBUG ) \
{ printf("%s:%d: ",__FILE__,__LINE__); printf(f,v); }}
#define Debug0(l,f) { if(l<= MAKE_DEBUG ) \
{ printf("%s:%d: ",__FILE__,__LINE__); printf(f); }}
#else
#define Debug(l,f,v) { if(l) \
{ printf("%s:%d: ",__FILE__,__LINE__); printf(f,v); }}
#define Debug0(l,f) { if(l) \
{ printf("%s:%d: ",__FILE__,__LINE__); printf(f); }}
#endif
#endif
#endif

View File

@@ -1,191 +0,0 @@
/* fast_lock.h */
/* share/epicsH $Id$ */
/*
* Author: Jeff Hill
* Date: 4-11-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
*
* Modification Log:
* -----------------
* .01 joh 041189 initial release into middle age
* .02 joh 071989 added fast lock test
* .03 joh 090391 VRTX kernel ifdef for V5 vxWorks
* .04 joh 091091 Now uses V5 vxWorks binary semaphore
* .05 joh 092491 Dont use V5 semaphore on V3 EPICS yet
* .06 jba 030692 added cast to vxTas arg in FASTLOCK vxWorks5
* .07 jba 081092 added cast to vxTas arg in FASTLOCKNOWAIT
* .08 mgb 082493 Removed V5/V4 conditional defines
* .09 joh 082493 include vxLib.h for vxWorks V5.1
* .10 joh 082593 made lock char as vxTas expects
* (padded structure to identical size)
* .11 joh 082593 made fast lock structure fields volatile
* .12 joh 091493 added sem and task lock based fast locks
* with ifdefs - removed volatile
*/
/*
*
*
* Macros and data structures for a much faster (than vrtx semaphore)
* mutual exclusion lock/unlock.
* (semaphore in this case is only used to wait for unlock)
*
* On a 68020 the following times include lock and unlock
*
* FASTLOCK-FASTUNLOCK 8 microsecs
* semTake-semGive(Macro) 80 microsecs
* semTake-semGive 92 microsecs
*
*/
#ifndef INCLfast_lockh
#define INCLfast_lockh
#ifndef INCLsemLibh
#include <semLib.h>
#endif
#ifndef INCLvxLibh
#include <vxLib.h>
#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 */

View File

@@ -36,12 +36,12 @@
*/
#include <vxWorks.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <ellLib.h>
#include <initHooks.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include "ellLib.h"
#include "initHooks.h"
typedef struct initHookLink {
ELLNODE node;

View File

@@ -39,14 +39,13 @@
typedef enum {
initHookAtBeginning,
initHookAfterGetResources,
initHookAfterLogInit,
initHookAfterCallbackInit,
initHookAfterCaLinkInit,
initHookAfterInitDrvSup,
initHookAfterInitRecSup,
initHookAfterInitDevSup,
initHookAfterTS_init,
initHookAfterClockInit,
initHookAfterInitDatabase,
initHookAfterFinishDevSup,
initHookAfterScanInit,

View File

@@ -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 <vxWorks.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sysLib.h>
#include <symLib.h>
#include <sysSymTbl.h> /* for sysSymTbl*/
#include <logLib.h>
#include <taskLib.h>
#include <envLib.h>
#include <errnoLib.h>
#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 <module_types.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "dbDefs.h"
#include "osiThread.h"
#include "osiClock.h"
#include "osiSem.h"
#include "epicsPrint.h"
#include "ellLib.h"
#include "dbDefs.h"
#include "dbBase.h"
#include "dbAccess.h"
#include "dbScan.h"
#include "taskwd.h"
#include "callback.h"
#include "dbCommon.h"
#include "dbLock.h"
#include "dbFldTypes.h"
#include "devSup.h"
#include "drvSup.h"
#include "registryRecordType.h"
#include "registryDeviceSupport.h"
#include "registryDriverSupport.h"
#include "errMdef.h"
#include "recSup.h"
#include "envDefs.h"
#include "dbStaticLib.h"
#include "initHooks.h"
#include "asLib.h"
LOCAL int initialized=FALSE;
@@ -112,276 +86,147 @@ volatile int interruptAccept=FALSE;
struct dbBase *pdbbase=NULL;
/* define forward references*/
LOCAL long initDrvSup(void);
LOCAL long initRecSup(void);
LOCAL long initDevSup(void);
LOCAL long finishDevSup(void);
LOCAL long initDatabase(void);
LOCAL long initialProcess(void);
LOCAL long getResources(char *fname);
LOCAL int getResourceToken(FILE *fp, char *pToken, unsigned maxToken);
LOCAL int getResourceTokenInternal(FILE *fp, char *pToken, unsigned maxToken);
LOCAL void initDrvSup(void);
LOCAL void initRecSup(void);
LOCAL void initDevSup(void);
LOCAL void finishDevSup(void);
LOCAL void initDatabase(void);
LOCAL void initialProcess(void);
/*
* Initialize EPICS on the IOC.
*/
int iocInit(char * pResourceFilename)
int iocInit()
{
long status;
char name[40];
long rtnval;
void (*pinitHooks)() = NULL;
SYM_TYPE type;
if (initialized) {
epicsPrintf("iocInit can only be called once\n");
errlogPrintf("iocInit can only be called once\n");
return(-1);
}
epicsPrintf("Starting iocInit\n");
errlogPrintf("Starting iocInit\n");
if (!pdbbase) {
epicsPrintf("iocInit aborting because No database\n");
errlogPrintf("iocInit aborting because No database\n");
return(-1);
}
/* Setup initialization hooks, if initHooks routine has been defined. */
strcpy(name, "_");
strcat(name, "initHooks");
rtnval = symFindByNameEPICS(sysSymTbl, name, (void *) &pinitHooks, &type);
if (pinitHooks) (*pinitHooks)(initHookAtBeginning);
initHooks(initHookAtBeginning);
coreRelease();
status = getResources(pResourceFilename);
if (pinitHooks) (*pinitHooks)(initHookAfterGetResources);
status = iocLogInit();
if (status!=0) {
epicsPrintf("iocInit Failed to Initialize Ioc Log Client \n");
}
if (pinitHooks) (*pinitHooks)(initHookAfterLogInit);
/* After this point, further calls to iocInit() are disallowed. */
iocLogInit(); initHooks(initHookAfterLogInit);
/* After this point, further calls to iocInit() are disallowed. */
initialized = TRUE;
/*
* Initialize the watchdog task. These is different from vxWorks watchdogs,
* this task is assigned to watching and reporting if the vxWorks tasks
* (that it has been told to watch) are suspended.
*/
taskwdInit();
callbackInit();
/* let threads start */
threadSleep(.1);
initHooks(initHookAfterCallbackInit);
dbCaLinkInit(); initHooks(initHookAfterCaLinkInit);
initDrvSup(); initHooks(initHookAfterInitDrvSup);
initRecSup(); initHooks(initHookAfterInitRecSup);
initDevSup(); initHooks(initHookAfterInitDevSup);
clockInit(); initHooks(initHookAfterClockInit);
/* Wait 1/10 second for above initializations to complete*/
(void)taskDelay(sysClkRateGet()/10);
if (pinitHooks) (*pinitHooks)(initHookAfterCallbackInit);
/* Initialize Channel Access Link mechanism. */
dbCaLinkInit();
if (pinitHooks) (*pinitHooks)(initHookAfterCaLinkInit);
if (initDrvSup() != 0)
epicsPrintf("iocInit: Drivers Failed during Initialization\n");
if (pinitHooks) (*pinitHooks)(initHookAfterInitDrvSup);
if (initRecSup() != 0)
epicsPrintf("iocInit: Record Support Failed during Initialization\n");
if (pinitHooks) (*pinitHooks)(initHookAfterInitRecSup);
if (initDevSup() != 0)
epicsPrintf("iocInit: Device Support Failed during Initialization\n");
if (pinitHooks) (*pinitHooks)(initHookAfterInitDevSup);
TSinit(); /* new time stamp driver (jbk) */
if (pinitHooks) (*pinitHooks)(initHookAfterTS_init);
/* initialize database records */
if (initDatabase() != 0)
epicsPrintf("iocInit: Database Failed during Initialization\n");
initDatabase();
dbLockInitRecords(pdbbase);
if (pinitHooks) (*pinitHooks)(initHookAfterInitDatabase);
initHooks(initHookAfterInitDatabase);
if (finishDevSup() != 0)
epicsPrintf("iocInit: Device Support Failed during Finalization\n");
if (pinitHooks) (*pinitHooks)(initHookAfterFinishDevSup);
finishDevSup(); initHooks(initHookAfterFinishDevSup);
scanInit();
if(asInit()) {
epicsPrintf("iocInit: asInit Failed during initialization\n");
errlogPrintf("iocInit: asInit Failed during initialization\n");
return(-1);
}
(void)taskDelay(sysClkRateGet()/2);
if (pinitHooks) (*pinitHooks)(initHookAfterScanInit);
threadSleep(.5);
initHooks(initHookAfterScanInit);
/* Enable scan tasks and some driver support functions. */
interruptAccept=TRUE;
interruptAccept=TRUE; initHooks(initHookAfterInterruptAccept);
if (pinitHooks) (*pinitHooks)(initHookAfterInterruptAccept);
/*
* Process all records that have their "process at initialization"
* field set (pini).
*/
if (initialProcess() != 0)
epicsPrintf("iocInit: initialProcess Failed\n");
if (pinitHooks) (*pinitHooks)(initHookAfterInitialProcess);
initialProcess(); initHooks(initHookAfterInitialProcess);
/* Start up CA server */
rsrv_init();
epicsPrintf("iocInit: All initialization complete\n");
if (pinitHooks) (*pinitHooks)(initHookAtEnd);
errlogPrintf("iocInit: All initialization complete\n");
initHooks(initHookAtEnd);
return(0);
}
/*
* Initialize Driver Support
* Locate all driver support entry tables.
* Call the initialization routine (init) for each
* driver type.
*/
LOCAL long initDrvSup(void) /* Locate all driver support entry tables */
LOCAL void initDrvSup(void) /* Locate all driver support entry tables */
{
char name[40];
SYM_TYPE type;
long status=0;
long rtnval;
STATUS vxstatus;
drvSup *pdrvSup;
struct drvet *pdrvet;
/*
* For every driver support module, look up the name
* for that function in the vxWorks symbol table. If
* a driver entry table doesn't exist, report that
* fact.
*/
for(pdrvSup = (drvSup *)ellFirst(&pdbbase->drvList); pdrvSup;
pdrvSup = (drvSup *)ellNext(&pdrvSup->node)) {
strcpy(name,"_");
strcat(name,pdrvSup->name);
vxstatus = symFindByNameEPICS(sysSymTbl, name,
(void *) &pdrvet, &type);
if (vxstatus != OK) {
status = S_drv_noDrvet;
errPrintf(status,__FILE__,__LINE__,"%s",pdrvSup->name);
pdrvet = registryDriverSupportFind(pdrvSup->name);
if(pdrvet==0) {
errlogPrintf("iocInit: driver %s not found\n",pdrvSup->name);
continue;
}
pdrvSup->pdrvet = pdrvet;
pdrvSup->pdrvet = pdrvet;
/*
* If an initialization routine is defined (not NULL),
* for the driver support call it.
*/
if (!pdrvet->init) continue;
rtnval = (*(pdrvet->init))();
if (status == 0) status = rtnval;
if(pdrvet->init) (*(pdrvet->init))();
}
return(status);
return;
}
/*
* Initialize Record Support
* Allocate a record support structure for every record type
* plus space for an array of pointers to RSETs.
* Locate all record support entry tables.
* Call the initialization routine (init) for each
* record type.
*/
LOCAL long initRecSup(void)
LOCAL void initRecSup(void)
{
char name[60];
SYM_TYPE type;
long status=0;
long rtnval;
STATUS vxstatus;
dbRecordType *pdbRecordType;
dbRecordType *pdbRecordType;
recordTypeLocation *precordTypeLocation;
struct rset *prset;
for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); pdbRecordType;
for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
pdbRecordType;
pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) {
strcpy(name,"_");
strcat(name,pdbRecordType->name);
strcat(name,"RSET");
vxstatus = symFindByNameEPICS(sysSymTbl, name,
(void *)&pdbRecordType->prset, &type);
if (vxstatus != OK) {
status = S_rec_noRSET;
errPrintf(status,__FILE__,__LINE__,"%s",pdbRecordType->name);
precordTypeLocation = registryRecordTypeFind(pdbRecordType->name);
if (precordTypeLocation==0) {
errlogPrintf("iocInit record support for %s not found\n",
pdbRecordType->name);
continue;
}
prset = pdbRecordType->prset;
/* If an initialization routine exists for a record type, execute it */
if(!prset->init) {
continue;
} else {
rtnval = (*prset->init)();
if (status==0)
status = rtnval;
}
prset = precordTypeLocation->prset;
pdbRecordType->prset = prset;
if(prset->init) (*prset->init)();
}
return(status);
return;
}
/* Initialize Device Support
* Locate all device support entry tables.
* Call the initialization routine (init) for each
* device type (First Pass).
*/
LOCAL long initDevSup(void)
LOCAL void initDevSup(void)
{
char *pname;
char name[40];
SYM_TYPE type;
long status=0;
long rtnval = 0;
STATUS vxstatus;
dbRecordType *pdbRecordType;
devSup *pdevSup;
struct dset *pdset;
for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); pdbRecordType;
for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
pdbRecordType;
pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) {
for(pdevSup = (devSup *)ellFirst(&pdbRecordType->devList); pdevSup;
pdevSup = (devSup *)ellNext(&pdevSup->node)) {
if(!(pname = pdevSup->name)) continue;
strcpy(name, "_");
strcat(name, pname);
vxstatus = (long) symFindByNameEPICS(sysSymTbl, name,
(void *) &pdset, &type);
if (vxstatus != OK) {
status = S_dev_noDSET;
errPrintf(status,__FILE__,__LINE__,"%s",pdevSup->name);
pdset = registryDeviceSupportFind(pdevSup->name);
if (pdset==0) {
errlogPrintf("device support %s not found\n",pdevSup->name);
continue;
}
pdevSup->pdset = pdset;
if(!(pdset->init)) continue;
rtnval = (*pdset->init)(0);
if (status == 0) status = rtnval;
if(pdset->init) (*pdset->init)(0);
}
}
return(status);
return;
}
/* Calls the second pass for each device support
* initialization routine. The second pass is made
* after the database records have been initialized and
* placed into lock sets.
*/
LOCAL long finishDevSup(void)
LOCAL void finishDevSup(void)
{
dbRecordType *pdbRecordType;
devSup *pdevSup;
struct dset *pdset;
for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); pdbRecordType;
for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
pdbRecordType;
pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) {
for(pdevSup = (devSup *)ellFirst(&pdbRecordType->devList); pdevSup;
pdevSup = (devSup *)ellNext(&pdevSup->node)) {
@@ -390,14 +235,12 @@ LOCAL long finishDevSup(void)
}
}
return(0);
return;
}
LOCAL long initDatabase(void)
LOCAL void initDatabase(void)
{
long status=0;
long rtnval=0;
dbRecordType *pdbRecordType;
dbRecordType *pdbRecordType;
dbFldDes *pdbFldDes;
dbRecordNode *pdbRecordNode;
devSup *pdevSup;
@@ -408,7 +251,8 @@ LOCAL long initDatabase(void)
DBLINK *plink;
int j;
for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); pdbRecordType;
for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
pdbRecordType;
pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) {
prset = pdbRecordType->prset;
for (pdbRecordNode=(dbRecordNode *)ellFirst(&pdbRecordType->recList);
@@ -420,7 +264,7 @@ LOCAL long initDatabase(void)
if(!(precord->name[0])) continue;
precord->rset = prset;
precord->rdes = pdbRecordType;
FASTLOCKINIT(&precord->mlok);
precord->mlok = semMutexCreate();
ellInit(&(precord->mlis));
/* Reset the process active field */
@@ -430,16 +274,14 @@ LOCAL long initDatabase(void)
pdevSup = (devSup *)ellNth(&pdbRecordType->devList,precord->dtyp+1);
pdset = (pdevSup ? pdevSup->pdset : 0);
precord->dset = pdset;
if(!prset->init_record) continue;
rtnval = (*prset->init_record)(precord,0);
if (status==0) status = rtnval;
if(prset->init_record) (*prset->init_record)(precord,0);
}
}
/*
* Second pass to resolve links
*/
for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); pdbRecordType;
/* initDatabse cont. */
/* Second pass to resolve links */
for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
pdbRecordType;
pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) {
prset = pdbRecordType->prset;
for (pdbRecordNode=(dbRecordNode *)ellFirst(&pdbRecordType->recList);
@@ -480,7 +322,8 @@ LOCAL long initDatabase(void)
}
/* Call record support init_record routine - Second pass */
for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); pdbRecordType;
for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
pdbRecordType;
pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) {
prset = pdbRecordType->prset;
for (pdbRecordNode=(dbRecordNode *)ellFirst(&pdbRecordType->recList);
@@ -491,19 +334,17 @@ LOCAL long initDatabase(void)
precord = pdbRecordNode->precord;
if(!(precord->name[0])) continue;
precord->rset = prset;
if(!prset->init_record) continue;
rtnval = (*prset->init_record)(precord,1);
if (status==0) status = rtnval;
if(prset->init_record) (*prset->init_record)(precord,1);
}
}
return(status);
return;
}
/*
* Process database records at initialization if
* their pini (process at init) field is set.
*/
LOCAL long initialProcess(void)
LOCAL void initialProcess(void)
{
dbRecordType *pdbRecordType;
dbRecordNode *pdbRecordNode;
@@ -521,366 +362,21 @@ LOCAL long initialProcess(void)
(void)dbProcess(precord);
}
}
return(0);
return;
}
int dbLoadDatabase(char *filename,char *path,char *substitutions)
{
return(dbReadDatabase(&pdbbase,filename,path,substitutions));
int status;
status = dbReadDatabase(&pdbbase,filename,path,substitutions);
if(status) return(status);
status = registerRecordDeviceDriver(pdbbase);
return(status);
}
/*Remaining code supplied by Bob Zieman*/
#define MAX 256
#define SAME 0
enum resType {
resDBF_STRING,
resDBF_SHORT,
resDBF_LONG,
resDBF_FLOAT,
resDBF_DOUBLE,
resInvalid};
LOCAL char *cvt_str[] = {
"DBF_STRING",
"DBF_SHORT",
"DBF_LONG",
"DBF_FLOAT",
"DBF_DOUBLE",
"Invalid",
};
#define EPICS_ENV_PREFIX "EPICS_"
long getResources(char *fname)
int dbLoadRecords(char* pfilename, char* substitutions)
{
char s1[MAX];
char s2[MAX];
char s3[MAX];
char name[40];
FILE *fp;
enum resType cvType = resInvalid;
int epicsFlag;
SYM_TYPE type;
char *pSymAddr;
short n_short;
long n_long;
float n_float;
double n_double;
int status;
if (!fname) return (0);
if ((fp = fopen(fname, "r")) == 0) {
errPrintf(
-1L,
__FILE__,
__LINE__,
"No such Resource file - %s",
fname);
return (-1);
}
while (TRUE) {
status = getResourceToken (fp, s1, sizeof(s1));
if (status<0) {
/*
* EOF
*/
break;
}
status = getResourceToken (fp, s2, sizeof(s2));
if (status<0) {
errPrintf (
-1L,
__FILE__,
__LINE__,
"Missing resource data type field for resource=%s in file=%s",
s1,
fname);
break;
}
status = getResourceToken (fp, s3, sizeof(s3));
if (status<0) {
errPrintf (
-1L,
__FILE__,
__LINE__,
"Missing resource value field for resource=%s data type=%s file=%s",
s1,
s2,
fname);
break; /* EOF */
}
for (cvType = 0; cvType < resInvalid; cvType++) {
if (strcmp(s2, cvt_str[cvType]) == SAME) {
break;
}
}
strcpy(name, "_");
strcat(name, s1);
status = symFindByNameEPICS(sysSymTbl, name, &pSymAddr, &type);
if (status!= OK) {
errPrintf (
-1L,
__FILE__,
__LINE__,
"Matching Symbol name not found for resource=%s",
s1);
continue;
}
status = strncmp (
s1,
EPICS_ENV_PREFIX,
strlen (EPICS_ENV_PREFIX));
if (status == SAME) {
epicsFlag = 1;
if (cvType != resDBF_STRING) {
errPrintf (
-1L,
__FILE__,
__LINE__,
"%s should be set with type DBF_STRING not type %s",
s1,
s2);
continue;
}
}
else {
epicsFlag = 0;
}
switch (cvType) {
case resDBF_STRING:
if ( epicsFlag ) {
char *pEnv;
/*
* space for two strings, an '=' character,
* and a null termination
*/
pEnv = malloc (strlen (s3) + strlen (s1) + 2);
if (!pEnv) {
errPrintf(
-1L,
__FILE__,
__LINE__,
"Failed to set environment parameter \"%s\" to \"%s\" because \"%s\"\n",
s1,
s3,
strerror (errnoGet()));
break;
}
strcpy (pEnv, s1);
strcat (pEnv, "=");
strcat (pEnv, s3);
status = putenv (pEnv);
if (status<0) {
errPrintf(
-1L,
__FILE__,
__LINE__,
"Failed to set environment parameter \"%s\" to \"%s\" because \"%s\"\n",
s1,
s3,
strerror (errnoGet()));
}
/*
* vxWorks copies into a private buffer
* (this does not match UNIX behavior)
*/
free (pEnv);
}
else{
strcpy(pSymAddr, s3);
}
break;
case resDBF_SHORT:
if (sscanf(s3, "%hd", &n_short) != 1) {
errPrintf (
-1L,
__FILE__,
__LINE__,
"Resource=%s value=%s conversion to %s failed",
s1,
s3,
cvt_str[cvType]);
continue;
}
*(short *) pSymAddr = n_short;
break;
case resDBF_LONG:
if (sscanf(s3, "%ld", &n_long) != 1) {
errPrintf (
-1L,
__FILE__,
__LINE__,
"Resource=%s value=%s conversion to %s failed",
s1,
s3,
cvt_str[cvType]);
continue;
}
*(long *) pSymAddr = n_long;
break;
case resDBF_FLOAT:
if (sscanf(s3, "%e", &n_float) != 1) {
errPrintf (
-1L,
__FILE__,
__LINE__,
"Resource=%s value=%s conversion to %s failed",
s1,
s3,
cvt_str[cvType]);
continue;
}
*(float *) pSymAddr = n_float;
break;
case resDBF_DOUBLE:
if (sscanf(s3, "%le", &n_double) != 1) {
errPrintf (
-1L,
__FILE__,
__LINE__,
"Resource=%s value=%s conversion to %s failed",
s1,
s3,
cvt_str[cvType]);
continue;
}
*(double *) pSymAddr = n_double;
break;
default:
errPrintf (
-1L,
__FILE__,
__LINE__,
"Invalid data type field=%s for resource=%s",
s2,
s1);
continue;
}
}
fclose(fp);
return (0);
return(dbReadDatabase(&pdbbase,pfilename,0,substitutions));
}
/*
* getResourceToken
*/
LOCAL int getResourceToken(FILE *fp, char *pToken, unsigned maxToken)
{
int status;
/*
* keep reading until we get a token
* (and comments have been stripped)
*/
while (TRUE) {
status = getResourceTokenInternal (fp, pToken, maxToken);
if (status < 0) {
return status;
}
if (pToken[0] != '\0') {
return status;
}
}
}
/*
* getResourceTokenInternal
*/
LOCAL int getResourceTokenInternal(FILE *fp, char *pToken, unsigned maxToken)
{
char formatString[32];
char quoteCharString[2];
int status;
quoteCharString[0] = '\0';
status = fscanf (fp, " %1[\"`'!]", quoteCharString);
if (status<0) {
return status;
}
switch (quoteCharString[0]) {
/*
* its a comment
* (consume everything up to the next new line)
*/
case '!':
{
char tmp[MAX];
sprintf(formatString, "%%%d[^\n\r\v\f]", (int)(sizeof(tmp)-1));
status = fscanf (fp, "%[^\n\r\v\f]",tmp);
pToken[0] = '\0';
if (status<0) {
return status;
}
break;
}
/*
* its a plain token
*/
case '\0':
sprintf(formatString, " %%%ds", maxToken-1);
status = fscanf (fp, formatString, pToken);
if (status!=1) {
if (status < 0){
pToken[0] = '\0';
return status;
}
}
break;
/*
* it was a quoted string
*/
default:
sprintf(
formatString,
"%%%d[^%c]",
maxToken-1,
quoteCharString[0]);
status = fscanf (fp, formatString, pToken);
if (status!=1) {
if (status < 0){
pToken[0] = '\0';
return status;
}
}
sprintf(formatString, "%%1[%c]", quoteCharString[0]);
status = fscanf (fp, formatString, quoteCharString);
if (status!=1) {
errPrintf (
-1L,
__FILE__,
__LINE__,
"Resource file syntax error: unterminated string \"%s\"",
pToken);
pToken[0] = '\0';
if (status < 0){
return status;
}
}
break;
}
return 0;
}

View File

@@ -41,23 +41,23 @@
* .11 03-21-94 mcn Added fast link routines
*/
#include <vxWorks.h>
#include <limits.h>
#include <types.h>
#include <stdioLib.h>
#include <strLib.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include "dbDefs.h"
#include "epicsPrint.h"
#include "dbBase.h"
#include "dbEvent.h"
#include "dbAccess.h"
#include "dbConvert.h"
#include "dbScan.h"
#include "devSup.h"
#include "recGbl.h"
#include "dbCommon.h"
#include "drvTS.h"
#include "dbDefs.h"
#include "osiClock.h"
#include "epicsPrint.h"
#include "dbBase.h"
#include "dbEvent.h"
#include "dbAccess.h"
#include "dbConvert.h"
#include "dbScan.h"
#include "devSup.h"
#include "recGbl.h"
#include "dbCommon.h"
/* local routines */
@@ -313,10 +313,10 @@ void recGblGetTimeStamp(void* prec)
if(pr->tsel.type!=CONSTANT)
{
dbGetLink(&(pr->tsel), DBR_SHORT,&(pr->tse),0,0);
TSgetTimeStamp((int)pr->tse,(struct timespec*)&pr->time);
clockGetEventTime((int)pr->tse,&pr->time);
}
else
TSgetTimeStamp((int)pr->tse,(struct timespec*)&pr->time);
clockGetEventTime((int)pr->tse,&pr->time);
}

View File

@@ -32,11 +32,7 @@
#define INCrecGblh 1
#ifdef vxWorks
#ifndef INCdbCommonh
#include <dbCommon.h>
#endif
#endif
/*
* One ABSOLUTELY must include dbAccess.h before the
@@ -51,15 +47,6 @@
#endif
#include <dbFldTypes.h>
/*************************************************************************
* The following must match definitions in global menu definitions
*************************************************************************/
/* GBL_IVOA */
#define IVOA_CONTINUE 0
#define IVOA_NO_OUTPUT 1
#define IVOA_OUTPUT_IVOV 2
/*************************************************************************/
#define recGblSetSevr(PREC,NSTA,NSEV) \

View File

@@ -32,27 +32,24 @@
* .02 05-04-94 mrk Allow user callback to call taskwdRemove
*/
#include <vxWorks.h>
#include <vxLib.h>
#include <stdlib.h>
#include <stdio.h>
#include <ellLib.h>
#include <taskLib.h>
#include <sysLib.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include "dbDefs.h"
#include "errlog.h"
#include "errMdef.h"
#include "taskwd.h"
#include "task_params.h"
#include "fast_lock.h"
#include "dbDefs.h"
#include "osiThread.h"
#include "osiSem.h"
#include "errlog.h"
#include "ellLib.h"
#include "errMdef.h"
#include "taskwd.h"
struct task_list {
ELLNODE node;
VOIDFUNCPTR callback;
void *arg;
union {
int tid;
threadId tid;
void *userpvt;
} id;
int suspended;
@@ -60,15 +57,18 @@ struct task_list {
static ELLLIST list;
static ELLLIST anylist;
static FAST_LOCK lock;
static FAST_LOCK anylock;
static FAST_LOCK alloclock;
static int taskwdid=0;
static semId lock;
static semId anylock;
static semId alloclock;
static threadId taskwdid=0;
volatile int taskwdOn=TRUE;
struct freeList{
struct freeList *next;
};
static struct freeList *freeHead=NULL;
/* Task delay times (seconds) */
#define TASKWD_DELAY 6.0
/*forward definitions*/
static void taskwdTask(void);
@@ -77,59 +77,59 @@ static void freeList(struct task_list *pt);
void taskwdInit()
{
FASTLOCKINIT(&lock);
FASTLOCKINIT(&anylock);
FASTLOCKINIT(&alloclock);
lock = semMutexCreate();
anylock = semMutexCreate();
alloclock = semMutexCreate();
ellInit(&list);
ellInit(&anylist);
taskwdid = taskSpawn(TASKWD_NAME,TASKWD_PRI,
TASKWD_OPT,TASKWD_STACK,(FUNCPTR )taskwdTask,
0,0,0,0,0,0,0,0,0,0);
taskwdid = threadCreate(
"taskwd",threadPriorityLow,threadGetStackSize(threadStackSmall),
(THREADFUNC)taskwdTask,0);
}
void taskwdInsert(int tid,VOIDFUNCPTR callback,void *arg)
void taskwdInsert(threadId tid,VOIDFUNCPTR callback,void *arg)
{
struct task_list *pt;
FASTLOCK(&lock);
semMutexTakeAssert(lock);
pt = allocList();
ellAdd(&list,(void *)pt);
pt->suspended = FALSE;
pt->id.tid = tid;
pt->callback = callback;
pt->arg = arg;
FASTUNLOCK(&lock);
semMutexGive(lock);
}
void taskwdAnyInsert(void *userpvt,VOIDFUNCPTR callback,void *arg)
{
struct task_list *pt;
FASTLOCK(&anylock);
semMutexTakeAssert(anylock);
pt = allocList();
ellAdd(&anylist,(void *)pt);
pt->id.userpvt = userpvt;
pt->callback = callback;
pt->arg = arg;
FASTUNLOCK(&anylock);
semMutexGive(anylock);
}
void taskwdRemove(int tid)
void taskwdRemove(threadId tid)
{
struct task_list *pt;
FASTLOCK(&lock);
semMutexTakeAssert(lock);
pt = (struct task_list *)ellFirst(&list);
while(pt!=NULL) {
if (tid == pt->id.tid) {
ellDelete(&list,(void *)pt);
freeList(pt);
FASTUNLOCK(&lock);
semMutexGive(lock);
return;
}
pt = (struct task_list *)ellNext((ELLNODE *)pt);
}
FASTUNLOCK(&lock);
semMutexGive(lock);
errMessage(-1,"taskwdRemove failed");
}
@@ -137,18 +137,18 @@ void taskwdAnyRemove(void *userpvt)
{
struct task_list *pt;
FASTLOCK(&anylock);
semMutexTakeAssert(anylock);
pt = (struct task_list *)ellFirst(&anylist);
while(pt!=NULL) {
if (userpvt == pt->id.userpvt) {
ellDelete(&anylist,(void *)pt);
freeList(pt);
FASTUNLOCK(&anylock);
semMutexGive(anylock);
return;
}
pt = (struct task_list *)ellNext((void *)pt);
}
FASTUNLOCK(&anylock);
semMutexGive(anylock);
errMessage(-1,"taskwdanyRemove failed");
}
@@ -158,20 +158,20 @@ static void taskwdTask(void)
while(TRUE) {
if(taskwdOn) {
FASTLOCK(&lock);
semMutexTakeAssert(lock);
pt = (struct task_list *)ellFirst(&list);
while(pt) {
next = (struct task_list *)ellNext((void *)pt);
if(taskIsSuspended(pt->id.tid)) {
char *pname;
if(threadIsSuspended(pt->id.tid)) {
const char *pname;
char message[100];
pname = taskName(pt->id.tid);
pname = threadGetName(pt->id.tid);
if(!pt->suspended) {
struct task_list *ptany;
pt->suspended = TRUE;
sprintf(message,"task %x %s suspended",pt->id.tid,pname);
sprintf(message,"task %s suspended",pname);
errMessage(-1,message);
ptany = (struct task_list *)ellFirst(&anylist);
while(ptany) {
@@ -183,7 +183,7 @@ static void taskwdTask(void)
void *arg = pt->arg;
/*Must allow callback to call taskwdRemove*/
FASTUNLOCK(&lock);
semMutexGive(lock);
(pcallback)(arg);
/*skip rest because we have unlocked*/
break;
@@ -194,9 +194,9 @@ static void taskwdTask(void)
}
pt = next;
}
FASTUNLOCK(&lock);
semMutexGive(lock);
}
taskDelay(TASKWD_DELAY*vxTicksPerSecond);
threadSleep(TASKWD_DELAY);
}
}
@@ -205,7 +205,7 @@ static struct task_list *allocList(void)
{
struct task_list *pt;
FASTLOCK(&alloclock);
semMutexTakeAssert(alloclock);
if(freeHead) {
pt = (struct task_list *)freeHead;
freeHead = freeHead->next;
@@ -214,15 +214,15 @@ static struct task_list *allocList(void)
errMessage(0,"taskwd failed on call to calloc\n");
exit(1);
}
FASTUNLOCK(&alloclock);
semMutexGive(alloclock);
return(pt);
}
static void freeList(struct task_list *pt)
{
FASTLOCK(&alloclock);
semMutexTakeAssert(alloclock);
((struct freeList *)pt)->next = freeHead;
freeHead = (struct freeList *)pt;
FASTUNLOCK(&alloclock);
semMutexGive(alloclock);
}

View File

@@ -35,11 +35,13 @@
#ifndef INCtaskwdh
#define INCtaskwdh 1
#include "osiThread.h"
#ifdef __STDC__
void taskwdInit();
void taskwdInsert(int tid, VOIDFUNCPTR callback,void *arg);
void taskwdInsert(threadId tid, VOIDFUNCPTR callback,void *arg);
void taskwdAnyInsert(void *userpvt, VOIDFUNCPTR callback,void *arg);
void taskwdRemove(int tid);
void taskwdRemove(threadId tid);
void taskwdAnyRemove(void *userpvt);
#else
void taskwdInit();

View File

@@ -1,7 +1,46 @@
TOP=../..
include $(TOP)/config/CONFIG_BASE
include $(TOP)/configure/CONFIG
include $(TOP)/config/RULES_ARCHS
# includes to install from this sub-project
#
INC += alarm.h alarmString.h dbBase.h dbFldTypes.h
INC += dbStaticLib.h link.h special.h guigroup.h
# Sources to compile & put into lib:
#
LIBSRCS := dbStaticLib.c dbYacc.c dbPvdLib.c dbStaticNoRun.c
# Library to build:
#
LIBRARY := Db
# Products to build:
#
PROD := dbReadTest dbExpand dbToMenuH dbToRecordtypeH
# libs needed by PROD:
#
PROD_LIBS := Db Com Osi
#====================================================
dbStaticLib_SRCS = \
dbYacc.c\
dbPvdLib.c\
dbStaticRun.c\
dbStaticLib.c
IOC_LIBRARY_vxWorks = dbStaticLib
#====================================================
include $(TOP)/configure/RULES_BUILD
# Extra rule since dbLexRoutines.c is included in dbYacc.c
dbYacc$(OBJ): dbLex.c ../dbLexRoutines.c
clean::
@$(RM) dbLex.c dbYacc.c
# EOF Makefile.Host for base/src/dbStatic

View File

@@ -1,37 +0,0 @@
# Makefile.Host for base/src/dbStatic
#
#
TOP = ../../..
include $(TOP)/config/CONFIG_BASE
# includes to install from this sub-project
#
INC += alarm.h alarmString.h dbBase.h dbFldTypes.h
INC += dbStaticLib.h link.h special.h guigroup.h
# Sources to compile & put into lib:
#
LIBSRCS := dbStaticLib.c dbYacc.c dbPvdLib.c dbStaticNoRun.c
# Library to build:
#
LIBRARY := Db
# Products to build:
#
PROD := dbReadTest dbExpand dbToMenuH dbToRecordtypeH
# libs needed by PROD:
#
PROD_LIBS := Db Com
include $(TOP)/config/RULES.Host
# Extra rule since dbLexRoutines.c is included in dbYacc.c
dbYacc$(OBJ): dbLex.c ../dbLexRoutines.c
clean::
@$(RM) dbLex.c dbYacc.c
# EOF Makefile.Host for base/src/dbStatic

View File

@@ -1,29 +0,0 @@
TOP = ../../..
include $(TOP)/config/CONFIG_BASE
SRCS.c = \
dbYacc.c \
../dbPvdLib.c\
../dbStaticRun.c\
../dbStaticLib.c
OBJSdbLib = \
dbYacc.o\
dbPvdLib.o\
dbStaticRun.o\
dbStaticLib.o
PROD = dbStaticLib
include $(TOP)/config/RULES.Vx
# Extra rule since dbLexRoutines.c is included in dbYacc.c
dbYacc.o: dbLex.c ../dbLexRoutines.c
clean::
@$(RM) dbLex.c dbYacc.c
dbStaticLib: $(OBJSdbLib)
$(RM) $@
$(LINK.c) $@ $(OBJSdbLib) $(LDLIBS)

View File

@@ -34,6 +34,9 @@
* .02 08-11-92 jba added new status DISABLE_ALARM, SIMM_ALARM
* .03 05-11-94 jba added new status READ_ACCESS_ALARM, WRITE_ACCESS_ALARM
* $Log$
* Revision 1.3 1998/03/12 20:43:35 jhill
* fixed string defs
*
* Revision 1.2 1996/06/19 19:59:31 jhill
* added missing defines/enums, corrected defines
*
@@ -43,8 +46,8 @@
#ifndef INCalarmh
#define INCalarmh 1
#include <shareLib.h>
#include <epicsTypes.h>
#include "shareLib.h"
#include "epicsTypes.h"
/* defines for the choice fields */
/* ALARM SEVERITIES - NOTE: must match defs in choiceGbl.ascii GBL_ALARM_SEV */

View File

@@ -34,9 +34,9 @@
#ifndef INCdbBaseh
#define INCdbBaseh 1
#include <dbFldTypes.h>
#include <ellLib.h>
#include <dbDefs.h>
#include "dbFldTypes.h"
#include "ellLib.h"
#include "dbDefs.h"
typedef struct dbMenu {
ELLNODE node;

View File

@@ -19,9 +19,6 @@ of this distribution.
/*The routines in this module are serially reusable NOT reentrant*/
#ifdef vxWorks
#include <vxWorks.h>
#endif
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
@@ -668,7 +665,6 @@ static void dbRecordtypeBody(void)
pgphentry->userPvt = pdbRecordType;
}
ellAdd(&pdbbase->recordTypeList,&pdbRecordType->node);
dbGetRecordtypeSizeOffset(pdbRecordType);
}
static void dbDevice(char *recordtype,char *linktype,

View File

@@ -9,10 +9,7 @@ This software was developed under a United States Government license
described on the COPYRIGHT_UniversityOfChicago file included as part
of this distribution.
**********************************************************************/
#ifdef vxWorks
#include <vxWorks.h>
#include <taskLib.h>
#endif
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

View File

@@ -19,10 +19,6 @@ of this distribution.
* .03 02-23-94 mrk dbPutString to DEV_CHOICE. Ok if no INP or OUT
*/
#ifdef vxWorks
#include <vxWorks.h>
#include <taskLib.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
@@ -30,6 +26,7 @@ of this distribution.
#include <math.h>
#include <ctype.h>
#include "cantProceed.h"
#define DBFLDTYPES_GBLSOURCE
#define GUIGROUPS_GBLSOURCE
#define SPECIAL_GBLSOURCE
@@ -527,29 +524,15 @@ void * epicsShareAPI dbCalloc(size_t nobj,size_t size)
{
void *p;
p=calloc(nobj,size);
if(p) return(p);
printf("dbCalloc: Can't allocate memory\n");
#ifdef vxWorks
taskSuspend(0);
#else
abort();
#endif
return(NULL);
p=callocMustSucceed(nobj,size,"dbCalloc");
return(p);
}
void * epicsShareAPI dbMalloc(size_t size)
{
void *p;
p=malloc(size);
if(p) return(p);
printf("dbMalloc: Can't allocate memory\n");
#ifdef vxWorks
taskSuspend(0);
#else
abort();
#endif
return(NULL);
p=mallocMustSucceed(size,"dbMalloc");
return(p);
}
#define INC_SIZE 256
@@ -2096,7 +2079,7 @@ long epicsShareAPI dbPutString(DBENTRY *pdbentry,char *pstring)
status = putPvLink(pdbentry,ppOpt|msOpt,pstr);
goto done;
}
break;
/*break; is unnecessary*/
case VME_IO: {
char *end;

View File

@@ -314,11 +314,6 @@ long dbPutStringNum(DBENTRY *pdbentry,char *pstring)
return(0);
}
void dbGetRecordtypeSizeOffset(dbRecordType *pdbRecordType)
{ /*For no run cant and dont need to set size and offset*/
return;
}
int epicsShareAPI dbGetMenuIndex(DBENTRY *pdbentry)
{
dbFldDes *pflddes = pdbentry->pflddes;

View File

@@ -48,8 +48,6 @@ char *dbRecordName(DBENTRY *pdbentry);
char *dbGetStringNum(DBENTRY *pdbentry);
long dbPutStringNum(DBENTRY *pdbentry,char *pstring);
void dbGetRecordtypeSizeOffset(dbRecordType *pdbRecordType);
/* The following is for path */
typedef struct dbPathNode {
ELLNODE node;

View File

@@ -15,20 +15,17 @@ of this distribution.
* .01 06-12-95 mrk Initial
*/
#ifdef vxWorks
#include <vxWorks.h>
#include <taskLib.h>
#endif
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <string.h>
#include <math.h>
#include <symLib.h>
#include <sysSymTbl.h> /* for sysSymTbl*/
#include "dbDefs.h"
#include "errMdef.h"
#include "dbBase.h"
#include "registryRecordType.h"
#include "epicsPrint.h"
#include "ellLib.h"
#include "dbDefs.h"
@@ -648,24 +645,3 @@ long dbPutMenuIndex(DBENTRY *pdbentry,int index)
}
return (S_dbLib_badField);
}
void dbGetRecordtypeSizeOffset(dbRecordType *pdbRecordType)
{
char name[60];
SYM_TYPE type;
STATUS vxstatus;
long status;
int (*sizeOffset)(dbRecordType *pdbRecordType);
strcpy(name,"_");
strcat(name,pdbRecordType->name);
strcat(name,"RecordSizeOffset");
vxstatus = symFindByNameEPICS(sysSymTbl, name,
(void *)&sizeOffset, &type);
if (vxstatus != OK) {
status = S_dbLib_noSizeOffset;
errPrintf(status,__FILE__,__LINE__,"%s",name);
return;
}
sizeOffset(pdbRecordType);
}

View File

@@ -112,10 +112,8 @@ int main(int argc,char **argv)
fprintf(stderr,"Terminal error For input file %s\n",argv[1]);
exit(-1);
}
fprintf(outFile,"#include <vxWorks.h>\n");
fprintf(outFile,"#include <semLib.h>\n");
fprintf(outFile,"#include \"ellLib.h\"\n");
fprintf(outFile,"#include \"fast_lock.h\"\n");
fprintf(outFile,"#include \"osiSem.h\"\n");
fprintf(outFile,"#include \"link.h\"\n");
fprintf(outFile,"#include \"tsDefs.h\"\n");
pdbMenu = (dbMenu *)ellFirst(&pdbbase->menuList);

View File

@@ -37,7 +37,7 @@
* .06 01-10-96 lrd added ca_link structure fields
*/
#include <dbDefs.h>
#include "dbDefs.h"
#ifndef INClinkh
#define INClinkh 1