Compare commits
46 Commits
R3.12.0-be
...
R3.12.0-be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0d1a39c57 | ||
|
|
622c4f8382 | ||
|
|
da47b297d2 | ||
|
|
53b2a77378 | ||
|
|
81de80789c | ||
|
|
d32a6bb770 | ||
|
|
5d341aed37 | ||
|
|
3fee3eceff | ||
|
|
ded5d21444 | ||
|
|
02310d0bd4 | ||
|
|
2fb0212252 | ||
|
|
2e16f3a6d7 | ||
|
|
47fa7a4fa4 | ||
|
|
0a1c03c8d4 | ||
|
|
8815ca1008 | ||
|
|
c1b65bad02 | ||
|
|
a8c8dc89d9 | ||
|
|
3ce0670ba8 | ||
|
|
bc89526dff | ||
|
|
1c7a4ef3db | ||
|
|
a7333f554d | ||
|
|
c2484d675b | ||
|
|
589ccacc3d | ||
|
|
9d3ce3aedd | ||
|
|
a88293bbbb | ||
|
|
46e1cdf441 | ||
|
|
1a826583e7 | ||
|
|
99434dfe06 | ||
|
|
5db7f418d4 | ||
|
|
70e2716ff0 | ||
|
|
51eb05d411 | ||
|
|
754dd841eb | ||
|
|
f2d167920c | ||
|
|
4ae4145b9e | ||
|
|
d453191f25 | ||
|
|
0c2699c85b | ||
|
|
ea9d141a54 | ||
|
|
7bb451bb74 | ||
|
|
0ba3898e81 | ||
|
|
547ca9d02d | ||
|
|
348f4c0e8d | ||
|
|
2fddb398b2 | ||
|
|
688f766622 | ||
|
|
c0892857eb | ||
|
|
a1458c0c58 | ||
|
|
15d6708cec |
44
Makefile
44
Makefile
@@ -1,5 +1,4 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Top Level EPICS Makefile
|
||||
# by Matthew Needes and Mike Bordua
|
||||
@@ -13,8 +12,8 @@
|
||||
# install because the release.% syntax is illegal.
|
||||
#
|
||||
# $Log$
|
||||
# Revision 1.19 1994/10/31 21:47:02 jba
|
||||
# Removed depends dependancy in release and built_release rules
|
||||
# Revision 1.1.1.1 1994/11/09 01:08:53 epics
|
||||
# Import of R3.12.0Beta
|
||||
#
|
||||
# Revision 1.18 1994/10/13 19:44:34 mda
|
||||
# Introduce temporary symbol (ARCH_TYPE=$$ARCH) and use in later targets/rules
|
||||
@@ -72,7 +71,7 @@ depends:
|
||||
${MAKE} ${MFLAGS} $@.$$ARCH; \
|
||||
done)
|
||||
|
||||
release:
|
||||
release:
|
||||
@echo TOP: Creating Release...
|
||||
@tools/MakeRelease
|
||||
|
||||
@@ -85,8 +84,8 @@ clean:
|
||||
@tools/Clean
|
||||
|
||||
uninstall:
|
||||
@rm -rf bin/* lib/* rec.bak
|
||||
@rm -f rec/default.dctsdr rec/default.sdrSum rec/*.h
|
||||
rm -rf bin/* lib/* rec.bak
|
||||
rm -f rec/default.dctsdr rec/default.sdrSum rec/*.h
|
||||
|
||||
# Notes for single architecture build rules:
|
||||
# CheckArch only has to be run for dirs.% . That
|
||||
@@ -106,25 +105,21 @@ uninstall:
|
||||
# basis.
|
||||
|
||||
dirs.%:
|
||||
@tools/CheckArch $(ARCH_TYPE)
|
||||
@echo $(ARCH_TYPE): Creating Directories
|
||||
@tools/MakeDirs $(ARCH_TYPE)
|
||||
@tools/CheckArch $*
|
||||
@echo $*: Creating Directories
|
||||
@tools/MakeDirs $*
|
||||
|
||||
build.%: dirs.%
|
||||
@echo $(ARCH_TYPE): Building
|
||||
@${MAKE} ${MFLAGS} T_A=$(ARCH_TYPE) -f Makefile.subdirs build
|
||||
@echo $*: Building
|
||||
@${MAKE} ${MFLAGS} T_A=$* -f Makefile.subdirs build
|
||||
|
||||
install.%: dirs.%
|
||||
@echo $(ARCH_TYPE): Installing
|
||||
@${MAKE} ${MFLAGS} T_A=$(ARCH_TYPE) -f Makefile.subdirs install
|
||||
@echo $*: Installing
|
||||
@${MAKE} ${MFLAGS} T_A=$* -f Makefile.subdirs install
|
||||
|
||||
depends.%: dirs.%
|
||||
@echo $(ARCH_TYPE): Performing Make Depends
|
||||
@${MAKE} ${MFLAGS} T_A=$(ARCH_TYPE) -f Makefile.subdirs depends
|
||||
|
||||
clean.%: dirs.%
|
||||
@echo $(ARCH_TYPE): Cleaning
|
||||
@${MAKE} ${MFLAGS} T_A=$(ARCH_TYPE) -f Makefile.subdirs clean
|
||||
@echo $*: Performing Make Depends
|
||||
@${MAKE} ${MFLAGS} T_A=$* -f Makefile.subdirs depends
|
||||
|
||||
# Illegal Syntax
|
||||
|
||||
@@ -138,15 +133,8 @@ uninstall.%:
|
||||
@echo
|
||||
@echo "The uninstall.arch syntax is not supported by this build."
|
||||
@echo
|
||||
|
||||
|
||||
# Clean RULE syntax: make clean.arch
|
||||
# e.g.: make clean.mv167
|
||||
#
|
||||
# Clean files for a particular architecture
|
||||
#
|
||||
|
||||
clean.%:
|
||||
@echo "$(ARCH_TYPE): Cleaning"
|
||||
@tools/Clean $(ARCH_TYPE)
|
||||
@echo "$*: Cleaning"
|
||||
@tools/Clean $*
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# supplement README for HP700 and Alpha OSF/1 builds
|
||||
#
|
||||
#
|
||||
# M. Anderson and J. Tang
|
||||
|
||||
|
||||
- EPICS environment variable - set by hand prior to build
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
For example:
|
||||
|
||||
% make HOST_ARCH=alpha
|
||||
% make HOST_ARCH=hp700
|
||||
|
||||
|
||||
Also, directory permissions may not be correct across multiple machines,
|
||||
@@ -41,3 +41,5 @@
|
||||
% chmod -R ugo+rw base extensions
|
||||
|
||||
might be necessary.
|
||||
|
||||
- bsdinstall is written to replace install for hp.
|
||||
|
||||
@@ -14,18 +14,24 @@ SRCS.c = \
|
||||
../iocinf.c ../access.c ../test_event.c ../service.c \
|
||||
../flow_control.c ../repeater.c ../conn.c ../acctst.c \
|
||||
../syncgrp.c ../if_depen.c ../netdb_depen.c ../bsd_depen.c \
|
||||
../gsd_sync_subr.c ../posix_depen.c ../caRepeater.c
|
||||
../posix_depen.c ../caRepeater.c ../acctst.c
|
||||
|
||||
OBJS = caRepeater.o
|
||||
OBJS = caRepeater.o
|
||||
|
||||
LIBOBJS = \
|
||||
iocinf.o access.o test_event.o service.o flow_control.o repeater.o \
|
||||
conn.o syncgrp.o if_depen.o netdb_depen.o \
|
||||
gsd_sync_subr.o bsd_depen.o posix_depen.o
|
||||
bsd_depen.o posix_depen.o
|
||||
|
||||
LIBNAME = libca.a
|
||||
|
||||
PROD = caRepeater
|
||||
PROD = caRepeater
|
||||
|
||||
|
||||
include $(EPICS)/config/RULES.Unix
|
||||
|
||||
acctst: acctst.o $(DEPLIBS_BASE)/libCom.a libca.a
|
||||
|
||||
acctst.o: ../acctst.c
|
||||
$(COMPILE.c) $<
|
||||
|
||||
|
||||
@@ -7,13 +7,13 @@ USR_CFLAGS = -DACCESS_SECURITY -D_NO_PROTO
|
||||
SRCS.c = \
|
||||
../iocinf.c ../access.c ../test_event.c ../service.c \
|
||||
../flow_control.c ../repeater.c ../conn.c ../syncgrp.c \
|
||||
../if_depen.c ../bsd_depen.c ../vxWorks_depen.c
|
||||
../if_depen.c ../bsd_depen.c ../vxWorks_depen.c ../acctst.c
|
||||
|
||||
OBJS = \
|
||||
iocinf.o access.o test_event.o service.o flow_control.o \
|
||||
repeater.o conn.o syncgrp.o if_depen.o bsd_depen.o vxWorks_depen.o
|
||||
repeater.o conn.o syncgrp.o if_depen.o bsd_depen.o vxWorks_depen.o
|
||||
|
||||
PROD = caLib
|
||||
PROD = caLib
|
||||
|
||||
include $(EPICS)/config/RULES.Vx
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
static char *sccsId = "$Id$";
|
||||
static char *sccsId = "@(#)V5_vxWorks_patch.c 1.2\t7/27/92";
|
||||
|
||||
#include <taskLib.h>
|
||||
#include <taskVarLib.h>
|
||||
|
||||
1028
src/ca/access.c
1028
src/ca/access.c
File diff suppressed because it is too large
Load Diff
@@ -3,8 +3,11 @@
|
||||
* CA test/debug routine
|
||||
*/
|
||||
|
||||
static char *sccsId = "$Id$";
|
||||
static char *sccsId = "@(#) $Id$";
|
||||
|
||||
#ifdef VMS
|
||||
#include <LIB$ROUTINES.H>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
@@ -52,9 +55,7 @@ int acctst(char *pname)
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
#endif /*vxWorks*/
|
||||
|
||||
#if defined(UNIX) || defined(VMS)
|
||||
#else /* not vxWorks */
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
if(argc == 2){
|
||||
@@ -65,7 +66,7 @@ main(int argc, char **argv)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* UNIX or VMS */
|
||||
#endif /*vxWorks*/
|
||||
|
||||
|
||||
int doacctst(char *pname)
|
||||
@@ -121,17 +122,17 @@ int doacctst(char *pname)
|
||||
NULL);
|
||||
SEVCHK(status, NULL);
|
||||
|
||||
assert(INVALID_DB_REQ(chix1->type) == TRUE);
|
||||
assert(INVALID_DB_REQ(chix2->type) == TRUE);
|
||||
assert(INVALID_DB_REQ(chix3->type) == TRUE);
|
||||
assert(INVALID_DB_REQ(chix4->type) == TRUE);
|
||||
if (ca_test_io() == ECA_IOINPROGRESS) {
|
||||
assert(INVALID_DB_REQ(chix1->type) == TRUE);
|
||||
assert(INVALID_DB_REQ(chix2->type) == TRUE);
|
||||
assert(INVALID_DB_REQ(chix3->type) == TRUE);
|
||||
assert(INVALID_DB_REQ(chix4->type) == TRUE);
|
||||
|
||||
assert(ca_state(chix1) == cs_never_conn);
|
||||
assert(ca_state(chix2) == cs_never_conn);
|
||||
assert(ca_state(chix3) == cs_never_conn);
|
||||
assert(ca_state(chix4) == cs_never_conn);
|
||||
|
||||
assert(ca_test_io() == ECA_IOINPROGRESS);
|
||||
assert(ca_state(chix1) == cs_never_conn);
|
||||
assert(ca_state(chix2) == cs_never_conn);
|
||||
assert(ca_state(chix3) == cs_never_conn);
|
||||
assert(ca_state(chix4) == cs_never_conn);
|
||||
}
|
||||
|
||||
status = ca_pend_io(1000.0);
|
||||
SEVCHK(status, NULL);
|
||||
@@ -244,9 +245,7 @@ int doacctst(char *pname)
|
||||
float temp;
|
||||
|
||||
printf("Performing multiple get test...");
|
||||
#ifdef UNIX
|
||||
fflush(stdout);
|
||||
#endif /*UNIX*/
|
||||
for(i=0; i<10000; i++){
|
||||
SEVCHK(ca_get(DBR_FLOAT, chix4, &temp),NULL);
|
||||
}
|
||||
@@ -262,9 +261,7 @@ int doacctst(char *pname)
|
||||
*/
|
||||
if(ca_write_access(chix4)){
|
||||
printf("Performing multiple put test...");
|
||||
#ifdef UNIX
|
||||
fflush(stdout);
|
||||
#endif /*UNIX*/
|
||||
for(i=0; i<10000; i++){
|
||||
double fval = 3.3;
|
||||
status = ca_put(DBR_DOUBLE, chix4, &fval);
|
||||
@@ -283,9 +280,7 @@ int doacctst(char *pname)
|
||||
*/
|
||||
if(ca_read_access(chix1)){
|
||||
printf("Performing multiple get callback test...");
|
||||
#ifdef UNIX
|
||||
fflush(stdout);
|
||||
#endif /*UNIX*/
|
||||
for(i=0; i<10000; i++){
|
||||
status = ca_array_get_callback(
|
||||
DBR_FLOAT,
|
||||
@@ -303,17 +298,18 @@ int doacctst(char *pname)
|
||||
printf("Skipped multiple get cb test - no read access\n");
|
||||
}
|
||||
|
||||
test_sync_groups(chix1);
|
||||
|
||||
if(ca_v42_ok(chix1)){
|
||||
test_sync_groups(chix1);
|
||||
}
|
||||
|
||||
/*
|
||||
* verify we dont jam up on many uninterrupted
|
||||
* solicitations
|
||||
*/
|
||||
if(ca_write_access(chix1)){
|
||||
if(ca_write_access(chix1) && ca_v42_ok(chix1)){
|
||||
printf("Performing multiple put callback test...");
|
||||
#ifdef UNIX
|
||||
fflush(stdout);
|
||||
#endif /*UNIX*/
|
||||
for(i=0; i<10000; i++){
|
||||
float fval = 3.3;
|
||||
status = ca_array_put_callback(
|
||||
@@ -337,9 +333,7 @@ int doacctst(char *pname)
|
||||
* verify we can add many monitors at once
|
||||
*/
|
||||
printf("Performing multiple monitor test...");
|
||||
#ifdef UNIX
|
||||
fflush(stdout);
|
||||
#endif /*UNIX*/
|
||||
{
|
||||
evid mid[1000];
|
||||
float temp;
|
||||
@@ -361,7 +355,7 @@ int doacctst(char *pname)
|
||||
printf(
|
||||
"Clear of event %d %x failed because \"%s\"\n",
|
||||
i,
|
||||
mid[i],
|
||||
mid[i]->id,
|
||||
ca_message(status));
|
||||
}
|
||||
SEVCHK(status,NULL);
|
||||
@@ -468,14 +462,19 @@ int doacctst(char *pname)
|
||||
printf("GR Float value Returned from put/get %f\n", pgrfloat[i].value);
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (i = 0; i < 10; i++)
|
||||
ca_get_callback(DBR_GR_FLOAT, chix1, ca_test_event, NULL);
|
||||
#endif
|
||||
|
||||
|
||||
SEVCHK(ca_modify_user_name("Willma"), NULL);
|
||||
SEVCHK(ca_modify_host_name("Bed Rock"), NULL);
|
||||
|
||||
assert(conn_get_cb_count == 3);
|
||||
if (conn_get_cb_count != 3){
|
||||
printf ("!!!! Connect cb count = %d expected = 3 !!!!\n",
|
||||
conn_get_cb_count);
|
||||
}
|
||||
|
||||
printf("-- Put/Gets done- waiting for Events --\n");
|
||||
status = ca_pend_event(10.0);
|
||||
@@ -501,7 +500,7 @@ void null_event(struct event_handler_args args)
|
||||
static int i;
|
||||
|
||||
if (i++ > 1000) {
|
||||
printf("1000 occured\n");
|
||||
printf("1000 occurred\n");
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
@@ -555,9 +554,7 @@ void test_sync_groups(chid chix)
|
||||
CA_SYNC_GID gid2;
|
||||
|
||||
printf("Performing sync group test...");
|
||||
#ifdef UNIX
|
||||
fflush(stdout);
|
||||
#endif /*UNIX*/
|
||||
|
||||
status = ca_sg_create(&gid1);
|
||||
SEVCHK(status, NULL);
|
||||
|
||||
@@ -1,6 +1,24 @@
|
||||
|
||||
#include <envDefs.h>
|
||||
|
||||
void caSetupAddrList(
|
||||
ELLLIST *pList,
|
||||
SOCKET socket);
|
||||
|
||||
void caPrintAddrList();
|
||||
|
||||
void caDiscoverInterfaces(
|
||||
ELLLIST *pList,
|
||||
SOCKET socket,
|
||||
int port);
|
||||
|
||||
void caAddConfiguredAddr(
|
||||
ELLLIST *pList,
|
||||
ENV_PARAM *pEnv,
|
||||
SOCKET socket,
|
||||
int port);
|
||||
|
||||
int local_addr(SOCKET socket, struct sockaddr_in *plcladdr);
|
||||
|
||||
|
||||
union caAddr{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id$
|
||||
* $Id$
|
||||
* Author: Jeffrey O. Hill
|
||||
* hill@luke.lanl.gov
|
||||
* (505) 665 1831
|
||||
@@ -36,23 +36,41 @@
|
||||
|
||||
/*
|
||||
* cac_select_io()
|
||||
*
|
||||
* NOTE: on multithreaded systems this assumes that the
|
||||
* local implementation of select is reentrant
|
||||
*/
|
||||
int cac_select_io(struct timeval *ptimeout, int flags)
|
||||
{
|
||||
long status;
|
||||
IIU *piiu;
|
||||
unsigned long minfreespace;
|
||||
unsigned long freespace;
|
||||
int maxfd;
|
||||
caFDInfo *pfdi;
|
||||
|
||||
LOCK;
|
||||
pfdi = (caFDInfo *) ellGet(&ca_static->fdInfoFreeList);
|
||||
|
||||
if (!pfdi) {
|
||||
pfdi = (caFDInfo *) calloc (1, sizeof(*pfdi));
|
||||
if (!pfdi) {
|
||||
ca_printf("CAC: no mem for select ctx?\n");
|
||||
UNLOCK;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ellAdd (&ca_static->fdInfoList, &pfdi->node);
|
||||
UNLOCK;
|
||||
|
||||
FD_ZERO (&pfdi->readMask);
|
||||
FD_ZERO (&pfdi->writeMask);
|
||||
|
||||
maxfd = 0;
|
||||
for( piiu=(IIU *)iiuList.node.next;
|
||||
for( piiu = (IIU *) iiuList.node.next;
|
||||
piiu;
|
||||
piiu=(IIU *)piiu->node.next){
|
||||
piiu = (IIU *) piiu->node.next) {
|
||||
|
||||
if(!piiu->conn_up){
|
||||
if (!piiu->conn_up) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -60,30 +78,24 @@ int cac_select_io(struct timeval *ptimeout, int flags)
|
||||
* Dont bother receiving if we have insufficient
|
||||
* space for the maximum UDP message
|
||||
*/
|
||||
if(flags&CA_DO_RECVS){
|
||||
freespace = cacRingBufferWriteSize(&piiu->recv, TRUE);
|
||||
if(piiu->sock_proto == IPPROTO_UDP){
|
||||
minfreespace =
|
||||
MAX_UDP+2*sizeof(struct udpmsglog);
|
||||
}
|
||||
else{
|
||||
minfreespace = 1;
|
||||
}
|
||||
|
||||
if(freespace>=minfreespace){
|
||||
maxfd = max(maxfd,piiu->sock_chan);
|
||||
FD_SET(piiu->sock_chan,&readch);
|
||||
if (flags&CA_DO_RECVS) {
|
||||
freespace = cacRingBufferWriteSize (&piiu->recv, TRUE);
|
||||
if (freespace>=piiu->minfreespace) {
|
||||
maxfd = max (maxfd,piiu->sock_chan);
|
||||
FD_SET (piiu->sock_chan, &pfdi->readMask);
|
||||
}
|
||||
}
|
||||
|
||||
if(flags&CA_DO_SENDS){
|
||||
if(cacRingBufferReadSize(&piiu->send, FALSE)>0){
|
||||
maxfd = max(maxfd,piiu->sock_chan);
|
||||
FD_SET(piiu->sock_chan,&writech);
|
||||
if (flags&CA_DO_SENDS) {
|
||||
if (cacRingBufferReadSize(&piiu->send, FALSE)>0) {
|
||||
maxfd = max (maxfd,piiu->sock_chan);
|
||||
FD_SET (piiu->sock_chan, &pfdi->writeMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
UNLOCK;
|
||||
|
||||
pfdi->writeSave = pfdi->writeMask;
|
||||
pfdi->readSave = pfdi->readMask;
|
||||
|
||||
#if 0
|
||||
printf( "max fd=%d tv_usec=%d tv_sec=%d\n",
|
||||
@@ -93,52 +105,64 @@ printf( "max fd=%d tv_usec=%d tv_sec=%d\n",
|
||||
#endif
|
||||
status = select(
|
||||
maxfd+1,
|
||||
&readch,
|
||||
&writech,
|
||||
&pfdi->readMask,
|
||||
&pfdi->writeMask,
|
||||
NULL,
|
||||
ptimeout);
|
||||
|
||||
#if 0
|
||||
printf("leaving select stat=%d errno=%d \n", status, MYERRNO);
|
||||
#endif
|
||||
if(status<0){
|
||||
if(MYERRNO == EINTR){
|
||||
if (status<0) {
|
||||
if (MYERRNO == EINTR) {
|
||||
}
|
||||
else if(MYERRNO == EWOULDBLOCK){
|
||||
else if (MYERRNO == EWOULDBLOCK) {
|
||||
ca_printf("CAC: blocked at select ?\n");
|
||||
}
|
||||
else{
|
||||
ca_printf(
|
||||
else if (MYERRNO == ESRCH) {
|
||||
}
|
||||
else {
|
||||
ca_printf (
|
||||
"CAC: unexpected select fail: %s\n",
|
||||
strerror(MYERRNO));
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
LOCK;
|
||||
if(status>0){
|
||||
for( piiu=(IIU *)iiuList.node.next;
|
||||
LOCK;
|
||||
if (status>0) {
|
||||
for ( piiu = (IIU *) iiuList.node.next;
|
||||
piiu;
|
||||
piiu=(IIU *)piiu->node.next){
|
||||
piiu = (IIU *) piiu->node.next) {
|
||||
|
||||
if(!piiu->conn_up){
|
||||
if (!piiu->conn_up) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(flags&CA_DO_SENDS &&
|
||||
FD_ISSET(piiu->sock_chan,&writech)){
|
||||
if (FD_ISSET(piiu->sock_chan,&pfdi->writeMask)) {
|
||||
(*piiu->sendBytes)(piiu);
|
||||
}
|
||||
|
||||
if(flags&CA_DO_RECVS &&
|
||||
FD_ISSET(piiu->sock_chan,&readch)){
|
||||
#if 0
|
||||
else{
|
||||
if (FD_ISSET(piiu->sock_chan, &pfdi->writeSave)) {
|
||||
if(FD_ISSET(piiu->sock_chan, &pfdi->readSave) &&
|
||||
!FD_ISSET(piiu->sock_chan,&pfdi->readMask)) {
|
||||
printf("Still waiting to send on %d with recv empty\n", piiu->sock_chan);
|
||||
}
|
||||
if(!FD_ISSET(piiu->sock_chan, &pfdi->readSave)){
|
||||
printf("Still waiting to send on %d with no recv wait?\n", piiu->sock_chan);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (FD_ISSET(piiu->sock_chan,&pfdi->readMask)) {
|
||||
(*piiu->recvBytes)(piiu);
|
||||
}
|
||||
|
||||
FD_CLR(piiu->sock_chan,&readch);
|
||||
FD_CLR(piiu->sock_chan,&writech);
|
||||
}
|
||||
}
|
||||
UNLOCK;
|
||||
|
||||
ellDelete (&ca_static->fdInfoList, &pfdi->node);
|
||||
ellAdd (&ca_static->fdInfoFreeList, &pfdi->node);
|
||||
UNLOCK;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
/*
|
||||
* $Id$
|
||||
* caRepeater.c
|
||||
* share/src/ca/caRepeater.c
|
||||
*
|
||||
|
||||
@@ -32,20 +32,16 @@
|
||||
/************************************************************************/
|
||||
/*_end */
|
||||
|
||||
static char *sccsId = "$Id$";
|
||||
static char *sccsId = "@(#) $Id$";
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef vxWorks
|
||||
# include <vxWorks.h>
|
||||
# include <logLib.h>
|
||||
#endif /*vxWorks*/
|
||||
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else /*__STDC__*/
|
||||
#include <varargs.h>
|
||||
#endif /*__STDC__*/
|
||||
|
||||
|
||||
/*
|
||||
@@ -65,24 +61,10 @@ va_dcl
|
||||
{
|
||||
va_list args;
|
||||
int status;
|
||||
#ifndef __STDC__
|
||||
char *pformat;
|
||||
#endif /*__STDC__*/
|
||||
|
||||
#ifdef __STDC__
|
||||
va_start(args, pformat);
|
||||
#else /*__STDC__*/
|
||||
va_start(args);
|
||||
pformat = va_arg(args, char *);
|
||||
#endif /*__STDC__*/
|
||||
|
||||
|
||||
#ifndef vxWorks
|
||||
status = vfprintf(
|
||||
stderr,
|
||||
pformat,
|
||||
args);
|
||||
#else /*vxWorks*/
|
||||
#if defined(vxWorks)
|
||||
{
|
||||
int logMsgArgs[6];
|
||||
int i;
|
||||
@@ -101,7 +83,12 @@ va_dcl
|
||||
logMsgArgs[5]);
|
||||
|
||||
}
|
||||
#endif /*vxWorks*/
|
||||
#else
|
||||
status = vfprintf(
|
||||
stderr,
|
||||
pformat,
|
||||
args);
|
||||
#endif
|
||||
|
||||
va_end(args);
|
||||
|
||||
|
||||
@@ -10,11 +10,8 @@
|
||||
|
||||
*/
|
||||
|
||||
# ifdef VMS
|
||||
lib$init_timer();
|
||||
# endif
|
||||
# ifdef VMS
|
||||
lib$show_timer();
|
||||
#ifdef VMS
|
||||
#include <LIB$ROUTINES.H>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
350
src/ca/conn.c
350
src/ca/conn.c
@@ -22,9 +22,11 @@
|
||||
/* .08 010493 joh removed `<Trying>' message */
|
||||
/* .09 090293 joh removed flush from manage_conn */
|
||||
/* (now handled by the send needed flag) */
|
||||
/* .10 102093 joh improved broadcast schedualing for */
|
||||
/* .10 102093 joh improved broadcast scheduling for */
|
||||
/* reconnects */
|
||||
/* .11 042994 joh removed client side heart beat */
|
||||
/* .12 110194 joh improved search scheduling */
|
||||
/* (dont send all chans in a block) */
|
||||
/* */
|
||||
/*_begin */
|
||||
/************************************************************************/
|
||||
@@ -39,10 +41,19 @@
|
||||
/************************************************************************/
|
||||
/*_end */
|
||||
|
||||
static char *sccsId = "$Id$";
|
||||
static char *sccsId = "@(#) $Id$";
|
||||
|
||||
#include "iocinf.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LOGRETRYINTERVAL logRetryInterval(__FILE__, __LINE__);
|
||||
#else
|
||||
#define LOGRETRYINTERVAL
|
||||
#endif
|
||||
|
||||
LOCAL void logRetryInterval(char *pFN, unsigned lineno);
|
||||
LOCAL void retrySearchRequest(int silent);
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
@@ -55,22 +66,31 @@ static char *sccsId = "$Id$";
|
||||
void manage_conn(int silent)
|
||||
{
|
||||
IIU *piiu;
|
||||
chid chix;
|
||||
unsigned int retry_cnt = 0;
|
||||
unsigned int retry_cnt_no_handler = 0;
|
||||
ca_time current;
|
||||
ca_real delay;
|
||||
unsigned long idelay;
|
||||
|
||||
current = time(NULL);
|
||||
/*
|
||||
* prevent recursion
|
||||
*/
|
||||
if(ca_static->ca_manage_conn_active){
|
||||
return;
|
||||
}
|
||||
|
||||
ca_static->ca_manage_conn_active = TRUE;
|
||||
|
||||
cac_gettimeval(¤t);
|
||||
|
||||
/*
|
||||
* issue connection heartbeat
|
||||
* (if we dont see a beacon)
|
||||
*/
|
||||
LOCK;
|
||||
for( piiu = (IIU *) iiuList.node.next;
|
||||
piiu;
|
||||
piiu = (IIU *) piiu->node.next){
|
||||
|
||||
if(piiu == piiuCast || !piiu->conn_up){
|
||||
if (piiu == piiuCast || !piiu->conn_up) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -78,8 +98,11 @@ void manage_conn(int silent)
|
||||
* mark connection for shutdown if outgoing messages
|
||||
* are not accepted by TCP/IP for several seconds
|
||||
*/
|
||||
if(piiu->sendPending){
|
||||
if((current-piiu->timeAtSendBlock)>CA_RETRY_PERIOD){
|
||||
if (piiu->sendPending) {
|
||||
delay = cac_time_diff (
|
||||
¤t,
|
||||
&piiu->timeAtSendBlock);
|
||||
if (delay>ca_static->ca_connectTMO) {
|
||||
TAG_CONN_DOWN(piiu);
|
||||
continue;
|
||||
}
|
||||
@@ -93,9 +116,14 @@ void manage_conn(int silent)
|
||||
int stmo;
|
||||
int rtmo;
|
||||
|
||||
stmo = (current-piiu->timeAtEchoRequest)
|
||||
> CA_RETRY_PERIOD;
|
||||
rtmo = (current-piiu->timeAtLastRecv)>CA_RETRY_PERIOD;
|
||||
delay = cac_time_diff (
|
||||
¤t,
|
||||
&piiu->timeAtEchoRequest);
|
||||
stmo = delay > CA_RETRY_PERIOD;
|
||||
delay = cac_time_diff (
|
||||
¤t,
|
||||
&piiu->timeAtLastRecv);
|
||||
rtmo = delay > CA_RETRY_PERIOD;
|
||||
if(stmo && rtmo && !piiu->sendPending){
|
||||
piiu->timeAtEchoRequest = current;
|
||||
noop_msg(piiu);
|
||||
@@ -104,7 +132,10 @@ void manage_conn(int silent)
|
||||
}
|
||||
|
||||
if(piiu->echoPending){
|
||||
if((current-piiu->timeAtEchoRequest)>CA_ECHO_TIMEOUT){
|
||||
delay = cac_time_diff (
|
||||
¤t,
|
||||
&piiu->timeAtEchoRequest);
|
||||
if (delay > CA_ECHO_TIMEOUT) {
|
||||
/*
|
||||
* mark connection for shutdown
|
||||
*/
|
||||
@@ -112,67 +143,208 @@ void manage_conn(int silent)
|
||||
}
|
||||
}
|
||||
else{
|
||||
int sendBytesAvailable;
|
||||
|
||||
sendBytesAvailable =
|
||||
cacRingBufferWriteSize(&piiu->send, TRUE);
|
||||
if((current-piiu->timeAtLastRecv)>CA_CONN_VERIFY_PERIOD &&
|
||||
sendBytesAvailable>sizeof(struct extmsg)){
|
||||
piiu->echoPending = TRUE;
|
||||
piiu->timeAtEchoRequest = current;
|
||||
echo_request(piiu);
|
||||
delay = cac_time_diff (
|
||||
¤t,
|
||||
&piiu->timeAtLastRecv);
|
||||
if (delay>ca_static->ca_connectTMO) {
|
||||
echo_request(piiu, ¤t);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
UNLOCK;
|
||||
|
||||
if(!piiuCast){
|
||||
/*
|
||||
* try to attach to the repeater if we havent yet
|
||||
*/
|
||||
if (!ca_static->ca_repeater_contacted) {
|
||||
delay = cac_time_diff (
|
||||
¤t,
|
||||
&ca_static->ca_last_repeater_try);
|
||||
if (delay > REPEATER_TRY_PERIOD) {
|
||||
ca_static->ca_last_repeater_try = current;
|
||||
notify_ca_repeater();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop here if there are not any disconnected channels
|
||||
*/
|
||||
if(!piiuCast) {
|
||||
ca_static->ca_manage_conn_active = FALSE;
|
||||
return;
|
||||
}
|
||||
if (piiuCast->chidlist.count == 0) {
|
||||
ca_static->ca_manage_conn_active = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
if(ca_static->ca_conn_next_retry == CA_CURRENT_TIME){
|
||||
ca_static->ca_conn_next_retry =
|
||||
current + ca_static->ca_conn_retry_delay;
|
||||
if(ca_static->ca_conn_next_retry.tv_sec == CA_CURRENT_TIME.tv_sec &&
|
||||
ca_static->ca_conn_next_retry.tv_usec == CA_CURRENT_TIME.tv_usec){
|
||||
ca_static->ca_conn_next_retry = current;
|
||||
LOGRETRYINTERVAL
|
||||
}
|
||||
|
||||
if(ca_static->ca_conn_next_retry > current)
|
||||
return;
|
||||
delay = cac_time_diff (
|
||||
&ca_static->ca_conn_next_retry,
|
||||
¤t);
|
||||
|
||||
if(ca_static->ca_conn_n_tries++ > MAXCONNTRIES)
|
||||
if (delay > 0.0) {
|
||||
ca_static->ca_manage_conn_active = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* the retry sequence number
|
||||
* (increments once all channels have received this
|
||||
* number of tries)
|
||||
*/
|
||||
if (ca_static->ca_search_retry >= MAXCONNTRIES) {
|
||||
ca_static->ca_manage_conn_active = FALSE;
|
||||
return;
|
||||
|
||||
if(ca_static->ca_conn_retry_delay<CA_RECAST_PERIOD){
|
||||
ca_static->ca_conn_retry_delay += ca_static->ca_conn_retry_delay;
|
||||
}
|
||||
ca_static->ca_conn_next_retry = current + ca_static->ca_conn_retry_delay;
|
||||
|
||||
retrySearchRequest (silent);
|
||||
|
||||
/*
|
||||
* set the retry interval
|
||||
*/
|
||||
assert(ca_static->ca_search_retry < NBBY*sizeof(idelay));
|
||||
idelay = 1;
|
||||
idelay = idelay << ca_static->ca_search_retry;
|
||||
delay = idelay * CA_RECAST_DELAY; /* sec */
|
||||
delay = min (CA_RECAST_PERIOD, delay);
|
||||
idelay = delay;
|
||||
ca_static->ca_conn_retry_delay.tv_sec = idelay;
|
||||
ca_static->ca_conn_retry_delay.tv_usec =
|
||||
(delay-idelay)*USEC_PER_SEC;
|
||||
ca_static->ca_conn_next_retry =
|
||||
cac_time_sum (
|
||||
¤t,
|
||||
&ca_static->ca_conn_retry_delay);
|
||||
LOGRETRYINTERVAL
|
||||
|
||||
ca_static->ca_manage_conn_active = FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* retrySearchRequest ()
|
||||
*/
|
||||
LOCAL void retrySearchRequest (int silent)
|
||||
{
|
||||
ELLLIST channelsSent;
|
||||
chid chix;
|
||||
unsigned min_retry_num;
|
||||
unsigned retry_cnt = 0;
|
||||
unsigned retry_cnt_no_handler = 0;
|
||||
int status;
|
||||
|
||||
if (!piiuCast) {
|
||||
return;
|
||||
}
|
||||
|
||||
ellInit (&channelsSent);
|
||||
|
||||
LOCK;
|
||||
for( chix = (chid) piiuCast->chidlist.node.next;
|
||||
chix;
|
||||
chix = (chid) chix->node.next){
|
||||
min_retry_num = MAXCONNTRIES;
|
||||
while (chix = (chid) ellGet (&piiuCast->chidlist)) {
|
||||
|
||||
search_msg(chix, DONTREPLY);
|
||||
retry_cnt++;
|
||||
ellAdd (&channelsSent, &chix->node);
|
||||
|
||||
if(!(silent || chix->pConnFunc)){
|
||||
ca_signal(ECA_CHIDNOTFND, (char *)(chix+1));
|
||||
retry_cnt_no_handler++;
|
||||
min_retry_num = min (min_retry_num, chix->retry);
|
||||
|
||||
if (chix->retry <= ca_static->ca_search_retry) {
|
||||
|
||||
status = search_msg (chix, DONTREPLY);
|
||||
if (status == ECA_NORMAL) {
|
||||
retry_cnt++;
|
||||
if (!(silent || chix->pConnFunc)) {
|
||||
ca_signal (
|
||||
ECA_CHIDNOTFND,
|
||||
(char *)(chix+1));
|
||||
retry_cnt_no_handler++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
UNLOCK;
|
||||
|
||||
if(retry_cnt){
|
||||
if(!silent && retry_cnt_no_handler){
|
||||
sprintf(
|
||||
/*
|
||||
* if we saw the entire list
|
||||
*/
|
||||
if (chix==NULL) {
|
||||
/*
|
||||
* increment the retry sequence number
|
||||
*/
|
||||
if (ca_static->ca_search_retry<MAXCONNTRIES) {
|
||||
ca_static->ca_search_retry++;
|
||||
}
|
||||
|
||||
/*
|
||||
* jump to the minimum retry number
|
||||
*/
|
||||
if (ca_static->ca_search_retry<min_retry_num) {
|
||||
ca_static->ca_search_retry = min_retry_num;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* return channels sent to main cast IIU's
|
||||
* channel prior to removing the lock
|
||||
*
|
||||
* This reorders the list so that each channel
|
||||
* get a fair chance to connect
|
||||
*/
|
||||
ellConcat (&piiuCast->chidlist, &channelsSent);
|
||||
|
||||
/*
|
||||
* LOCK around use of the sprintf buffer
|
||||
*/
|
||||
if (retry_cnt) {
|
||||
if (!silent && retry_cnt_no_handler) {
|
||||
sprintf (
|
||||
sprintf_buf,
|
||||
"%d channels outstanding",
|
||||
retry_cnt);
|
||||
ca_signal(ECA_CHIDRETRY, sprintf_buf);
|
||||
ca_signal (ECA_CHIDRETRY, sprintf_buf);
|
||||
}
|
||||
}
|
||||
UNLOCK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* logRetryInterval()
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
LOCAL void logRetryInterval(char *pFN, unsigned lineno)
|
||||
{
|
||||
ca_time currentTime;
|
||||
ca_real delay;
|
||||
|
||||
assert(ca_static->ca_conn_next_retry.tv_usec<USEC_PER_SEC);
|
||||
cac_gettimeval(¤tTime);
|
||||
delay = cac_time_diff(
|
||||
&ca_static->ca_conn_next_retry,
|
||||
¤tTime);
|
||||
ca_printf("%s.%d next retry in %f sec\n",
|
||||
pFN,
|
||||
lineno,
|
||||
delay);
|
||||
delay = ca_static->ca_conn_retry_delay.tv_sec +
|
||||
((double)ca_static->ca_conn_retry_delay.tv_usec)/
|
||||
USEC_PER_SEC;
|
||||
ca_printf("%s.%d retry interval = %f sec - disconn count = %d\n",
|
||||
pFN,
|
||||
lineno,
|
||||
delay,
|
||||
ellCount(&piiuCast->chidlist));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
@@ -184,8 +356,9 @@ void manage_conn(int silent)
|
||||
*/
|
||||
void mark_server_available(struct in_addr *pnet_addr)
|
||||
{
|
||||
int currentPeriod;
|
||||
int currentTime;
|
||||
chid chan;
|
||||
ca_real currentPeriod;
|
||||
ca_time currentTime;
|
||||
bhe *pBHE;
|
||||
unsigned port;
|
||||
int netChange = FALSE;
|
||||
@@ -200,7 +373,7 @@ void mark_server_available(struct in_addr *pnet_addr)
|
||||
return;
|
||||
}
|
||||
|
||||
currentTime = time(NULL);
|
||||
cac_gettimeval(¤tTime);
|
||||
|
||||
LOCK;
|
||||
/*
|
||||
@@ -217,11 +390,17 @@ void mark_server_available(struct in_addr *pnet_addr)
|
||||
/*
|
||||
* update time stamp and average period
|
||||
*/
|
||||
currentPeriod = currentTime - pBHE->timeStamp;
|
||||
pBHE->averagePeriod = (currentPeriod + pBHE->averagePeriod)>>1;
|
||||
currentPeriod = cac_time_diff (
|
||||
¤tTime,
|
||||
&pBHE->timeStamp);
|
||||
/*
|
||||
* update the average
|
||||
*/
|
||||
pBHE->averagePeriod += currentPeriod;
|
||||
pBHE->averagePeriod /= 2.0;
|
||||
pBHE->timeStamp = currentTime;
|
||||
|
||||
if((currentPeriod>>2)>=pBHE->averagePeriod){
|
||||
if ((currentPeriod/4.0)>=pBHE->averagePeriod) {
|
||||
#ifdef DEBUG
|
||||
ca_printf(
|
||||
"net resume seen %x cur=%d avg=%d\n",
|
||||
@@ -232,7 +411,7 @@ void mark_server_available(struct in_addr *pnet_addr)
|
||||
netChange = TRUE;
|
||||
}
|
||||
|
||||
if((pBHE->averagePeriod>>1)>=currentPeriod){
|
||||
if ((pBHE->averagePeriod/2.0)>=currentPeriod) {
|
||||
#ifdef DEBUG
|
||||
ca_printf(
|
||||
"reboot seen %x cur=%d avg=%d\n",
|
||||
@@ -260,8 +439,8 @@ void mark_server_available(struct in_addr *pnet_addr)
|
||||
|
||||
|
||||
/*
|
||||
* This part is very important since many machines
|
||||
* could have channels in a disconnected state which
|
||||
* This part is essential since many machines
|
||||
* might have channels in a disconnected state which
|
||||
* dont exist anywhere on the network. This insures
|
||||
* that we dont have many CA clients synchronously
|
||||
* flooding the network with broadcasts.
|
||||
@@ -279,23 +458,47 @@ void mark_server_available(struct in_addr *pnet_addr)
|
||||
piiuCast->sock_chan,
|
||||
(struct sockaddr *)&saddr,
|
||||
&saddr_length);
|
||||
assert(status>=0);
|
||||
assert (status>=0);
|
||||
port = ntohs(saddr.sin_port);
|
||||
}
|
||||
|
||||
{
|
||||
int delay;
|
||||
int next;
|
||||
ca_real diff;
|
||||
ca_real delay;
|
||||
unsigned idelay;
|
||||
ca_time ca_delay;
|
||||
ca_time next;
|
||||
|
||||
delay = port&CA_RECAST_PORT_MASK;
|
||||
delay = (port&CA_RECAST_PORT_MASK);
|
||||
delay /= MSEC_PER_SEC;
|
||||
delay += CA_RECAST_DELAY;
|
||||
idelay = delay;
|
||||
ca_delay.tv_sec = idelay;
|
||||
ca_delay.tv_usec = (delay-idelay) * USEC_PER_SEC;
|
||||
next = cac_time_sum(¤tTime, &ca_delay);
|
||||
|
||||
next = currentTime + delay;
|
||||
|
||||
if(ca_static->ca_conn_next_retry>next){
|
||||
diff = cac_time_diff(
|
||||
&ca_static->ca_conn_next_retry,
|
||||
&next);
|
||||
if(diff>0.0){
|
||||
ca_static->ca_conn_next_retry = next;
|
||||
LOGRETRYINTERVAL
|
||||
}
|
||||
ca_static->ca_conn_retry_delay = CA_RECAST_DELAY;
|
||||
ca_static->ca_conn_n_tries = 0;
|
||||
idelay = CA_RECAST_DELAY;
|
||||
ca_static->ca_conn_retry_delay.tv_sec = idelay;
|
||||
ca_static->ca_conn_retry_delay.tv_usec =
|
||||
(CA_RECAST_DELAY-idelay) * USEC_PER_SEC;
|
||||
ca_static->ca_search_retry = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* set retry count of all disconnected channels
|
||||
* to zero
|
||||
*/
|
||||
chan = (chid) ellFirst(&piiuCast->chidlist);
|
||||
while (chan) {
|
||||
chan->retry = 0;
|
||||
chan = (chid) ellNext (&chan->node);
|
||||
}
|
||||
|
||||
UNLOCK;
|
||||
@@ -330,6 +533,7 @@ bhe *createBeaconHashEntry(struct in_addr *pnet_addr)
|
||||
#ifdef DEBUG
|
||||
ca_printf("new IOC %x\n", pnet_addr->s_addr);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* store the inet address
|
||||
*/
|
||||
@@ -338,8 +542,8 @@ bhe *createBeaconHashEntry(struct in_addr *pnet_addr)
|
||||
/*
|
||||
* start the average at zero
|
||||
*/
|
||||
pBHE->averagePeriod = 0;
|
||||
pBHE->timeStamp = time(NULL);
|
||||
pBHE->averagePeriod = 0.0;
|
||||
cac_gettimeval(&pBHE->timeStamp);
|
||||
|
||||
/*
|
||||
* install in the hash table
|
||||
@@ -383,29 +587,29 @@ bhe *lookupBeaconInetAddr(struct in_addr *pnet_addr)
|
||||
*
|
||||
* LOCK must be applied
|
||||
*/
|
||||
void removeBeaconInetAddr(struct in_addr *pnet_addr)
|
||||
void removeBeaconInetAddr (struct in_addr *pnet_addr)
|
||||
{
|
||||
bhe *pBHE;
|
||||
bhe **ppBHE;
|
||||
unsigned index;
|
||||
|
||||
index = ntohl(pnet_addr->s_addr);
|
||||
index = ntohl (pnet_addr->s_addr);
|
||||
index &= BHT_INET_ADDR_MASK;
|
||||
|
||||
assert(index<NELEMENTS(ca_static->ca_beaconHash));
|
||||
assert (index<NELEMENTS(ca_static->ca_beaconHash));
|
||||
|
||||
ppBHE = &ca_static->ca_beaconHash[index];
|
||||
pBHE = *ppBHE;
|
||||
while(pBHE){
|
||||
if(pBHE->inetAddr.s_addr == pnet_addr->s_addr){
|
||||
while (pBHE) {
|
||||
if (pBHE->inetAddr.s_addr == pnet_addr->s_addr) {
|
||||
*ppBHE = pBHE->pNext;
|
||||
free(pBHE);
|
||||
free (pBHE);
|
||||
return;
|
||||
}
|
||||
ppBHE = &pBHE->pNext;
|
||||
pBHE = *ppBHE;
|
||||
}
|
||||
assert(0);
|
||||
assert (0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
141
src/ca/convert.c
141
src/ca/convert.c
@@ -23,11 +23,12 @@
|
||||
* joh 07-05-94 Fixed double invocation of ++ operator
|
||||
* by byte swap macro bug in cvrt_short(),
|
||||
* cvrt_long(), cvrt_enum().
|
||||
* joh 11-02-94 moved float convert to this source
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
static char *sccsId = "$Id$";
|
||||
static char *sccsId = "@(#) $Id$";
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -36,11 +37,8 @@ static char *sccsId = "$Id$";
|
||||
|
||||
void htond(double *pHost, double *pNet);
|
||||
void ntohd(double *pNet, double *pHost);
|
||||
|
||||
#ifndef CONVERSION_REQUIRED
|
||||
void htonf(float *IEEEhost, float *IEEEnet);
|
||||
void ntohf(float *IEEEnet, float *IEEEhost);
|
||||
#endif /*not CONVERSION_REQUIRED*/
|
||||
void htonf(float *pHost, float *pNet);
|
||||
void ntohf(float *pNet, float *pHost);
|
||||
|
||||
/*
|
||||
* if hton is true then it is a host to network conversion
|
||||
@@ -94,9 +92,6 @@ LOCAL CACVRTFUNC cvrt_ctrl_long;
|
||||
LOCAL CACVRTFUNC cvrt_ctrl_double;
|
||||
|
||||
/* cvrt is (array of) (pointer to) (function returning) int */
|
||||
#ifdef VMS
|
||||
globaldef
|
||||
#endif
|
||||
CACVRTFUNC *cac_dbr_cvrt[]
|
||||
=
|
||||
{
|
||||
@@ -148,7 +143,7 @@ typedef short ca_short_tt;
|
||||
typedef float ca_float_tt;
|
||||
typedef short ca_enum_tt;
|
||||
typedef char ca_char_tt;
|
||||
typedef long ca_long_tt;
|
||||
typedef int ca_long_tt;
|
||||
typedef double ca_double_tt;
|
||||
|
||||
#define dbr_ntohs(A) ntohs(A)
|
||||
@@ -227,7 +222,7 @@ int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned long i;
|
||||
ca_char_tt *pSrc = s;
|
||||
ca_char_tt *pDest = d;
|
||||
|
||||
@@ -280,7 +275,7 @@ int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned long i;
|
||||
ca_enum_tt *pSrc;
|
||||
ca_enum_tt *pDest;
|
||||
|
||||
@@ -347,7 +342,7 @@ int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned long i;
|
||||
ca_double_tt *pSrc = s;
|
||||
ca_double_tt *pDest = d;
|
||||
|
||||
@@ -1379,7 +1374,7 @@ unsigned long num /* number of values */
|
||||
}
|
||||
|
||||
|
||||
#ifdef MIT_FLOAT
|
||||
#ifdef CA_FLOAT_MIT
|
||||
/************************************************************************/
|
||||
/* double convert */
|
||||
/* (THIS ASSUMES IEEE IS THE NETWORK FLOATING POINT FORMAT) */
|
||||
@@ -1424,8 +1419,8 @@ void htond(double *pHost, double *pNet)
|
||||
double copyin;
|
||||
struct mitdbl *pMIT;
|
||||
struct ieeedbl *pIEEE;
|
||||
long *ptmp;
|
||||
long tmp;
|
||||
ca_uint32_t *ptmp;
|
||||
ca_uint32_t tmp;
|
||||
|
||||
copyin = *pHost;
|
||||
pMIT = (struct mitdbl *)©in;
|
||||
@@ -1448,7 +1443,7 @@ void htond(double *pHost, double *pNet)
|
||||
/*
|
||||
* byte swap to net order
|
||||
*/
|
||||
ptmp = (long *) pNet;
|
||||
ptmp = (ca_uint32_t *) pNet;
|
||||
tmp = htonl(ptmp[0]);
|
||||
ptmp[0] = htonl(ptmp[1]);
|
||||
ptmp[1] = tmp;
|
||||
@@ -1464,8 +1459,8 @@ void ntohd(double *pNet, double *pHost)
|
||||
double copyin;
|
||||
struct mitdbl *pMIT;
|
||||
struct ieeedbl *pIEEE;
|
||||
long *ptmp;
|
||||
long tmp;
|
||||
ca_uint32_t *ptmp;
|
||||
ca_uint32_t tmp;
|
||||
|
||||
copyin = *pNet;
|
||||
pMIT = (struct mitdbl *)pHost;
|
||||
@@ -1474,7 +1469,7 @@ void ntohd(double *pNet, double *pHost)
|
||||
/*
|
||||
* Byte swap from net order to host order
|
||||
*/
|
||||
ptmp = (long *) pIEEE;
|
||||
ptmp = (ca_uint32_t *) pIEEE;
|
||||
tmp = htonl(ptmp[0]);
|
||||
ptmp[0] = htonl(ptmp[1]);
|
||||
ptmp[1] = tmp;
|
||||
@@ -1505,9 +1500,106 @@ void ntohd(double *pNet, double *pHost)
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*MIT_FLOAT*/
|
||||
/************************************************************************/
|
||||
/* (THIS ASSUMES IEEE IS THE NETWORK FLOATING POINT FORMAT) */
|
||||
/************************************************************************/
|
||||
|
||||
struct ieeeflt{
|
||||
unsigned mant :23;
|
||||
unsigned exp :8;
|
||||
unsigned sign :1;
|
||||
};
|
||||
|
||||
/* Exponent sign bias */
|
||||
#define IEEE_SB 127
|
||||
|
||||
/* Conversion Range */
|
||||
/* -126<exp<127 with mantissa of form 1.mant */
|
||||
#define EXPMINIEEE -126 /* min for norm # IEEE exponent */
|
||||
|
||||
|
||||
struct mitflt{
|
||||
unsigned mant1 :7;
|
||||
unsigned exp :8;
|
||||
unsigned sign :1;
|
||||
unsigned mant2 :16;
|
||||
};
|
||||
|
||||
/* Exponent sign bias */
|
||||
# define MIT_SB 129
|
||||
|
||||
/* Conversion Ranges */
|
||||
/* -128<exp<126 with mantissa of form 1.mant */
|
||||
# define EXPMAXMIT 126 /* max MIT exponent */
|
||||
# define EXPMINMIT -128 /* min MIT exponent */
|
||||
|
||||
/* (this includes mapping of fringe reals to zero or infinity) */
|
||||
/* (byte swaps included in conversion */
|
||||
|
||||
void htonf(float *pHost, float *pNet)
|
||||
{
|
||||
struct mitflt *pMIT = pHost;
|
||||
struct ieeeflt *pIEEE = pNet;
|
||||
long exp,mant,sign;
|
||||
|
||||
sign = pHost->sign;
|
||||
|
||||
if( (short)(pMIT->exp < EXPMINIEEE + MIT_SB){
|
||||
exp = 0;
|
||||
mant = 0;
|
||||
sign = 0;
|
||||
}
|
||||
else{
|
||||
exp = (short)pMIT->exp-MIT_SB+IEEE_SB;
|
||||
mant = (pMIT->mant1<<16) | pMIT->mant2;
|
||||
}
|
||||
pIEEE->mant = mant;
|
||||
pIEEE->exp = exp;
|
||||
pIEEE->sign = sign;
|
||||
*(ca_uint32_t *)pIEEE = ntohl(*(ca_uint32_t *)pIEEE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* sign must be forced to zero if the exponent is zero to prevent a reserved
|
||||
* operand fault- joh 9-13-90
|
||||
*/
|
||||
void ntohf(float *pNet, float *pHost)
|
||||
{
|
||||
struct mitflt *pMIT = pHost;
|
||||
struct ieeeflt *pIEEE = pNet;
|
||||
long exp,mant2,mant1,sign;
|
||||
|
||||
*(ca_uint32_t *)pIEEE = htonl(*(ca_uint32_t *)pIEEE);
|
||||
if( (short) pIEEE->exp > EXPMAXMIT + IEEE_SB){
|
||||
sign = pIEEE->sign;
|
||||
exp = EXPMAXMIT + MIT_SB;
|
||||
mant2 = ~0;
|
||||
mant1 = ~0;
|
||||
}
|
||||
else if( pIEEE->exp == 0){
|
||||
sign = 0;
|
||||
exp = 0;
|
||||
mant2 = 0;
|
||||
mant1 = 0;
|
||||
}
|
||||
else{
|
||||
sign = pIEEE->sign;
|
||||
exp = pIEEE->exp+MIT_SB-IEEE_SB;
|
||||
mant2 = pIEEE->mant;
|
||||
mant1 = pIEEE->mant>>(unsigned)16;
|
||||
}
|
||||
pMIT->exp = exp;
|
||||
pMIT->mant2 = mant2;
|
||||
pMIT->mant1 = mant1;
|
||||
pMIT->sign = sign;
|
||||
}
|
||||
|
||||
|
||||
#endif /*CA_FLOAT_MIT*/
|
||||
|
||||
#ifndef CA_FLOAT_MIT
|
||||
|
||||
#ifndef CONVERSION_REQUIRED
|
||||
void htond(double *IEEEhost, double *IEEEnet)
|
||||
{
|
||||
*IEEEnet = *IEEEhost;
|
||||
@@ -1527,5 +1619,8 @@ void htonf(float *IEEEhost, float *IEEEnet)
|
||||
{
|
||||
*IEEEnet = *IEEEhost;
|
||||
}
|
||||
#endif /* not MIT_FLOAT */
|
||||
|
||||
#endif /* not CA_MIT_FLOAT*/
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
/************************************************************************/
|
||||
/*_end */
|
||||
|
||||
static char *sccsId = "$Id$";
|
||||
static char *sccsId = "@(#) $Id$";
|
||||
|
||||
#include "iocinf.h"
|
||||
|
||||
@@ -61,7 +61,7 @@ void flow_control(struct ioc_in_use *piiu)
|
||||
*/
|
||||
status = socket_ioctl(piiu->sock_chan,
|
||||
FIONREAD,
|
||||
(int)&nbytes);
|
||||
&nbytes);
|
||||
if (status < 0) {
|
||||
TAG_CONN_DOWN(piiu);
|
||||
UNLOCK;
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
***************************************************
|
||||
*/
|
||||
|
||||
static char *sccsId = "$Id$";
|
||||
static char *sccsId = "@(#)gsd_sync_subr.c 1.8\t11/5/92";
|
||||
|
||||
#if defined(UNIX)
|
||||
# include <sys/types.h>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* if_depen.c */
|
||||
/* $Id$ */
|
||||
/* share/src/ca/$Id$ */
|
||||
|
||||
/*
|
||||
* Author: Jeff Hill
|
||||
@@ -35,11 +35,18 @@
|
||||
*/
|
||||
|
||||
|
||||
static char *sccsId = "$Id$";
|
||||
static char *sccsId = "@(#) $Id$";
|
||||
|
||||
|
||||
#include "iocinf.h"
|
||||
|
||||
/*
|
||||
* Dont use ca_static based lock macros here because this is
|
||||
* also called by the server. All locks required are applied at
|
||||
* a higher level.
|
||||
*/
|
||||
#undef LOCK
|
||||
#undef UNLOCK
|
||||
|
||||
|
||||
/*
|
||||
@@ -69,39 +76,42 @@ int local_addr(int s, struct sockaddr_in *plcladdr)
|
||||
*/
|
||||
ifconf.ifc_len = sizeof ifreq;
|
||||
ifconf.ifc_req = ifreq;
|
||||
status = socket_ioctl(s, SIOCGIFCONF, (int)&ifconf);
|
||||
status = socket_ioctl(s, SIOCGIFCONF, &ifconf);
|
||||
if (status < 0 || ifconf.ifc_len == 0) {
|
||||
ca_printf("CAC: ioctl failed %s\n", strerror(MYERRNO));
|
||||
ifconf.ifc_len = 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
ca_printf("CAC: %d if fnd\n", ifconf.ifc_len/sizeof(*pifreq));
|
||||
#endif
|
||||
|
||||
for ( pifreq = ifconf.ifc_req;
|
||||
ifconf.ifc_len >= sizeof(*pifreq);
|
||||
pifreq++, ifconf.ifc_len -= sizeof(*pifreq)) {
|
||||
|
||||
status = socket_ioctl(s, SIOCGIFFLAGS, (int)pifreq);
|
||||
status = socket_ioctl(s, SIOCGIFFLAGS, pifreq);
|
||||
if (status == ERROR){
|
||||
ca_printf("CAC: could not obtain if flags\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(pifreq->ifr_flags & IFF_UP)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pifreq->ifr_flags & IFF_LOOPBACK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(pifreq->ifr_flags & IFF_BROADCAST)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
ca_printf("CAC: if fnd %s\n", pifreq->ifr_name);
|
||||
#endif
|
||||
|
||||
status = socket_ioctl(s, SIOCGIFADDR, (int)pifreq);
|
||||
if (!(pifreq->ifr_flags & IFF_UP)) {
|
||||
#ifdef DEBUG
|
||||
ca_printf("CAC: if was down\n");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* o Dont require broadcast capabilities.
|
||||
* o Loopback addresss is ok - preferable?
|
||||
*/
|
||||
status = socket_ioctl(s, SIOCGIFADDR, pifreq);
|
||||
if (status == ERROR){
|
||||
#ifdef DEBUG
|
||||
ca_printf("CAC: could not obtain addr\n");
|
||||
@@ -118,20 +128,9 @@ int local_addr(int s, struct sockaddr_in *plcladdr)
|
||||
|
||||
tmpaddr = (struct sockaddr_in *) &pifreq->ifr_addr;
|
||||
|
||||
if (!init){
|
||||
init = TRUE;
|
||||
addr = *tmpaddr;
|
||||
}
|
||||
else {
|
||||
if (tmpaddr->sin_addr.s_addr
|
||||
!= addr.sin_addr.s_addr)
|
||||
ca_printf("CAC: %s: interface=%s inet addr does not match first interface found %x\n",
|
||||
__FILE__,
|
||||
pifreq->ifr_name,
|
||||
tmpaddr->sin_addr.s_addr);
|
||||
if (tmpaddr->sin_port != addr.sin_port)
|
||||
ca_printf("CAC: local_addr(): inconsistent port found- first used\n");
|
||||
}
|
||||
init = TRUE;
|
||||
addr = *tmpaddr;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!init){
|
||||
@@ -149,6 +148,9 @@ int local_addr(int s, struct sockaddr_in *plcladdr)
|
||||
*
|
||||
* Load the list with the broadcast address for all
|
||||
* interfaces found that support broadcast.
|
||||
*
|
||||
* LOCK should be applied here for (pList)
|
||||
* (this is also called from the server)
|
||||
*/
|
||||
void caDiscoverInterfaces(ELLLIST *pList, int socket, int port)
|
||||
{
|
||||
@@ -176,7 +178,7 @@ void caDiscoverInterfaces(ELLLIST *pList, int socket, int port)
|
||||
|
||||
ifconf.ifc_len = nelem*sizeof(*pifreq);
|
||||
ifconf.ifc_req = pIfreqList;
|
||||
status = socket_ioctl(socket, SIOCGIFCONF, (int)&ifconf);
|
||||
status = socket_ioctl(socket, SIOCGIFCONF, &ifconf);
|
||||
if (status < 0 || ifconf.ifc_len == 0) {
|
||||
free(pIfreqList);
|
||||
return;
|
||||
@@ -184,7 +186,7 @@ void caDiscoverInterfaces(ELLLIST *pList, int socket, int port)
|
||||
|
||||
nelem = ifconf.ifc_len/sizeof(struct ifreq);
|
||||
for (pifreq = pIfreqList; pifreq<(pIfreqList+nelem); pifreq++){
|
||||
status = socket_ioctl(socket, SIOCGIFFLAGS, (int) pifreq);
|
||||
status = socket_ioctl(socket, SIOCGIFFLAGS, pifreq);
|
||||
if (status){
|
||||
continue;
|
||||
}
|
||||
@@ -206,7 +208,7 @@ void caDiscoverInterfaces(ELLLIST *pList, int socket, int port)
|
||||
/*
|
||||
* Fetch the local address for this interface
|
||||
*/
|
||||
status = socket_ioctl(socket, SIOCGIFADDR, (int)pifreq);
|
||||
status = socket_ioctl(socket, SIOCGIFADDR, pifreq);
|
||||
if (status){
|
||||
continue;
|
||||
}
|
||||
@@ -234,7 +236,7 @@ void caDiscoverInterfaces(ELLLIST *pList, int socket, int port)
|
||||
status = socket_ioctl(
|
||||
socket,
|
||||
SIOCGIFBRDADDR,
|
||||
(int) pifreq);
|
||||
pifreq);
|
||||
if (status){
|
||||
continue;
|
||||
}
|
||||
@@ -243,7 +245,7 @@ void caDiscoverInterfaces(ELLLIST *pList, int socket, int port)
|
||||
status = socket_ioctl(
|
||||
socket,
|
||||
SIOCGIFDSTADDR,
|
||||
(int) pifreq);
|
||||
pifreq);
|
||||
if (status){
|
||||
continue;
|
||||
}
|
||||
@@ -264,10 +266,10 @@ void caDiscoverInterfaces(ELLLIST *pList, int socket, int port)
|
||||
pNode->destAddr.inetAddr.sin_port = htons(port);
|
||||
pNode->srcAddr.inetAddr = localAddr;
|
||||
|
||||
LOCK;
|
||||
/*
|
||||
* LOCK applied externally
|
||||
*/
|
||||
ellAdd(pList, &pNode->node);
|
||||
UNLOCK;
|
||||
|
||||
}
|
||||
|
||||
free(pIfreqList);
|
||||
|
||||
397
src/ca/iocinf.c
397
src/ca/iocinf.c
@@ -66,7 +66,7 @@
|
||||
/************************************************************************/
|
||||
/*_end */
|
||||
|
||||
static char *sccsId = "$Id$";
|
||||
static char *sccsId = "@(#) $Id$";
|
||||
|
||||
|
||||
/* Allocate storage for global variables in this module */
|
||||
@@ -152,7 +152,7 @@ int net_proto
|
||||
{
|
||||
struct ioc_in_use *piiu;
|
||||
int status;
|
||||
int sock;
|
||||
SOCKET sock;
|
||||
int true = TRUE;
|
||||
struct sockaddr_in saddr;
|
||||
caAddrNode *pNode;
|
||||
@@ -190,17 +190,19 @@ int net_proto
|
||||
}
|
||||
pNode->destAddr.inetAddr.sin_family = AF_INET;
|
||||
pNode->destAddr.inetAddr.sin_addr = *pnet_addr;
|
||||
pNode->destAddr.inetAddr.sin_port = htons(CA_SERVER_PORT);
|
||||
pNode->destAddr.inetAddr.sin_port =
|
||||
htons (ca_static->ca_server_port);
|
||||
ellAdd(&piiu->destAddr, &pNode->node);
|
||||
piiu->recvBytes = tcp_recv_msg;
|
||||
piiu->sendBytes = cac_tcp_send_msg_piiu;
|
||||
piiu->procInput = ca_process_tcp;
|
||||
piiu->minfreespace = 1;
|
||||
|
||||
/* allocate a socket */
|
||||
sock = socket( AF_INET, /* domain */
|
||||
SOCK_STREAM, /* type */
|
||||
0); /* deflt proto */
|
||||
if(sock == ERROR){
|
||||
if(sock == INVALID_SOCKET){
|
||||
free(piiu);
|
||||
UNLOCK;
|
||||
return ECA_SOCK;
|
||||
@@ -347,7 +349,7 @@ int net_proto
|
||||
status = socket_ioctl(
|
||||
piiu->sock_chan,
|
||||
FIONBIO,
|
||||
(int) &true);
|
||||
&true);
|
||||
if(status<0){
|
||||
ca_printf(
|
||||
"Error setting non-blocking io: %s\n",
|
||||
@@ -363,7 +365,7 @@ int net_proto
|
||||
piiu->host_name_str,
|
||||
sizeof(piiu->host_name_str));
|
||||
|
||||
piiu->timeAtLastRecv = time(NULL);
|
||||
cac_gettimeval (&piiu->timeAtLastRecv);
|
||||
|
||||
break;
|
||||
|
||||
@@ -373,12 +375,13 @@ int net_proto
|
||||
piiu->recvBytes = udp_recv_msg;
|
||||
piiu->sendBytes = cac_udp_send_msg_piiu;
|
||||
piiu->procInput = ca_process_udp;
|
||||
piiu->minfreespace = MAX_UDP+2*sizeof(struct udpmsglog);
|
||||
|
||||
/* allocate a socket */
|
||||
sock = socket( AF_INET, /* domain */
|
||||
SOCK_DGRAM, /* type */
|
||||
0); /* deflt proto */
|
||||
if(sock == ERROR){
|
||||
if(sock == INVALID_SOCKET){
|
||||
free (piiu);
|
||||
UNLOCK;
|
||||
return ECA_SOCK;
|
||||
@@ -423,19 +426,18 @@ int net_proto
|
||||
ca_signal(ECA_INTERNAL,"bind failed");
|
||||
}
|
||||
|
||||
caDiscoverInterfaces(
|
||||
&piiu->destAddr,
|
||||
sock,
|
||||
CA_SERVER_PORT);
|
||||
|
||||
caAddConfiguredAddr(
|
||||
/*
|
||||
* load user and auto configured
|
||||
* broadcast address list
|
||||
*/
|
||||
caSetupBCastAddrList(
|
||||
&piiu->destAddr,
|
||||
&EPICS_CA_ADDR_LIST,
|
||||
sock,
|
||||
CA_SERVER_PORT);
|
||||
sock,
|
||||
ca_static->ca_server_port);
|
||||
|
||||
cacRingBufferInit(&piiu->recv, sizeof(piiu->send.buf));
|
||||
cacRingBufferInit(&piiu->send, min(MAX_UDP, sizeof(piiu->send.buf)));
|
||||
cacRingBufferInit(&piiu->send, min(MAX_UDP,
|
||||
sizeof(piiu->send.buf)));
|
||||
|
||||
strncpy(
|
||||
piiu->host_name_str,
|
||||
@@ -460,18 +462,6 @@ int net_proto
|
||||
UNLOCKEVENTS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* setup the recv thread
|
||||
* (OS dependent)
|
||||
*/
|
||||
status = cac_setup_recv_thread(piiu);
|
||||
if(status != ECA_NORMAL){
|
||||
free(piiu);
|
||||
status = socket_close(sock);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* add to the list of active IOCs
|
||||
*/
|
||||
@@ -485,12 +475,64 @@ int net_proto
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caSetupBCastAddrList()
|
||||
*/
|
||||
void caSetupBCastAddrList (ELLLIST *pList, SOCKET sock, unsigned port)
|
||||
{
|
||||
char *pstr;
|
||||
ENV_PARAM yesno;
|
||||
int yes;
|
||||
|
||||
/*
|
||||
* dont load the list twice
|
||||
*/
|
||||
assert (ellCount(pList)==0);
|
||||
|
||||
/*
|
||||
* Check to see if the user has disabled
|
||||
* initializing the search b-cast list
|
||||
* from the interfaces found.
|
||||
*/
|
||||
yes = TRUE;
|
||||
pstr = envGetConfigParam (
|
||||
&EPICS_CA_AUTO_ADDR_LIST,
|
||||
sizeof(yesno.dflt),
|
||||
yesno.dflt);
|
||||
if (pstr) {
|
||||
if (strstr(pstr,"no")||strstr(pstr,"NO")) {
|
||||
yes = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* LOCK is for piiu->destAddr list
|
||||
* (lock outside because this is used by the server also)
|
||||
*/
|
||||
if (yes) {
|
||||
caDiscoverInterfaces(
|
||||
pList,
|
||||
sock,
|
||||
port);
|
||||
}
|
||||
|
||||
caAddConfiguredAddr(
|
||||
pList,
|
||||
&EPICS_CA_ADDR_LIST,
|
||||
sock,
|
||||
port);
|
||||
|
||||
if (ellCount(pList)==0) {
|
||||
ca_signal (ECA_NOSEARCHADDR, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* NOTIFY_CA_REPEATER()
|
||||
*
|
||||
* tell the cast repeater that another client has come on line
|
||||
* tell the cast repeater that another client needs fan out
|
||||
*
|
||||
* NOTES:
|
||||
* 1) local communication only (no LAN traffic)
|
||||
@@ -498,25 +540,55 @@ int net_proto
|
||||
*/
|
||||
void notify_ca_repeater()
|
||||
{
|
||||
struct extmsg msg;
|
||||
struct sockaddr_in saddr;
|
||||
int status;
|
||||
static int once = FALSE;
|
||||
|
||||
if(!piiuCast)
|
||||
if (ca_static->ca_repeater_contacted) {
|
||||
return;
|
||||
if(!piiuCast->conn_up)
|
||||
}
|
||||
|
||||
if (!piiuCast) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!piiuCast->conn_up) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ca_static->ca_repeater_tries>N_REPEATER_TRIES_PRIOR_TO_MSG){
|
||||
if (!once) {
|
||||
ca_printf(
|
||||
"Unable to contact CA repeater after %d tries\n",
|
||||
N_REPEATER_TRIES_PRIOR_TO_MSG);
|
||||
ca_printf(
|
||||
"Silence this message by starting a CA repeater daemon\n");
|
||||
once = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
LOCK; /*MULTINET TCP/IP routines are not reentrant*/
|
||||
status = local_addr(piiuCast->sock_chan, &saddr);
|
||||
if(status == OK){
|
||||
saddr.sin_port = htons(CA_CLIENT_PORT);
|
||||
if (status == OK) {
|
||||
memset((char *)&msg, 0, sizeof(msg));
|
||||
msg.m_cmmd = htons(REPEATER_REGISTER);
|
||||
msg.m_available = saddr.sin_addr.s_addr;
|
||||
saddr.sin_port = htons(ca_static->ca_repeater_port);
|
||||
/*
|
||||
* Intentionally sending a zero length message here
|
||||
* until most CA repeater daemons have been restarted
|
||||
* (and only then will accept the above protocol)
|
||||
* (repeaters began accepting this protocol
|
||||
* starting with EPICS 3.12)
|
||||
*/
|
||||
status = sendto(
|
||||
piiuCast->sock_chan,
|
||||
NULL,
|
||||
0, /* zero length message */
|
||||
(char *)&msg, /* UCX requires a valid address here */
|
||||
0, /* <= sizeof(msg) ! see comment above ! */
|
||||
0,
|
||||
(struct sockaddr *)&saddr,
|
||||
sizeof saddr);
|
||||
sizeof(saddr));
|
||||
if(status < 0){
|
||||
if( MYERRNO != EINTR &&
|
||||
MYERRNO != ENOBUFS &&
|
||||
@@ -527,6 +599,9 @@ void notify_ca_repeater()
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
else{
|
||||
ca_static->ca_repeater_tries++;
|
||||
}
|
||||
}
|
||||
UNLOCK;
|
||||
}
|
||||
@@ -659,7 +734,7 @@ LOCAL void cac_tcp_send_msg_piiu(struct ioc_in_use *piiu)
|
||||
MYERRNO == EINTR){
|
||||
UNLOCK;
|
||||
if(!piiu->sendPending){
|
||||
piiu->timeAtSendBlock = time(NULL);
|
||||
cac_gettimeval(&piiu->timeAtSendBlock);
|
||||
piiu->sendPending = TRUE;
|
||||
}
|
||||
return;
|
||||
@@ -830,7 +905,7 @@ LOCAL void tcp_recv_msg(struct ioc_in_use *piiu)
|
||||
* Record the time whenever we receive a message
|
||||
* from this IOC
|
||||
*/
|
||||
piiu->timeAtLastRecv = time(NULL);
|
||||
cac_gettimeval(&piiu->timeAtLastRecv);
|
||||
|
||||
UNLOCK;
|
||||
return;
|
||||
@@ -856,7 +931,7 @@ LOCAL void ca_process_tcp(struct ioc_in_use *piiu)
|
||||
|
||||
pNode = (caAddrNode *) piiu->destAddr.node.next;
|
||||
|
||||
post_msg_active++;
|
||||
post_msg_active = TRUE;
|
||||
|
||||
LOCK;
|
||||
while(TRUE){
|
||||
@@ -873,7 +948,8 @@ LOCAL void ca_process_tcp(struct ioc_in_use *piiu)
|
||||
bytesToProcess);
|
||||
if(status != OK){
|
||||
TAG_CONN_DOWN(piiu);
|
||||
post_msg_active--;
|
||||
post_msg_active = FALSE;
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
CAC_RING_BUFFER_READ_ADVANCE(
|
||||
@@ -882,7 +958,7 @@ LOCAL void ca_process_tcp(struct ioc_in_use *piiu)
|
||||
}
|
||||
UNLOCK;
|
||||
|
||||
post_msg_active--;
|
||||
post_msg_active = FALSE;
|
||||
|
||||
flow_control(piiu);
|
||||
|
||||
@@ -939,7 +1015,7 @@ LOCAL void udp_recv_msg(struct ioc_in_use *piiu)
|
||||
* log the msg size
|
||||
* and advance the ring index
|
||||
*/
|
||||
pmsglog->nbytes = (long) status;
|
||||
pmsglog->nbytes = status;
|
||||
pmsglog->valid = TRUE;
|
||||
bytesActual = status + sizeof(*pmsglog);
|
||||
CAC_RING_BUFFER_WRITE_ADVANCE(&piiu->recv, bytesActual);
|
||||
@@ -961,7 +1037,7 @@ LOCAL void udp_recv_msg(struct ioc_in_use *piiu)
|
||||
ca_printf(
|
||||
"%s: udp reply of %d bytes\n",
|
||||
__FILE__,
|
||||
byte_cnt);
|
||||
status);
|
||||
# endif
|
||||
}
|
||||
|
||||
@@ -991,7 +1067,7 @@ LOCAL void ca_process_udp(struct ioc_in_use *piiu)
|
||||
}
|
||||
|
||||
|
||||
post_msg_active++;
|
||||
post_msg_active = TRUE;
|
||||
|
||||
LOCK;
|
||||
while(TRUE){
|
||||
@@ -1029,7 +1105,7 @@ LOCAL void ca_process_udp(struct ioc_in_use *piiu)
|
||||
sizeof(piiu->recv.buf));
|
||||
piiu->curMsgBytes = 0;
|
||||
piiu->curDataBytes = 0;
|
||||
post_msg_active--;
|
||||
post_msg_active = FALSE;
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
@@ -1043,7 +1119,7 @@ LOCAL void ca_process_udp(struct ioc_in_use *piiu)
|
||||
|
||||
UNLOCK;
|
||||
|
||||
post_msg_active--;
|
||||
post_msg_active = FALSE;
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1057,7 +1133,7 @@ LOCAL void ca_process_udp(struct ioc_in_use *piiu)
|
||||
*
|
||||
*
|
||||
*/
|
||||
void close_ioc(struct ioc_in_use *piiu)
|
||||
void close_ioc (struct ioc_in_use *piiu)
|
||||
{
|
||||
caAddrNode *pNode;
|
||||
chid chix;
|
||||
@@ -1066,107 +1142,116 @@ void close_ioc(struct ioc_in_use *piiu)
|
||||
/*
|
||||
* dont close twice
|
||||
*/
|
||||
if(piiu->sock_chan == -1){
|
||||
return;
|
||||
}
|
||||
assert (piiu->sock_chan!=INVALID_SOCKET);
|
||||
|
||||
LOCK;
|
||||
|
||||
ellDelete(&iiuList, &piiu->node);
|
||||
ellDelete (&iiuList, &piiu->node);
|
||||
|
||||
/*
|
||||
* attempt to clear out messages in recv queue
|
||||
*/
|
||||
(*piiu->procInput)(piiu);
|
||||
(*piiu->procInput) (piiu);
|
||||
|
||||
if(piiu == piiuCast){
|
||||
|
||||
if (piiu == piiuCast) {
|
||||
piiuCast = NULL;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* remove IOC from the hash table
|
||||
*/
|
||||
pNode = (caAddrNode *) piiu->destAddr.node.next;
|
||||
assert (pNode);
|
||||
removeBeaconInetAddr (&pNode->destAddr.inetAddr.sin_addr);
|
||||
|
||||
/*
|
||||
* Mark all of their channels disconnected
|
||||
* prior to calling handlers incase the
|
||||
* handler tries to use a channel before
|
||||
* I mark it disconnected.
|
||||
*/
|
||||
chix = (chid) &piiu->chidlist.node.next;
|
||||
while(chix = (chid) chix->node.next){
|
||||
chix->type = TYPENOTCONN;
|
||||
chix->count = 0;
|
||||
chix->state = cs_prev_conn;
|
||||
chix->id.sid = ~0L;
|
||||
chix->ar.read_access = FALSE;
|
||||
chix->ar.write_access = FALSE;
|
||||
}
|
||||
|
||||
if(piiu->chidlist.count){
|
||||
ca_signal(ECA_DISCONN,piiu->host_name_str);
|
||||
}
|
||||
|
||||
/*
|
||||
* remove IOC from the hash table
|
||||
*/
|
||||
pNode = (caAddrNode *) piiu->destAddr.node.next;
|
||||
assert(pNode);
|
||||
removeBeaconInetAddr(&pNode->destAddr.inetAddr.sin_addr);
|
||||
|
||||
/*
|
||||
* call their connection handler as required
|
||||
*/
|
||||
chix = (chid) &piiu->chidlist.node.next;
|
||||
while(chix = (chid) chix->node.next){
|
||||
LOCKEVENTS;
|
||||
if(chix->pConnFunc){
|
||||
struct connection_handler_args args;
|
||||
|
||||
args.chid = chix;
|
||||
args.op = CA_OP_CONN_DOWN;
|
||||
(*chix->pConnFunc)(args);
|
||||
}
|
||||
if(chix->pAccessRightsFunc){
|
||||
struct access_rights_handler_args args;
|
||||
|
||||
args.chid = chix;
|
||||
args.ar = chix->ar;
|
||||
(*chix->pAccessRightsFunc)(args);
|
||||
/*
|
||||
* Mark all of their channels disconnected
|
||||
* prior to calling handlers incase the
|
||||
* handler tries to use a channel before
|
||||
* I mark it disconnected.
|
||||
*/
|
||||
chix = (chid) &piiu->chidlist.node.next;
|
||||
while (chix = (chid) chix->node.next) {
|
||||
chix->type = TYPENOTCONN;
|
||||
chix->count = 0;
|
||||
chix->state = cs_prev_conn;
|
||||
chix->id.sid = ~0L;
|
||||
chix->ar.read_access = FALSE;
|
||||
chix->ar.write_access = FALSE;
|
||||
/*
|
||||
* try to reconnect
|
||||
*/
|
||||
chix->retry = 0;
|
||||
}
|
||||
UNLOCKEVENTS;
|
||||
chix->piiu = piiuCast;
|
||||
}
|
||||
|
||||
if (piiu->chidlist.count) {
|
||||
ca_signal (ECA_DISCONN,piiu->host_name_str);
|
||||
}
|
||||
|
||||
/*
|
||||
* call their connection handler as required
|
||||
*/
|
||||
chix = (chid) &piiu->chidlist.node.next;
|
||||
while (chix = (chid) chix->node.next) {
|
||||
LOCKEVENTS;
|
||||
if (chix->pConnFunc) {
|
||||
struct connection_handler_args args;
|
||||
|
||||
args.chid = chix;
|
||||
args.op = CA_OP_CONN_DOWN;
|
||||
(*chix->pConnFunc) (args);
|
||||
}
|
||||
if (chix->pAccessRightsFunc) {
|
||||
struct access_rights_handler_args args;
|
||||
|
||||
args.chid = chix;
|
||||
args.ar = chix->ar;
|
||||
(*chix->pAccessRightsFunc) (args);
|
||||
}
|
||||
UNLOCKEVENTS;
|
||||
chix->piiu = piiuCast;
|
||||
}
|
||||
|
||||
/*
|
||||
* move all channels to the broadcast IIU
|
||||
*
|
||||
* if we loose the broadcast IIU its a severe error
|
||||
*/
|
||||
assert (piiuCast);
|
||||
ellConcat (&piiuCast->chidlist, &piiu->chidlist);
|
||||
assert (piiu->chidlist.count==0);
|
||||
}
|
||||
|
||||
/*
|
||||
* move all channels to the broadcast IIU
|
||||
*
|
||||
* if we loose the broadcast IIU its a severe error
|
||||
* Try to reconnect
|
||||
*/
|
||||
assert(piiuCast);
|
||||
ellConcat(&piiuCast->chidlist, &piiu->chidlist);
|
||||
ca_static->ca_search_retry = 0;
|
||||
|
||||
assert(piiu->chidlist.count==0);
|
||||
|
||||
if(fd_register_func){
|
||||
if (fd_register_func) {
|
||||
LOCKEVENTS;
|
||||
(*fd_register_func)(fd_register_arg, piiu->sock_chan, FALSE);
|
||||
(*fd_register_func) (fd_register_arg, piiu->sock_chan, FALSE);
|
||||
UNLOCKEVENTS;
|
||||
}
|
||||
|
||||
status = socket_close(piiu->sock_chan);
|
||||
assert(status == 0);
|
||||
status = socket_close (piiu->sock_chan);
|
||||
assert (status == 0);
|
||||
|
||||
/*
|
||||
* free message body cache
|
||||
*/
|
||||
if(piiu->pCurData){
|
||||
free(piiu->pCurData);
|
||||
if (piiu->pCurData) {
|
||||
free (piiu->pCurData);
|
||||
piiu->pCurData = NULL;
|
||||
piiu->curDataMax = 0;
|
||||
}
|
||||
|
||||
piiu->sock_chan = -1;
|
||||
piiu->sock_chan = INVALID_SOCKET;
|
||||
|
||||
ellFree(&piiu->destAddr);
|
||||
ellFree (&piiu->destAddr);
|
||||
|
||||
free (piiu);
|
||||
|
||||
free(piiu);
|
||||
UNLOCK;
|
||||
}
|
||||
|
||||
@@ -1179,7 +1264,7 @@ void close_ioc(struct ioc_in_use *piiu)
|
||||
*
|
||||
* NOTE: potential race condition here can result
|
||||
* in two copies of the repeater being spawned
|
||||
* however the repeater detectes this, prints a message,
|
||||
* however the repeater detects this, prints a message,
|
||||
* and lets the other task start the repeater.
|
||||
*
|
||||
* QUESTION: is there a better way to test for a port in use?
|
||||
@@ -1198,12 +1283,11 @@ void close_ioc(struct ioc_in_use *piiu)
|
||||
*/
|
||||
int repeater_installed()
|
||||
{
|
||||
int status;
|
||||
int sock;
|
||||
struct sockaddr_in bd;
|
||||
int true = 1;
|
||||
|
||||
int installed = FALSE;
|
||||
int status;
|
||||
SOCKET sock;
|
||||
struct sockaddr_in bd;
|
||||
int true = 1;
|
||||
int installed = FALSE;
|
||||
|
||||
LOCK;
|
||||
|
||||
@@ -1211,7 +1295,7 @@ int repeater_installed()
|
||||
sock = socket( AF_INET, /* domain */
|
||||
SOCK_DGRAM, /* type */
|
||||
0); /* deflt proto */
|
||||
if(sock == ERROR){
|
||||
if(sock == INVALID_SOCKET) {
|
||||
UNLOCK;
|
||||
return installed;
|
||||
}
|
||||
@@ -1219,7 +1303,7 @@ int repeater_installed()
|
||||
memset((char *)&bd,0,sizeof bd);
|
||||
bd.sin_family = AF_INET;
|
||||
bd.sin_addr.s_addr = INADDR_ANY;
|
||||
bd.sin_port = htons(CA_CLIENT_PORT);
|
||||
bd.sin_port = htons(ca_static->ca_repeater_port);
|
||||
status = bind( sock,
|
||||
(struct sockaddr *) &bd,
|
||||
sizeof bd);
|
||||
@@ -1417,31 +1501,25 @@ unsigned long cacRingBufferWriteSize(struct ca_buffer *pBuf, int contiguous)
|
||||
*
|
||||
* o Indicates failure by setting ptr to nill
|
||||
*
|
||||
* o Calls non posix gethostname()
|
||||
*
|
||||
* o We want the full domain name however neither
|
||||
* gethostbyname() or gethostname() appear to provide it
|
||||
* under SUNOS.
|
||||
* o Calls non posix gethostbyname() so that we get DNS style names
|
||||
* (gethostbyname() should be available with most BSD sock libs)
|
||||
*
|
||||
* vxWorks user may need to configure a DNS format name for the
|
||||
* vxWorks user will need to configure a DNS format name for the
|
||||
* host name if they wish to be cnsistent with UNIX and VMS hosts.
|
||||
*
|
||||
*/
|
||||
char *localHostName()
|
||||
{
|
||||
int size;
|
||||
int status;
|
||||
char nameBuf[MAXHOSTNAMELEN];
|
||||
char *pName;
|
||||
char *pTmp;
|
||||
int size;
|
||||
int status;
|
||||
char pName[MAXHOSTNAMELEN];
|
||||
char *pTmp;
|
||||
|
||||
status = gethostname(nameBuf, sizeof(nameBuf));
|
||||
status = gethostname(pName, sizeof(pName));
|
||||
if(status){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pName = nameBuf;
|
||||
|
||||
size = strlen(pName)+1;
|
||||
pTmp = malloc(size);
|
||||
if(!pTmp){
|
||||
@@ -1459,7 +1537,7 @@ char *localHostName()
|
||||
* caAddConfiguredAddr()
|
||||
*/
|
||||
void caAddConfiguredAddr(ELLLIST *pList, ENV_PARAM *pEnv,
|
||||
int socket, int port)
|
||||
SOCKET socket, int port)
|
||||
{
|
||||
caAddrNode *pNode;
|
||||
ENV_PARAM list;
|
||||
@@ -1572,3 +1650,36 @@ void caPrintAddrList(ELLLIST *pList)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caFetchPortConfig()
|
||||
*/
|
||||
unsigned caFetchPortConfig(ENV_PARAM *pEnv, unsigned defaultPort)
|
||||
{
|
||||
long longStatus;
|
||||
long port;
|
||||
|
||||
longStatus = envGetLongConfigParam(pEnv, &port);
|
||||
if (longStatus!=0) {
|
||||
port = defaultPort;
|
||||
ca_printf ("EPICS \"%s\" integer fetch failed\n", pEnv->name);
|
||||
ca_printf ("setting \"%s\" = %ld\n", pEnv->name, port);
|
||||
}
|
||||
|
||||
/*
|
||||
* Thus must be a server port that will fit in a signed
|
||||
* short
|
||||
*/
|
||||
if (port <= IPPORT_USERRESERVED || port>SHRT_MAX) {
|
||||
ca_printf ("EPICS \"%s\" out of range\n", pEnv->name);
|
||||
/*
|
||||
* Quit if the port is wrong due CA coding error
|
||||
*/
|
||||
assert (port != defaultPort);
|
||||
port = defaultPort;
|
||||
ca_printf ("Setting \"%s\" = %ld\n", pEnv->name, port);
|
||||
}
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
|
||||
309
src/ca/iocinf.h
309
src/ca/iocinf.h
@@ -53,7 +53,27 @@
|
||||
#ifndef INCiocinfh
|
||||
#define INCiocinfh
|
||||
|
||||
static char *iocinfhSccsId = "$Id$";
|
||||
#ifdef CA_GLBLSOURCE
|
||||
# define GLBLTYPE
|
||||
#else
|
||||
# define GLBLTYPE extern
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
# define VERSIONID(NAME,VERS) \
|
||||
char *EPICS_CAS_VID_ ## NAME = VERS;
|
||||
#else /*__STDC__*/
|
||||
# define VERSIONID(NAME,VERS) \
|
||||
char *EPICS_CAS_VID_/* */NAME = VERS;
|
||||
#endif /*__STDC__*/
|
||||
|
||||
#ifdef CAC_VERSION_GLOBAL
|
||||
# define HDRVERSIONID(NAME,VERS) VERSIONID(NAME,VERS)
|
||||
#else /*CAC_VERSION_GLOBAL*/
|
||||
# define HDRVERSIONID(NAME,VERS)
|
||||
#endif /*CAC_VERSION_GLOBAL*/
|
||||
|
||||
HDRVERSIONID(iocinfh, "$Id$")
|
||||
|
||||
/*
|
||||
* ANSI C includes
|
||||
@@ -64,6 +84,7 @@ static char *iocinfhSccsId = "$Id$";
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
/*
|
||||
@@ -97,7 +118,7 @@ static char *iocinfhSccsId = "$Id$";
|
||||
# define NBBY 8 /* number of bits per byte */
|
||||
#endif
|
||||
|
||||
#define SELECT_POLL 50000 /* units micro-sec */
|
||||
#define MSEC_PER_SEC 1000
|
||||
#define USEC_PER_SEC 1000000
|
||||
|
||||
/*
|
||||
@@ -139,26 +160,38 @@ struct putCvrtBuf{
|
||||
#define CA_DO_RECVS 2
|
||||
|
||||
struct pending_io_event{
|
||||
ELLNODE node;
|
||||
void (*io_done_sub)();
|
||||
void *io_done_arg;
|
||||
ELLNODE node;
|
||||
void (*io_done_sub)();
|
||||
void *io_done_arg;
|
||||
};
|
||||
|
||||
typedef unsigned long ca_time;
|
||||
typedef struct timeval ca_time;
|
||||
|
||||
#define LD_CA_TIME(FLOAT_TIME,PCATIME) \
|
||||
((PCATIME)->tv_sec = (FLOAT_TIME), \
|
||||
(PCATIME)->tv_usec = ((FLOAT_TIME)-(PCATIME)->tv_sec)*USEC_PER_SEC)
|
||||
|
||||
/*
|
||||
* dont adjust
|
||||
*/
|
||||
#define CA_CURRENT_TIME 0
|
||||
#ifdef CA_GLBLSOURCE
|
||||
const ca_time CA_CURRENT_TIME = {0,0};
|
||||
#else /*CA_GLBLSOURCE*/
|
||||
extern const ca_time CA_CURRENT_TIME;
|
||||
#endif /*CA_GLBLSOURCE*/
|
||||
|
||||
/*
|
||||
* these control the duration and period of name resolution
|
||||
* broadcasts
|
||||
*
|
||||
* MAXCONNTRIES must be less than the number of bits in type long
|
||||
*/
|
||||
#define MAXCONNTRIES 60 /* N conn retries on unchanged net */
|
||||
#define CA_RECAST_DELAY 1 /* initial int sec to next recast */
|
||||
#define CA_RECAST_PORT_MASK 0x3 /* random retry interval off port */
|
||||
#define CA_RECAST_PERIOD 5 /* ul on retry period long term */
|
||||
#define MAXCONNTRIES 30 /* N conn retries on unchanged net */
|
||||
|
||||
#define SELECT_POLL (0.1) /* units sec - polls into recast */
|
||||
#define CA_RECAST_DELAY (0.1) /* initial delay to next recast (sec) */
|
||||
#define CA_RECAST_PORT_MASK 0xff /* random retry interval off port */
|
||||
#define CA_RECAST_PERIOD (5.0) /* ul on retry period long term (sec) */
|
||||
|
||||
/*
|
||||
* these two control the period of connection verifies
|
||||
@@ -166,15 +199,21 @@ typedef unsigned long ca_time;
|
||||
* long we will wait for an echo reply before we
|
||||
* give up and flag the connection for disconnect
|
||||
* - CA_ECHO_TIMEOUT.
|
||||
*
|
||||
* CA_CONN_VERIFY_PERIOD is normally obtained from an
|
||||
* EPICS environment variable.
|
||||
*/
|
||||
#define CA_ECHO_TIMEOUT 5 /* disconn if no echo reply tmo */
|
||||
#define CA_CONN_VERIFY_PERIOD 30 /* how often to request echo */
|
||||
#define CA_ECHO_TIMEOUT 5.0 /* (sec) disconn no echo reply tmo */
|
||||
#define CA_CONN_VERIFY_PERIOD 30.0 /* (sec) how often to request echo */
|
||||
|
||||
/*
|
||||
* only used when communicating with old servers
|
||||
*/
|
||||
#define CA_RETRY_PERIOD 5 /* int sec to next keepalive */
|
||||
|
||||
#define N_REPEATER_TRIES_PRIOR_TO_MSG 50
|
||||
#define REPEATER_TRY_PERIOD (0.1)
|
||||
|
||||
#ifdef vxWorks
|
||||
typedef struct caclient_put_notify{
|
||||
ELLNODE node;
|
||||
@@ -192,10 +231,12 @@ typedef struct caclient_put_notify{
|
||||
/*
|
||||
* ! lock needs to be applied when an id is allocated !
|
||||
*/
|
||||
#define CLIENT_ID_WIDTH 20 /* bits (1 million before rollover) */
|
||||
#define CLIENT_HASH_TBL_SIZE (1<<12)
|
||||
#define CLIENT_ID_WIDTH 28 /* bits */
|
||||
#define CLIENT_ID_COUNT (1<<CLIENT_ID_WIDTH)
|
||||
#define CLIENT_ID_MASK (CLIENT_ID_COUNT-1)
|
||||
#define CLIENT_ID_ALLOC (CLIENT_ID_MASK&nextBucketId++)
|
||||
#define CLIENT_FAST_ID_ALLOC (CLIENT_ID_MASK&nextFastBucketId++)
|
||||
#define CLIENT_SLOW_ID_ALLOC (CLIENT_ID_MASK&nextSlowBucketId++)
|
||||
|
||||
#define SEND_RETRY_COUNT_INIT 100
|
||||
|
||||
@@ -215,12 +256,11 @@ typedef struct caclient_put_notify{
|
||||
(ca_static->ca_fd_register_func)
|
||||
#define fd_register_arg (ca_static->ca_fd_register_arg)
|
||||
#define post_msg_active (ca_static->ca_post_msg_active)
|
||||
#define send_msg_active (ca_static->ca_send_msg_active)
|
||||
#define sprintf_buf (ca_static->ca_sprintf_buf)
|
||||
#define pBucket (ca_static->ca_pBucket)
|
||||
#define nextBucketId (ca_static->ca_nextBucketId)
|
||||
#define readch (ca_static->ca_readch)
|
||||
#define writech (ca_static->ca_writech)
|
||||
#define pSlowBucket (ca_static->ca_pSlowBucket)
|
||||
#define pFastBucket (ca_static->ca_pFastBucket)
|
||||
#define nextSlowBucketId (ca_static->ca_nextSlowBucketId)
|
||||
#define nextFastBucketId (ca_static->ca_nextFastBucketId)
|
||||
|
||||
#if defined(vxWorks)
|
||||
# define io_done_sem (ca_static->ca_io_done_sem)
|
||||
@@ -287,26 +327,27 @@ typedef struct ioc_in_use{
|
||||
ELLNODE node;
|
||||
ELLLIST chidlist; /* chans on this connection */
|
||||
ELLLIST destAddr;
|
||||
struct ca_static *pcas;
|
||||
int sock_chan;
|
||||
int sock_proto;
|
||||
unsigned minor_version_number;
|
||||
unsigned contiguous_msg_count;
|
||||
struct ca_buffer send;
|
||||
struct ca_buffer recv;
|
||||
struct extmsg curMsg;
|
||||
unsigned curMsgBytes;
|
||||
void *pCurData;
|
||||
unsigned long curDataMax;
|
||||
unsigned long curDataBytes;
|
||||
ca_time timeAtLastRecv;
|
||||
ca_time timeAtSendBlock;
|
||||
ca_time timeAtEchoRequest;
|
||||
unsigned long curDataMax;
|
||||
unsigned long curDataBytes;
|
||||
struct ca_buffer send;
|
||||
struct ca_buffer recv;
|
||||
struct extmsg curMsg;
|
||||
struct ca_static *pcas;
|
||||
void *pCurData;
|
||||
void (*sendBytes)(struct ioc_in_use *);
|
||||
void (*recvBytes)(struct ioc_in_use *);
|
||||
void (*procInput)(struct ioc_in_use *);
|
||||
SOCKET sock_chan;
|
||||
int sock_proto;
|
||||
unsigned minor_version_number;
|
||||
unsigned contiguous_msg_count;
|
||||
unsigned curMsgBytes;
|
||||
unsigned read_seq;
|
||||
unsigned cur_read_seq;
|
||||
unsigned minfreespace;
|
||||
char host_name_str[32];
|
||||
|
||||
/*
|
||||
@@ -327,12 +368,23 @@ typedef struct beaconHashEntry{
|
||||
struct beaconHashEntry *pNext;
|
||||
IIU *piiu;
|
||||
struct in_addr inetAddr;
|
||||
int timeStamp;
|
||||
int averagePeriod;
|
||||
ca_time timeStamp;
|
||||
ca_real averagePeriod;
|
||||
}bhe;
|
||||
|
||||
/*
|
||||
* This struct allocated off of a free list
|
||||
* so that the select() ctx is thread safe
|
||||
*/
|
||||
typedef struct {
|
||||
ELLNODE node;
|
||||
fd_set readMask;
|
||||
fd_set writeMask;
|
||||
fd_set writeSave;
|
||||
fd_set readSave;
|
||||
}caFDInfo;
|
||||
|
||||
struct ca_static{
|
||||
IIU *ca_piiuCast;
|
||||
ELLLIST ca_iiuList;
|
||||
ELLLIST ca_ioeventlist;
|
||||
ELLLIST ca_free_event_list;
|
||||
@@ -343,44 +395,54 @@ struct ca_static{
|
||||
ELLLIST activeCASGOP;
|
||||
ELLLIST freeCASGOP;
|
||||
ELLLIST putCvrtBuf;
|
||||
long ca_pndrecvcnt;
|
||||
void (*ca_exception_func)();
|
||||
void *ca_exception_arg;
|
||||
void (*ca_connection_func)();
|
||||
void *ca_connection_arg;
|
||||
void (*ca_fd_register_func)();
|
||||
void *ca_fd_register_arg;
|
||||
short ca_exit_in_progress;
|
||||
unsigned short ca_post_msg_active;
|
||||
short ca_repeater_contacted;
|
||||
unsigned short ca_send_msg_active;
|
||||
char ca_sprintf_buf[256];
|
||||
BUCKET *ca_pBucket;
|
||||
unsigned long ca_nextBucketId;
|
||||
bhe *ca_beaconHash[BHT_INET_ADDR_MASK+1];
|
||||
char *ca_pUserName;
|
||||
char *ca_pHostName;
|
||||
unsigned ca_conn_n_tries;
|
||||
ELLLIST fdInfoFreeList;
|
||||
ELLLIST fdInfoList;
|
||||
ca_time ca_conn_next_retry;
|
||||
ca_time ca_conn_retry_delay;
|
||||
fd_set ca_readch;
|
||||
fd_set ca_writech;
|
||||
ca_time ca_last_repeater_try;
|
||||
ca_real ca_connectTMO;
|
||||
long ca_pndrecvcnt;
|
||||
unsigned long ca_nextSlowBucketId;
|
||||
unsigned long ca_nextFastBucketId;
|
||||
IIU *ca_piiuCast;
|
||||
void (*ca_exception_func)
|
||||
(struct exception_handler_args);
|
||||
void *ca_exception_arg;
|
||||
void (*ca_connection_func)
|
||||
(struct connection_handler_args);
|
||||
void *ca_connection_arg;
|
||||
void (*ca_fd_register_func)
|
||||
(void *, SOCKET, int);
|
||||
void *ca_fd_register_arg;
|
||||
char *ca_pUserName;
|
||||
char *ca_pHostName;
|
||||
BUCKET *ca_pSlowBucket;
|
||||
BUCKET *ca_pFastBucket;
|
||||
bhe *ca_beaconHash[BHT_INET_ADDR_MASK+1];
|
||||
unsigned ca_repeater_tries;
|
||||
unsigned ca_search_retry; /* search retry seq number */
|
||||
unsigned short ca_server_port;
|
||||
unsigned short ca_repeater_port;
|
||||
char ca_sprintf_buf[256];
|
||||
unsigned ca_post_msg_active:1;
|
||||
unsigned ca_manage_conn_active:1;
|
||||
unsigned ca_repeater_contacted:1;
|
||||
#if defined(vxWorks)
|
||||
SEM_ID ca_io_done_sem;
|
||||
SEM_ID ca_blockSem;
|
||||
void *ca_evuser;
|
||||
SEM_ID ca_client_lock;
|
||||
SEM_ID ca_event_lock; /* dont allow events to preempt */
|
||||
SEM_ID ca_putNotifyLock;
|
||||
int ca_tid;
|
||||
ELLLIST ca_local_chidlist;
|
||||
ELLLIST ca_dbfree_ev_list;
|
||||
ELLLIST ca_lcl_buff_list;
|
||||
ELLLIST ca_putNotifyQue;
|
||||
int ca_event_tid;
|
||||
unsigned ca_local_ticks;
|
||||
int recv_tid;
|
||||
ELLLIST ca_taskVarList;
|
||||
void *ca_evuser;
|
||||
int ca_event_tid;
|
||||
int ca_tid;
|
||||
int recv_tid;
|
||||
unsigned ca_local_ticks;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -419,22 +481,9 @@ typedef struct{
|
||||
|
||||
|
||||
/*
|
||||
GLOBAL VARIABLES
|
||||
There should only be one - add others to ca_static above -joh
|
||||
*/
|
||||
#ifdef CA_GLBLSOURCE
|
||||
# ifdef VAXC
|
||||
# define GLBLTYPE globaldef
|
||||
# else
|
||||
# define GLBLTYPE
|
||||
# endif
|
||||
#else
|
||||
# ifdef VAXC
|
||||
# define GLBLTYPE globalref
|
||||
# else
|
||||
# define GLBLTYPE extern
|
||||
# endif
|
||||
#endif
|
||||
* GLOBAL VARIABLES
|
||||
* There should only be one - add others to ca_static above -joh
|
||||
*/
|
||||
|
||||
GLBLTYPE
|
||||
struct ca_static *ca_static;
|
||||
@@ -444,31 +493,30 @@ struct ca_static *ca_static;
|
||||
*
|
||||
*/
|
||||
|
||||
void cac_send_msg();
|
||||
void cac_mux_io(struct timeval *ptimeout);
|
||||
int repeater_installed();
|
||||
void search_msg(chid chix, int reply_type);
|
||||
int ca_request_event(evid monix);
|
||||
void ca_busy_message(struct ioc_in_use *piiu);
|
||||
void ca_ready_message(struct ioc_in_use *piiu);
|
||||
void noop_msg(struct ioc_in_use *piiu);
|
||||
void echo_request(struct ioc_in_use *piiu);
|
||||
void issue_claim_channel(struct ioc_in_use *piiu, chid pchan);
|
||||
void issue_identify_client(struct ioc_in_use *piiu);
|
||||
void issue_client_host_name(struct ioc_in_use *piiu);
|
||||
int ca_defunct(void);
|
||||
int ca_printf(char *pformat, ...);
|
||||
void manage_conn(int silent);
|
||||
void mark_server_available(struct in_addr *pnet_addr);
|
||||
void flow_control(struct ioc_in_use *piiu);
|
||||
int broadcast_addr(struct in_addr *pcastaddr);
|
||||
int local_addr(int s, struct sockaddr_in *plcladdr);
|
||||
void ca_repeater();
|
||||
void cac_recv_task(int tid);
|
||||
void cac_io_done(int lock);
|
||||
void ca_sg_init(void);
|
||||
void ca_sg_shutdown(struct ca_static *ca_temp);
|
||||
int cac_select_io(struct timeval *ptimeout, int flags);
|
||||
void cac_send_msg(void);
|
||||
void cac_mux_io(struct timeval *ptimeout);
|
||||
int repeater_installed(void);
|
||||
int search_msg(chid chix, int reply_type);
|
||||
int ca_request_event(evid monix);
|
||||
void ca_busy_message(struct ioc_in_use *piiu);
|
||||
void ca_ready_message(struct ioc_in_use *piiu);
|
||||
void noop_msg(struct ioc_in_use *piiu);
|
||||
int echo_request(struct ioc_in_use *piiu, ca_time *pCurrentTime);
|
||||
void issue_claim_channel(struct ioc_in_use *piiu, chid pchan);
|
||||
void issue_identify_client(struct ioc_in_use *piiu);
|
||||
void issue_client_host_name(struct ioc_in_use *piiu);
|
||||
int ca_defunct(void);
|
||||
int ca_printf(char *pformat, ...);
|
||||
void manage_conn(int silent);
|
||||
void mark_server_available(struct in_addr *pnet_addr);
|
||||
void flow_control(struct ioc_in_use *piiu);
|
||||
int broadcast_addr(struct in_addr *pcastaddr);
|
||||
void ca_repeater(void);
|
||||
void cac_recv_task(int tid);
|
||||
void cac_io_done(int lock);
|
||||
void ca_sg_init(void);
|
||||
void ca_sg_shutdown(struct ca_static *ca_temp);
|
||||
int cac_select_io(struct timeval *ptimeout, int flags);
|
||||
void caHostFromInetAddr(
|
||||
struct in_addr *pnet_addr,
|
||||
char *pBuf,
|
||||
@@ -481,8 +529,8 @@ int post_msg(
|
||||
unsigned long blockSize
|
||||
);
|
||||
int alloc_ioc(
|
||||
struct in_addr *pnet_addr,
|
||||
struct ioc_in_use **ppiiu
|
||||
struct in_addr *pnet_addr,
|
||||
struct ioc_in_use **ppiiu
|
||||
);
|
||||
unsigned long cacRingBufferWrite(
|
||||
struct ca_buffer *pRing,
|
||||
@@ -502,26 +550,9 @@ unsigned long cacRingBufferReadSize(
|
||||
struct ca_buffer *pBuf,
|
||||
int contiguous);
|
||||
|
||||
void caSetupAddrList(
|
||||
ELLLIST *pList,
|
||||
int socket);
|
||||
char *localUserName(void);
|
||||
|
||||
void caDiscoverInterfaces(
|
||||
ELLLIST *pList,
|
||||
int socket,
|
||||
int port);
|
||||
|
||||
void caAddConfiguredAddr(
|
||||
ELLLIST *pList,
|
||||
ENV_PARAM *pEnv,
|
||||
int socket,
|
||||
int port);
|
||||
|
||||
void caPrintAddrList();
|
||||
|
||||
char *localUserName();
|
||||
|
||||
char *localHostName();
|
||||
char *localHostName(void);
|
||||
|
||||
int create_net_chan(
|
||||
struct ioc_in_use **ppiiu,
|
||||
@@ -529,30 +560,39 @@ struct in_addr *pnet_addr, /* only used by TCP connections */
|
||||
int net_proto
|
||||
);
|
||||
|
||||
int ca_check_for_fp();
|
||||
int ca_check_for_fp(void);
|
||||
|
||||
void caSetupBCastAddrList (ELLLIST *pList, SOCKET sock, unsigned port);
|
||||
|
||||
int ca_os_independent_init (void);
|
||||
|
||||
void freeBeaconHash(struct ca_static *ca_temp);
|
||||
void removeBeaconInetAddr(struct in_addr *pnet_addr);
|
||||
bhe *lookupBeaconInetAddr(struct in_addr *pnet_addr);
|
||||
bhe *createBeaconHashEntry(struct in_addr *pnet_addr);
|
||||
int cac_setup_recv_thread(IIU *piiu);
|
||||
void close_ioc(IIU *piiu);
|
||||
void notify_ca_repeater();
|
||||
void cac_clean_iiu_list();
|
||||
void notify_ca_repeater(void);
|
||||
void cac_clean_iiu_list(void);
|
||||
|
||||
void ca_process_input_queue();
|
||||
void cac_flush_internal();
|
||||
void cac_block_for_io_completion();
|
||||
void cac_block_for_sg_completion();
|
||||
void ca_process_input_queue(void);
|
||||
void cac_flush_internal(void);
|
||||
void cac_block_for_io_completion(struct timeval *pTV);
|
||||
void cac_block_for_sg_completion(CASG *pcasg, struct timeval *pTV);
|
||||
void os_specific_sg_create(CASG *pcasg);
|
||||
void os_specific_sg_delete(CASG *pcasg);
|
||||
void os_specific_sg_io_complete(CASG *pcasg);
|
||||
int cac_os_depen_init(struct ca_static *pcas);
|
||||
void ca_process_exit(struct ca_static *ca_temp);
|
||||
int cac_add_task_variable(struct ca_static *);
|
||||
void ca_spawn_repeater();
|
||||
void cac_os_depen_exit (struct ca_static *pcas);
|
||||
void ca_process_exit();
|
||||
void ca_spawn_repeater(void);
|
||||
typedef void CACVRTFUNC(void *pSrc, void *pDest, int hton, unsigned long count);
|
||||
|
||||
void cac_gettimeval(struct timeval *pt);
|
||||
/* returns A - B in floating secs */
|
||||
ca_real cac_time_diff(ca_time *pTVA, ca_time *pTVB);
|
||||
/* returns A + B in integer secs & integer usec */
|
||||
ca_time cac_time_sum(ca_time *pTVA, ca_time *pTVB);
|
||||
void caIOBlockFree(evid pIOBlock);
|
||||
void clearChannelResources(unsigned id);
|
||||
|
||||
/*
|
||||
* !!KLUDGE!!
|
||||
@@ -561,6 +601,7 @@ typedef void CACVRTFUNC(void *pSrc, void *pDest, int hton, unsigned long count);
|
||||
* to include both dbAccess.h and db_access.h at the
|
||||
* same time.
|
||||
*/
|
||||
#define M_dbAccess (501 <<16) /*Database Access Routines */
|
||||
#define S_db_Blocked (M_dbAccess|39) /*Request is Blocked*/
|
||||
|
||||
#endif /* this must be the last line in this file */
|
||||
|
||||
@@ -19,33 +19,61 @@
|
||||
* .07 041194 joh New command added for CA V4.2 - access rights
|
||||
*
|
||||
* .08 050594 joh New command added for CA V4.3 - echo request
|
||||
*
|
||||
* .09 050594 joh New command added for CA V4.3 - repeater fanout register
|
||||
*
|
||||
* .10 050594 joh New command added for CA V4.3 - wakeup the server
|
||||
*/
|
||||
|
||||
#define __IOCMSG__
|
||||
|
||||
static char *iocmsghSccsId = "$Id$ CA version 4.3";
|
||||
HDRVERSIONID(iocmsgh, "@(#) $Id$ CA version 4.4")
|
||||
|
||||
/* TCP/UDP port number (bumped each protocol change) */
|
||||
#define CA_PROTOCOL_VERSION 4
|
||||
#define CA_MINOR_VERSION 3
|
||||
#define CA_MINOR_VERSION 4
|
||||
#define CA_UKN_MINOR_VERSION 0 /* unknown minor version */
|
||||
#if CA_PROTOCOL_VERSION == 4
|
||||
#define CA_V41(MAJOR,MINOR) ((MINOR)>=1)
|
||||
#define CA_V42(MAJOR,MINOR) ((MINOR)>=2)
|
||||
#define CA_V43(MAJOR,MINOR) ((MINOR)>=3)
|
||||
#else
|
||||
#define CA_V44(MAJOR,MINOR) ((MINOR)>=4)
|
||||
#elif CA_PROTOCOL_VERSION > 4
|
||||
#define CA_V41(MAJOR,MINOR) ( 1 )
|
||||
#define CA_V42(MAJOR,MINOR) ( 1 )
|
||||
#define CA_V43(MAJOR,MINOR) ( 1 )
|
||||
#define CA_V44(MAJOR,MINOR) ( 1 )
|
||||
#else
|
||||
#define CA_V41(MAJOR,MINOR) ( 0 )
|
||||
#define CA_V42(MAJOR,MINOR) ( 0 )
|
||||
#define CA_V43(MAJOR,MINOR) ( 0 )
|
||||
#define CA_V44(MAJOR,MINOR) ( 0 )
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NOTE: These port numbers are only used if the CA repeater and
|
||||
* CA server port numbers cant be obtained from the EPICS
|
||||
* environment variables "EPICS_CA_REPEATER_PORT" and
|
||||
* "EPICS_CA_SERVER_PORT"
|
||||
*/
|
||||
#define CA_PORT_BASE IPPORT_USERRESERVED + 56
|
||||
#define CA_SERVER_PORT (CA_PORT_BASE+CA_PROTOCOL_VERSION*2)
|
||||
#define CA_CLIENT_PORT (CA_PORT_BASE+CA_PROTOCOL_VERSION*2+1)
|
||||
#define CA_REPEATER_PORT (CA_PORT_BASE+CA_PROTOCOL_VERSION*2+1)
|
||||
|
||||
#define MAX_UDP 1024
|
||||
#define MAX_TCP (MAX_UDP*16) /* so waveforms fit */
|
||||
#define MAX_MSG_SIZE (MAX_TCP) /* the larger of tcp and udp max */
|
||||
|
||||
/*
|
||||
* architecture independent types
|
||||
*
|
||||
* (so far this works on all archs we have ported to)
|
||||
*/
|
||||
typedef unsigned short ca_uint16_t;
|
||||
typedef unsigned int ca_uint32_t;
|
||||
typedef float ca_float32_t;
|
||||
|
||||
|
||||
/* values for m_cmmd */
|
||||
#define IOC_NOOP 0 /* do nothing, but verify TCP */
|
||||
#define IOC_EVENT_ADD 1 /* add an event */
|
||||
@@ -54,6 +82,7 @@ static char *iocmsghSccsId = "$Id$ CA version 4.3";
|
||||
#define IOC_WRITE 4 /* write a channel value */
|
||||
#define IOC_SNAPSHOT 5 /* snapshot of the system */
|
||||
#define IOC_SEARCH 6 /* IOC channel search */
|
||||
/* 7 */
|
||||
#define IOC_EVENTS_OFF 8 /* flow control */
|
||||
#define IOC_EVENTS_ON 9 /* flow control */
|
||||
#define IOC_READ_SYNC 10 /* purge old reads */
|
||||
@@ -62,6 +91,7 @@ static char *iocmsghSccsId = "$Id$ CA version 4.3";
|
||||
#define IOC_RSRV_IS_UP 13 /* CA server has joined the net */
|
||||
#define IOC_NOT_FOUND 14 /* channel not found */
|
||||
#define IOC_READ_NOTIFY 15 /* add a one shot event */
|
||||
/* 16 */
|
||||
#define REPEATER_CONFIRM 17 /* registration confirmation */
|
||||
#define IOC_CLAIM_CIU 18 /* client claims resource in server */
|
||||
#define IOC_WRITE_NOTIFY 19 /* notify after write chan value */
|
||||
@@ -69,6 +99,8 @@ static char *iocmsghSccsId = "$Id$ CA version 4.3";
|
||||
#define IOC_HOST_NAME 21 /* CA V4.1 identify client */
|
||||
#define IOC_ACCESS_RIGHTS 22 /* CA V4.2 asynch access rights chg */
|
||||
#define IOC_ECHO 23 /* CA V4.3 connection verify */
|
||||
#define REPEATER_REGISTER 24 /* registr for repeater fan out */
|
||||
#define IOC_SIGNAL 25 /* knock the server out of select */
|
||||
|
||||
/*
|
||||
* for use with search and not_found (if search fails and
|
||||
@@ -98,12 +130,8 @@ static char *iocmsghSccsId = "$Id$ CA version 4.3";
|
||||
#define CA_ACCESS_RIGHT_WRITE (1<<1)
|
||||
|
||||
/*
|
||||
* Required Message Alignment
|
||||
*
|
||||
* Determined by the architecture with the most restrictive
|
||||
* alignment requirements (currently the SPARC).
|
||||
*
|
||||
* octal rounding
|
||||
* All structures passed in the protocol must have individual
|
||||
* fields aligned on natural boundaries.
|
||||
*
|
||||
* NOTE: all structures declared in this file must have a
|
||||
* byte count which is evenly divisible by 8 for the SPARC.
|
||||
@@ -114,25 +142,25 @@ static char *iocmsghSccsId = "$Id$ CA version 4.3";
|
||||
* the common part of each message sent/recv by the
|
||||
* CA server.
|
||||
*/
|
||||
struct extmsg {
|
||||
unsigned short m_cmmd; /* operation to be performed */
|
||||
unsigned short m_postsize; /* size of message extension */
|
||||
unsigned short m_type; /* operation data type */
|
||||
unsigned short m_count; /* operation data count */
|
||||
unsigned long m_cid; /* channel identifier */
|
||||
unsigned long m_available; /* undefined message location for use
|
||||
typedef struct extmsg {
|
||||
ca_uint16_t m_cmmd; /* operation to be performed */
|
||||
ca_uint16_t m_postsize; /* size of message extension */
|
||||
ca_uint16_t m_type; /* operation data type */
|
||||
ca_uint16_t m_count; /* operation data count */
|
||||
ca_uint32_t m_cid; /* channel identifier */
|
||||
ca_uint32_t m_available; /* undefined message location for use
|
||||
* by client processes */
|
||||
};
|
||||
}caHdr;
|
||||
|
||||
/*
|
||||
* for monitor (event) message extension
|
||||
*/
|
||||
struct mon_info{
|
||||
float m_lval; /* low delta */
|
||||
float m_hval; /* high delta */
|
||||
float m_toval; /* period btween samples */
|
||||
unsigned short m_mask; /* event select mask */
|
||||
unsigned short m_pad; /* extend to 32 bits */
|
||||
ca_float32_t m_lval; /* low delta */
|
||||
ca_float32_t m_hval; /* high delta */
|
||||
ca_float32_t m_toval; /* period btween samples */
|
||||
ca_uint16_t m_mask; /* event select mask */
|
||||
ca_uint16_t m_pad; /* extend to 32 bits */
|
||||
};
|
||||
|
||||
struct monops { /* monitor req opi to ioc */
|
||||
|
||||
@@ -29,7 +29,7 @@ printf("%x\n", net_addr.s_addr);
|
||||
|
||||
|
||||
/* the above seems to be broken ? */
|
||||
ent = gethostbyaddr(&net, sizeof(net_addr), AF_INET);
|
||||
ent = gethostbyaddr(&addr, sizeof(net_addr), AF_INET);
|
||||
if(ent)
|
||||
printf("%s\n", ent->h_name);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id$
|
||||
* $Id$
|
||||
*
|
||||
* N E T _ C O N V E R T . H
|
||||
* MACROS for rapid conversion between HOST data formats and those used
|
||||
@@ -10,151 +10,62 @@
|
||||
* to prevent a reseved operand fault.
|
||||
*
|
||||
* joh 03-16-94 Added double fp
|
||||
* joh 11-02-94 Moved all fp cvrt to functions in
|
||||
* convert.c
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/************************************************************************/
|
||||
/* So byte swapping can be performed in line for efficiency */
|
||||
/* (WINTCP has library routines with the same same functionality */
|
||||
/* but more than twice the delay) JH */
|
||||
/* WARNING: WILL NOT WORK ON TYPES FLOAT OR DOUBLE */
|
||||
/* (use *(long *)& to perform type convert without reformat) */
|
||||
/************************************************************************/
|
||||
|
||||
#ifdef LITTLE_ENDIAN
|
||||
# define ntohs(SHORT)\
|
||||
((unsigned short)(((short)(SHORT))<<8 | ((unsigned short)(SHORT))>>8 ))
|
||||
# define htons(SHORT)\
|
||||
((unsigned short)(((short)(SHORT))<<8 | ((unsigned short)(SHORT))>>8 ))
|
||||
#ifdef CA_LITTLE_ENDIAN
|
||||
# ifndef ntohs
|
||||
# define ntohs(SHORT)\
|
||||
( ((SHORT) & 0x00ff) << 8 | ((SHORT) & 0xff00) >> 8 )
|
||||
# endif
|
||||
# ifndef htons
|
||||
# define htons(SHORT)\
|
||||
( ((SHORT) & 0x00ff) << 8 | ((SHORT) & 0xff00) >> 8 )
|
||||
# endif
|
||||
#else
|
||||
# ifndef ntohs
|
||||
# define ntohs(SHORT) (SHORT)
|
||||
# endif
|
||||
# ifndef htons
|
||||
# define htons(SHORT) (SHORT)
|
||||
# endif
|
||||
# ifndef ntohs
|
||||
# define ntohs(SHORT) (SHORT)
|
||||
# endif
|
||||
# ifndef htons
|
||||
# define htons(SHORT) (SHORT)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LITTLE_ENDIAN
|
||||
# define ntohl(LONG)\
|
||||
(\
|
||||
((long)(LONG))<<24 |\
|
||||
((unsigned long)(LONG))>>24 |\
|
||||
(((long)(LONG))&0x00ff0000)>>8 |\
|
||||
(((long)(LONG))&0x0000ff00)<<8\
|
||||
)
|
||||
# define htonl(LONG)\
|
||||
(\
|
||||
((long)(LONG))<<24 |\
|
||||
((unsigned long)(LONG))>>24 |\
|
||||
(((long)(LONG))&0x00ff0000)>>8 |\
|
||||
(((long)(LONG))&0x0000ff00)<<8\
|
||||
)
|
||||
#else
|
||||
# ifndef ntohl
|
||||
# define ntohl(LONG) (LONG)
|
||||
# endif
|
||||
# ifndef htonl
|
||||
# define htonl(LONG) (LONG)
|
||||
# endif
|
||||
#ifdef CA_LITTLE_ENDIAN
|
||||
# ifndef ntohl
|
||||
# define ntohl(LONG)\
|
||||
(\
|
||||
((LONG) & 0xff000000) >> 24 |\
|
||||
((LONG) & 0x000000ff) << 24 |\
|
||||
((LONG) & 0x0000ff00) << 8 |\
|
||||
((LONG) & 0x00ff0000) >> 8\
|
||||
)
|
||||
# endif
|
||||
# ifndef htonl
|
||||
# define htonl(LONG)\
|
||||
(\
|
||||
((LONG) & 0x000000ff) << 24 |\
|
||||
((LONG) & 0xff000000) >> 24 |\
|
||||
((LONG) & 0x00ff0000) >> 8 |\
|
||||
((LONG) & 0x0000ff00) << 8\
|
||||
)
|
||||
# endif
|
||||
# else
|
||||
# ifndef ntohl
|
||||
# define ntohl(LONG) (LONG)
|
||||
# endif
|
||||
# ifndef htonl
|
||||
# define htonl(LONG) (LONG)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* So float convert can be performed in line */
|
||||
/* (THIS ASSUMES IEEE IS THE NETWORK FLOATING POINT FORMAT) */
|
||||
/************************************************************************/
|
||||
struct ieeeflt{
|
||||
unsigned mant :23;
|
||||
unsigned exp :8;
|
||||
unsigned sign :1;
|
||||
};
|
||||
|
||||
/* Exponent sign bias */
|
||||
#define IEEE_SB 127
|
||||
|
||||
/* Conversion Range */
|
||||
/* -126<exp<127 with mantissa of form 1.mant */
|
||||
#define EXPMINIEEE -126 /* min for norm # IEEE exponent */
|
||||
|
||||
#ifdef MIT_FLOAT
|
||||
|
||||
struct mitflt{
|
||||
unsigned mant1 :7;
|
||||
unsigned exp :8;
|
||||
unsigned sign :1;
|
||||
unsigned mant2 :16;
|
||||
};
|
||||
|
||||
/* Exponent sign bias */
|
||||
# define MIT_SB 129
|
||||
|
||||
/* Conversion Ranges */
|
||||
/* -128<exp<126 with mantissa of form 1.mant */
|
||||
# define EXPMAXMIT 126 /* max MIT exponent */
|
||||
# define EXPMINMIT -128 /* min MIT exponent */
|
||||
|
||||
/* passed by ref until beter alternative found */
|
||||
/* (this includes mapping of fringe reals to zero or infinity) */
|
||||
/* (byte swaps included in conversion */
|
||||
|
||||
# define htonf(MIT,IEEE)\
|
||||
{\
|
||||
long exp,mant,sign;\
|
||||
sign = ((struct mitflt *) (MIT))->sign;\
|
||||
if( (short)((struct mitflt *) (MIT))->exp < EXPMINIEEE + MIT_SB){\
|
||||
exp = 0;\
|
||||
mant = 0;\
|
||||
sign = 0;\
|
||||
}\
|
||||
else{\
|
||||
exp = (short)((struct mitflt *) (MIT))->exp-MIT_SB+IEEE_SB;\
|
||||
mant = (((struct mitflt *) (MIT))->mant1<<16) |\
|
||||
((struct mitflt *) (MIT))->mant2;\
|
||||
}\
|
||||
((struct ieeeflt *) (IEEE))->mant = mant;\
|
||||
((struct ieeeflt *) (IEEE))->exp = exp;\
|
||||
((struct ieeeflt *) (IEEE))->sign = sign;\
|
||||
*(long *)(IEEE) = ntohl(*(long*)(IEEE));\
|
||||
}
|
||||
|
||||
/*
|
||||
* sign must be forced to zero if the exponent is zero to prevent a reserved
|
||||
* operand fault- joh 9-13-90
|
||||
*/
|
||||
# define ntohf(IEEE,MIT)\
|
||||
{\
|
||||
long exp,mant2,mant1,sign;\
|
||||
*(long *)(IEEE) = htonl(*(long*)(IEEE));\
|
||||
if( (short)((struct ieeeflt *) (IEEE))->exp > EXPMAXMIT + IEEE_SB){\
|
||||
sign = ((struct ieeeflt *) (IEEE))->sign;\
|
||||
exp = EXPMAXMIT + MIT_SB;\
|
||||
mant2 = ~0;\
|
||||
mant1 = ~0;\
|
||||
}\
|
||||
else if( ((struct ieeeflt *) (IEEE))->exp == 0){\
|
||||
sign = 0;\
|
||||
exp = 0;\
|
||||
mant2 = 0;\
|
||||
mant1 = 0;\
|
||||
}\
|
||||
else{\
|
||||
sign = ((struct ieeeflt *) (IEEE))->sign;\
|
||||
exp = ((struct ieeeflt *) (IEEE))->exp+MIT_SB-IEEE_SB;\
|
||||
mant2 = ((struct ieeeflt *) (IEEE))->mant;\
|
||||
mant1 = ((struct ieeeflt *) (IEEE))->mant>>(unsigned)16;\
|
||||
}\
|
||||
((struct mitflt *) (MIT))->exp = exp;\
|
||||
((struct mitflt *) (MIT))->mant2 = mant2;\
|
||||
((struct mitflt *) (MIT))->mant1 = mant1;\
|
||||
((struct mitflt *) (MIT))->sign = sign;\
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
# define ntohf(NET,HOST) {*(float *)(HOST) = *(float *)(NET);}
|
||||
# define htonf(HOST,NET) {*(float *)(NET) = *(float *)(HOST);}
|
||||
#ifndef MIT_FLOAT
|
||||
#define htond(IEEEhost, IEEEnet) (*(IEEEnet) = *(IEEEhost))
|
||||
#define ntohd(IEEEnet, IEEEhost) (*(IEEEhost) = *(IEEEnet))
|
||||
#define htonf(IEEEhost, IEEEnet) (*(IEEEnet) = *(IEEEhost))
|
||||
#define ntohf(IEEEnet, IEEEhost) (*(IEEEhost) = *(IEEEnet))
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* netdb_depen.c */
|
||||
/* $Id$ */
|
||||
/* share/src/ca/$Id$ */
|
||||
/*
|
||||
* Author: Jeff Hill
|
||||
* Date: 04-05-94
|
||||
@@ -31,7 +31,7 @@
|
||||
*/
|
||||
|
||||
|
||||
static char *sccsId = "$Id$";
|
||||
static char *sccsId = "@(#) $Id$";
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
* .10 joh 112092 removed the requirement that VMS locking
|
||||
* pairs reside at the same C bracket level
|
||||
* .11 GeG 120992 support VMS/UCX
|
||||
* .12 CJM 130794 define MYERRNO properly for UCX
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -92,7 +93,7 @@ static char *os_depenhSccsId = "$Id$";
|
||||
# include <sys/types.h>
|
||||
# include <sys/socket.h>
|
||||
# include <netinet/in.h>
|
||||
# define __TIME /* dont include VMS CC time.h under MULTINET */
|
||||
# define __TIME_LOADED /* dont include VMS CC time.h under MULTINET */
|
||||
# include <sys/time.h>
|
||||
# include <tcp/errno.h>
|
||||
# include <ssdef>
|
||||
@@ -113,30 +114,64 @@ static char *os_depenhSccsId = "$Id$";
|
||||
# define CA_OS_CONFIGURED
|
||||
#endif /*VMS*/
|
||||
|
||||
#ifdef _WINDOWS
|
||||
# include <errno.h>
|
||||
# include <time.h>
|
||||
# include <windows.h>
|
||||
# include <winsock.h>
|
||||
# define CA_OS_CONFIGURED
|
||||
#endif /*_WINDOWS*/
|
||||
|
||||
#ifndef CA_OS_CONFIGURED
|
||||
#error Please define one of vxWorks, UNIX or VMS
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set the flag "CONVERSION_REQUIRED" if the architechure is
|
||||
* little endian or if the local floating point format isnt IEEE.
|
||||
* Big endin architecture is assumed. Otherwise set "CA_LITTLE_ENDIAN".
|
||||
*
|
||||
* Big endin architecture is assumed. Otherwise set "LITTLE_ENDIAN".
|
||||
*
|
||||
* IEEE floating point architecture assumed. Set "MIT_FLOAT" if
|
||||
* IEEE floating point architecture assumed. Set "CA_FLOAT_MIT" if
|
||||
* appropriate. No other floating point formats currently
|
||||
* supported.
|
||||
*/
|
||||
#ifdef VAX
|
||||
#define CONVERSION_REQUIRED
|
||||
#define MIT_FLOAT
|
||||
#define LITTLE_ENDIAN
|
||||
#if defined(VAX)
|
||||
# define CA_FLOAT_MIT
|
||||
# define CA_LITTLE_ENDIAN
|
||||
#elif defined(_X86_)
|
||||
# define CA_FLOAT_IEEE
|
||||
# define CA_LITTLE_ENDIAN
|
||||
#elif (defined(__ALPHA) || defined(__alpha)) && defined(VMS)
|
||||
# define CA_FLOAT_MIT
|
||||
# define CA_LITTLE_ENDIAN
|
||||
#elif (defined(__ALPHA) || defined(__alpha)) && defined(UNIX)
|
||||
# define CA_FLOAT_IEEE
|
||||
# define CA_LITTLE_ENDIAN
|
||||
#else
|
||||
# define CA_FLOAT_IEEE
|
||||
# define CA_BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
#ifdef __ALPHA
|
||||
/*
|
||||
* some architecture sanity checks
|
||||
*/
|
||||
#if defined(CA_BIG_ENDIAN) && defined(CA_LITTLE_ENDIAN)
|
||||
#error defined(CA_BIG_ENDIAN) && defined(CA_LITTLE_ENDIAN)
|
||||
#endif
|
||||
#if !defined(CA_BIG_ENDIAN) && !defined(CA_LITTLE_ENDIAN)
|
||||
#error !defined(CA_BIG_ENDIAN) && !defined(CA_LITTLE_ENDIAN)
|
||||
#endif
|
||||
#if defined(CA_FLOAT_IEEE) && defined(CA_FLOAT_MIT)
|
||||
#error defined(CA_FLOAT_IEEE) && defined(CA_FLOAT_MIT)
|
||||
#endif
|
||||
#if !defined(CA_FLOAT_IEEE) && !defined(CA_FLOAT_MIT)
|
||||
#error !defined(CA_FLOAT_IEEE) && !defined(CA_FLOAT_MIT)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* CONVERSION_REQUIRED is set if either the byte order
|
||||
* or the floating point does not match
|
||||
*/
|
||||
#if !defined(CA_FLOAT_IEEE) || !defined(CA_BIG_ENDIAN)
|
||||
#define CONVERSION_REQUIRED
|
||||
#define MIT_FLOAT
|
||||
#define LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
@@ -167,45 +202,57 @@ static char *os_depenhSccsId = "$Id$";
|
||||
#define LOCAL static
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
/* Provided to enforce one thread at a time code sections */
|
||||
/* independent of a particular operating system */
|
||||
/************************************************************************/
|
||||
/* delay for when a poll is used */
|
||||
/* NOTE: DELAYTICKS must be less than TICKSPERSEC */
|
||||
#define DELAYTICKS 50L /* (adjust units below) */
|
||||
#define TICKSPERSEC 1000L /* mili sec per sec */
|
||||
|
||||
/*
|
||||
* order of ops is important here
|
||||
*
|
||||
* NOTE: large OS dependent SYFREQ might cause an overflow
|
||||
*/
|
||||
#define LOCALTICKS ((SYSFREQ*DELAYTICKS)/TICKSPERSEC)
|
||||
|
||||
#if defined(VMS)
|
||||
# define LOCK
|
||||
# define UNLOCK
|
||||
# define LOCKEVENTS
|
||||
# define UNLOCKEVENTS
|
||||
# define EVENTLOCKTEST (post_msg_active!=0)
|
||||
#endif
|
||||
|
||||
#if defined(vxWorks)
|
||||
# define VXTASKIDNONE 0
|
||||
# define LOCK semTake(client_lock, WAIT_FOREVER);
|
||||
# define UNLOCK semGive(client_lock);
|
||||
# define LOCKEVENTS \
|
||||
# define VXTASKIDNONE 0
|
||||
# define LOCK semTake(client_lock, WAIT_FOREVER);
|
||||
# define UNLOCK semGive(client_lock);
|
||||
# define LOCKEVENTS \
|
||||
{semTake(event_lock, WAIT_FOREVER); event_tid=(int)taskIdCurrent;}
|
||||
# define UNLOCKEVENTS \
|
||||
# define UNLOCKEVENTS \
|
||||
{event_tid=VXTASKIDNONE; semGive(event_lock);}
|
||||
# define EVENTLOCKTEST \
|
||||
# define EVENTLOCKTEST \
|
||||
(((int)taskIdCurrent)==event_tid || ca_static->recv_tid == (int)taskIdCurrent)
|
||||
# define VXTHISTASKID taskIdSelf()
|
||||
# define abort() taskSuspend(VXTHISTASKID)
|
||||
# define socket_close(S) close(S)
|
||||
/* vxWorks still has a brain dead func proto for ioctl */
|
||||
# define socket_ioctl(A,B,C) ioctl(A,B,(int)C)
|
||||
# define MYERRNO (errnoGet()&0xffff)
|
||||
# define POST_IO_EV semGive(io_done_sem)
|
||||
# define SYSFREQ ((long) sysClkRateGet()) /* usually 60 Hz */
|
||||
# define time(A) (tickGet()/SYSFREQ)
|
||||
typedef int SOCKET;
|
||||
# define INVALID_SOCKET (-1)
|
||||
#endif
|
||||
|
||||
#if defined(UNIX)
|
||||
# define LOCK
|
||||
# define UNLOCK
|
||||
# define LOCKEVENTS
|
||||
# define UNLOCKEVENTS
|
||||
# define EVENTLOCKTEST (post_msg_active!=0)
|
||||
# define LOCK
|
||||
# define UNLOCK
|
||||
# define LOCKEVENTS
|
||||
# define UNLOCKEVENTS
|
||||
# define EVENTLOCKTEST (post_msg_active)
|
||||
# define socket_close(S) close(S)
|
||||
# define socket_ioctl(A,B,C) ioctl(A,B,C)
|
||||
# define MYERRNO errno
|
||||
# define POST_IO_EV
|
||||
# define SYSFREQ 1000000L /* 1 MHz */
|
||||
typedef int SOCKET;
|
||||
# define INVALID_SOCKET (-1)
|
||||
#endif
|
||||
|
||||
#ifdef vxWorks
|
||||
# define VXTHISTASKID taskIdSelf()
|
||||
# define abort() taskSuspend(VXTHISTASKID)
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(VMS)
|
||||
# if defined(WINTCP) /* Wallangong */
|
||||
/* (the VAXC runtime lib has its own close */
|
||||
@@ -216,73 +263,42 @@ static char *os_depenhSccsId = "$Id$";
|
||||
# define socket_close(S) close(S)
|
||||
# define socket_ioctl(A,B,C) ioctl(A,B,C)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(UNIX)
|
||||
# define socket_close(S) close(S)
|
||||
# define socket_ioctl(A,B,C) ioctl(A,B,C)
|
||||
#endif
|
||||
|
||||
#if defined(vxWorks)
|
||||
# define socket_close(S) close(S)
|
||||
# define socket_ioctl(A,B,C) ioctl(A,B,C)
|
||||
#endif
|
||||
|
||||
#if defined(VMS)
|
||||
# ifdef WINTCP
|
||||
extern int uerrno; /* Wallongong errno is uerrno */
|
||||
extern int uerrno;
|
||||
# define MYERRNO uerrno
|
||||
# else
|
||||
# ifdef UCX
|
||||
# define MYERRNO errno
|
||||
extern volatile int noshare errno ;
|
||||
# else
|
||||
# define MYERRNO socket_errno
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(vxWorks)
|
||||
# define MYERRNO (errnoGet()&0xffff)
|
||||
#endif
|
||||
|
||||
#if defined(UNIX)
|
||||
# define MYERRNO errno
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(vxWorks)
|
||||
# define POST_IO_EV semGive(io_done_sem)
|
||||
#endif
|
||||
|
||||
#if defined(VMS)
|
||||
# define POST_IO_EV
|
||||
#endif
|
||||
|
||||
#if defined(UNIX)
|
||||
# define POST_IO_EV
|
||||
#endif
|
||||
|
||||
/* delay for when a poll is used */
|
||||
/* NOTE: DELAYTICKS must be less than TICKSPERSEC */
|
||||
#define DELAYTICKS 50L /* (adjust units below) */
|
||||
#define TICKSPERSEC 1000L /* mili sec per sec */
|
||||
|
||||
/*
|
||||
* order of ops is important here
|
||||
*
|
||||
* NOTE: large SYFREQ can cause an overflow
|
||||
*/
|
||||
# define LOCALTICKS ((SYSFREQ*DELAYTICKS)/TICKSPERSEC)
|
||||
|
||||
#if defined(VMS)
|
||||
# define SYSFREQ 10000000L /* 10 MHz */
|
||||
# define LOCK
|
||||
# define UNLOCK
|
||||
# define LOCKEVENTS
|
||||
# define UNLOCKEVENTS
|
||||
# define EVENTLOCKTEST (post_msg_active)
|
||||
typedef int SOCKET;
|
||||
# define INVALID_SOCKET (-1)
|
||||
#endif
|
||||
|
||||
#if defined(vxWorks)
|
||||
# define SYSFREQ ((long) sysClkRateGet()) /* usually 60 Hz */
|
||||
# define time(A) (tickGet()/SYSFREQ)
|
||||
#endif
|
||||
|
||||
#if defined(UNIX)
|
||||
# define SYSFREQ 1000000L /* 1 MHz */
|
||||
#endif
|
||||
|
||||
#ifdef _WINDOWS
|
||||
# define IPPORT_USERRESERVED 5000
|
||||
# define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
# define ENOBUFS WSAENOBUFS
|
||||
# define ECONNRESET WSAECONNRESET
|
||||
# define ETIMEDOUT WSAETIMEDOUT
|
||||
# define EADDRINUSE WSAEADDRINUSE
|
||||
# define socket_close(S) closesocket(S)
|
||||
# define socket_ioctl(A,B,C) ioctlsocket(A,B,C)
|
||||
# define MYERRNO WSAGetLastError()
|
||||
# define POST_IO_EV
|
||||
# define SYSFREQ 1000000L /* 1 MHz */
|
||||
#endif /*_WINDOWS*/
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id$
|
||||
* $Id$
|
||||
* Author: Jeffrey O. Hill
|
||||
* hill@luke.lanl.gov
|
||||
* (505) 665 1831
|
||||
@@ -45,6 +45,22 @@
|
||||
|
||||
#include "iocinf.h"
|
||||
|
||||
|
||||
/*
|
||||
* cac_gettimeval
|
||||
*/
|
||||
void cac_gettimeval(struct timeval *pt)
|
||||
{
|
||||
struct timezone tz;
|
||||
int status;
|
||||
|
||||
/*
|
||||
* Not POSIX but available on most of the systems that we use
|
||||
*/
|
||||
status = gettimeofday(pt, &tz);
|
||||
assert(status == 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CAC_MUX_IO()
|
||||
@@ -61,14 +77,15 @@ void cac_mux_io(struct timeval *ptimeout)
|
||||
int newInput;
|
||||
struct timeval timeout;
|
||||
|
||||
if(!ca_static->ca_repeater_contacted){
|
||||
notify_ca_repeater();
|
||||
}
|
||||
|
||||
cac_clean_iiu_list();
|
||||
|
||||
timeout = *ptimeout;
|
||||
do{
|
||||
/*
|
||||
* manage search timers and detect disconnects
|
||||
*/
|
||||
manage_conn(TRUE);
|
||||
|
||||
newInput = FALSE;
|
||||
do{
|
||||
count = cac_select_io(
|
||||
@@ -83,27 +100,35 @@ void cac_mux_io(struct timeval *ptimeout)
|
||||
while(count>0);
|
||||
|
||||
ca_process_input_queue();
|
||||
|
||||
}
|
||||
while(newInput);
|
||||
|
||||
/*
|
||||
* manage search timers and detect disconnects
|
||||
*/
|
||||
manage_conn(TRUE);
|
||||
}
|
||||
|
||||
log_time(char *pStr)
|
||||
{
|
||||
static struct timeval time;
|
||||
struct timeval newtime;
|
||||
struct timezone tz;
|
||||
ca_real diff;
|
||||
int status;
|
||||
|
||||
status = gettimeofday(&newtime, &tz);
|
||||
assert(status==0);
|
||||
|
||||
diff = cac_time_diff(&newtime, &time);
|
||||
printf("Expired %f - %s\n", diff, pStr);
|
||||
time = newtime;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* cac_block_for_io_completion()
|
||||
*/
|
||||
void cac_block_for_io_completion()
|
||||
void cac_block_for_io_completion(struct timeval *pTV)
|
||||
{
|
||||
struct timeval itimeout;
|
||||
|
||||
itimeout.tv_usec = SELECT_POLL%USEC_PER_SEC;
|
||||
itimeout.tv_sec = SELECT_POLL/USEC_PER_SEC;
|
||||
|
||||
cac_mux_io(&itimeout);
|
||||
cac_mux_io(pTV);
|
||||
}
|
||||
|
||||
|
||||
@@ -126,14 +151,9 @@ void os_specific_sg_delete(CASG *pcasg)
|
||||
}
|
||||
|
||||
|
||||
void cac_block_for_sg_completion(CASG *pcasg)
|
||||
void cac_block_for_sg_completion(CASG *pcasg, struct timeval *pTV)
|
||||
{
|
||||
struct timeval itimeout;
|
||||
|
||||
itimeout.tv_usec = SELECT_POLL%USEC_PER_SEC;
|
||||
itimeout.tv_sec = SELECT_POLL/USEC_PER_SEC;
|
||||
|
||||
cac_mux_io(&itimeout);
|
||||
cac_mux_io(pTV);
|
||||
}
|
||||
|
||||
|
||||
@@ -152,7 +172,9 @@ int cac_add_task_variable(struct ca_static *ca_temp)
|
||||
*/
|
||||
int cac_os_depen_init(struct ca_static *pcas)
|
||||
{
|
||||
int status;
|
||||
int status;
|
||||
|
||||
ca_static = pcas;
|
||||
|
||||
/*
|
||||
* dont allow disconnect to terminate process
|
||||
@@ -163,7 +185,22 @@ int cac_os_depen_init(struct ca_static *pcas)
|
||||
*/
|
||||
signal(SIGPIPE,SIG_IGN);
|
||||
|
||||
return ECA_NORMAL;
|
||||
status = ca_os_independent_init ();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* cac_os_depen_exit ()
|
||||
*/
|
||||
void cac_os_depen_exit (struct ca_static *pcas)
|
||||
{
|
||||
ca_static = pcas;
|
||||
ca_process_exit();
|
||||
ca_static = NULL;
|
||||
|
||||
free ((char *)pcas);
|
||||
}
|
||||
|
||||
|
||||
@@ -245,17 +282,6 @@ void ca_spawn_repeater()
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Setup recv thread
|
||||
* (OS dependent)
|
||||
*/
|
||||
int cac_setup_recv_thread(IIU *piiu)
|
||||
{
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ca_printf()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id$
|
||||
* REPEATER.C
|
||||
*
|
||||
* CA broadcast repeater
|
||||
*
|
||||
@@ -60,7 +60,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
static char *sccsId = "$Id$";
|
||||
static char *sccsId = "@(#)$Id$";
|
||||
|
||||
#include "iocinf.h"
|
||||
|
||||
@@ -77,7 +77,9 @@ static ELLLIST client_list;
|
||||
|
||||
static char buf[MAX_UDP];
|
||||
|
||||
LOCAL int clean_client(struct one_client *pclient, int sock);
|
||||
LOCAL int clean_client(struct one_client *pclient);
|
||||
LOCAL void register_new_client(SOCKET sock, struct sockaddr_in *pLocal,
|
||||
struct sockaddr_in *pFrom);
|
||||
|
||||
|
||||
/*
|
||||
@@ -90,8 +92,7 @@ void ca_repeater()
|
||||
{
|
||||
int status;
|
||||
int size;
|
||||
int sock;
|
||||
int bindsock;
|
||||
SOCKET sock;
|
||||
int true = 1;
|
||||
struct sockaddr_in from;
|
||||
struct sockaddr_in bd;
|
||||
@@ -99,6 +100,11 @@ void ca_repeater()
|
||||
int from_size = sizeof from;
|
||||
struct one_client *pclient;
|
||||
struct one_client *pnxtclient;
|
||||
short port;
|
||||
|
||||
port = caFetchPortConfig(
|
||||
&EPICS_CA_REPEATER_PORT,
|
||||
CA_REPEATER_PORT);
|
||||
|
||||
ellInit(&client_list);
|
||||
|
||||
@@ -106,18 +112,13 @@ void ca_repeater()
|
||||
sock = socket( AF_INET, /* domain */
|
||||
SOCK_DGRAM, /* type */
|
||||
0); /* deflt proto */
|
||||
assert(sock >= 0);
|
||||
assert(sock != INVALID_SOCKET);
|
||||
|
||||
/* allocate a socket */
|
||||
bindsock = socket( AF_INET, /* domain */
|
||||
SOCK_DGRAM, /* type */
|
||||
0); /* deflt proto */
|
||||
assert(bindsock >= 0);
|
||||
|
||||
memset((char *)&bd,0,sizeof(bd));
|
||||
memset((char *)&bd, 0, sizeof(bd));
|
||||
bd.sin_family = AF_INET;
|
||||
bd.sin_addr.s_addr = INADDR_ANY;
|
||||
bd.sin_port = htons(CA_CLIENT_PORT);
|
||||
bd.sin_port = htons(port);
|
||||
status = bind(sock, (struct sockaddr *)&bd, sizeof(bd));
|
||||
if(status<0){
|
||||
if(MYERRNO != EADDRINUSE){
|
||||
@@ -149,91 +150,81 @@ void ca_repeater()
|
||||
#endif
|
||||
|
||||
while(TRUE){
|
||||
struct extmsg *pMsg;
|
||||
|
||||
size = recvfrom(
|
||||
sock,
|
||||
buf,
|
||||
sizeof buf,
|
||||
0,
|
||||
(struct sockaddr *)&from,
|
||||
&from_size);
|
||||
|
||||
if(size > 0){
|
||||
if(from.sin_addr.s_addr != local.sin_addr.s_addr)
|
||||
for( pclient = (struct one_client *)
|
||||
client_list.node.next;
|
||||
pclient;
|
||||
pclient = (struct one_client *)
|
||||
pclient->node.next){
|
||||
|
||||
status = sendto(
|
||||
sock,
|
||||
buf,
|
||||
size,
|
||||
0,
|
||||
(struct sockaddr *)&pclient->from,
|
||||
sizeof pclient->from);
|
||||
if(status < 0){
|
||||
ca_printf("CA Repeater: fanout err %s\n",
|
||||
strerror(MYERRNO));
|
||||
}
|
||||
#ifdef DEBUG
|
||||
ca_printf("Sent\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if(size == 0){
|
||||
struct extmsg confirm;
|
||||
|
||||
/*
|
||||
* If this is a processor local message then add to
|
||||
* the list of clients to repeat to if not there
|
||||
* already
|
||||
*/
|
||||
for( pclient = (struct one_client *)
|
||||
client_list.node.next;
|
||||
pclient;
|
||||
pclient = (struct one_client *)
|
||||
pclient->node.next)
|
||||
if(from.sin_port == pclient->from.sin_port)
|
||||
break;
|
||||
|
||||
if(!pclient){
|
||||
pclient = (struct one_client *)
|
||||
calloc(1,sizeof *pclient);
|
||||
if(pclient){
|
||||
pclient->from = from;
|
||||
ellAdd( &client_list,
|
||||
&pclient->node);
|
||||
#ifdef DEBUG
|
||||
ca_printf(
|
||||
"Added %x %d\n",
|
||||
from.sin_port, size);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
memset((char *)&confirm, 0, sizeof confirm);
|
||||
confirm.m_cmmd = htons(REPEATER_CONFIRM);
|
||||
confirm.m_available = local.sin_addr.s_addr;
|
||||
status = sendto(
|
||||
sock,
|
||||
(char *)&confirm,
|
||||
sizeof confirm,
|
||||
0,
|
||||
(struct sockaddr *)&from, /* back to sender */
|
||||
sizeof from);
|
||||
if(status != sizeof confirm){
|
||||
ca_printf("CA Repeater: confirm err %s\n",
|
||||
strerror(MYERRNO));
|
||||
}
|
||||
}
|
||||
else{
|
||||
buf,
|
||||
sizeof(buf),
|
||||
0,
|
||||
(struct sockaddr *)&from,
|
||||
&from_size);
|
||||
|
||||
if(size < 0){
|
||||
ca_printf("CA Repeater: recv err %s\n",
|
||||
strerror(MYERRNO));
|
||||
}
|
||||
|
||||
/* remove any dead wood prior to pending */
|
||||
pMsg = (struct extmsg *) buf;
|
||||
|
||||
/*
|
||||
* both zero leng message and a registartion message
|
||||
* will register a new client
|
||||
*/
|
||||
if(size >= sizeof(*pMsg)){
|
||||
if(ntohs(pMsg->m_cmmd) == REPEATER_REGISTER){
|
||||
register_new_client(sock, &local, &from);
|
||||
|
||||
/*
|
||||
* strip register client message
|
||||
*/
|
||||
pMsg++;
|
||||
size -= sizeof(*pMsg);
|
||||
}
|
||||
}
|
||||
else if(size == 0){
|
||||
register_new_client(sock, &local, &from);
|
||||
}
|
||||
|
||||
/*
|
||||
* size may have been adjusted above
|
||||
*/
|
||||
if(size){
|
||||
for( pclient = (struct one_client *)
|
||||
client_list.node.next;
|
||||
pclient;
|
||||
pclient = (struct one_client *)
|
||||
pclient->node.next){
|
||||
|
||||
/*
|
||||
* Dont reflect back to sender
|
||||
*/
|
||||
if(from.sin_port == pclient->from.sin_port &&
|
||||
from.sin_addr.s_addr ==
|
||||
pclient->from.sin_addr.s_addr){
|
||||
continue;
|
||||
}
|
||||
|
||||
status = sendto(
|
||||
sock,
|
||||
(char *)pMsg,
|
||||
size,
|
||||
0,
|
||||
(struct sockaddr *)&pclient->from,
|
||||
sizeof pclient->from);
|
||||
if(status < 0){
|
||||
ca_printf("CA Repeater: fanout err %s\n",
|
||||
strerror(MYERRNO));
|
||||
}
|
||||
#ifdef DEBUG
|
||||
ca_printf("Sent\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* remove any dead wood prior to pending
|
||||
*/
|
||||
for( pclient = (struct one_client *)
|
||||
client_list.node.next;
|
||||
pclient;
|
||||
@@ -241,44 +232,129 @@ void ca_repeater()
|
||||
/* do it now in case item deleted */
|
||||
pnxtclient = (struct one_client *)
|
||||
pclient->node.next;
|
||||
clean_client(pclient, bindsock);
|
||||
clean_client(pclient);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* register_new_client()
|
||||
*/
|
||||
void register_new_client(
|
||||
SOCKET sock,
|
||||
struct sockaddr_in *pLocal,
|
||||
struct sockaddr_in *pFrom)
|
||||
{
|
||||
int status;
|
||||
struct one_client *pclient;
|
||||
struct extmsg confirm;
|
||||
|
||||
for( pclient = (struct one_client *) client_list.node.next;
|
||||
pclient;
|
||||
pclient = (struct one_client *) pclient->node.next){
|
||||
|
||||
if( pFrom->sin_port == pclient->from.sin_port &&
|
||||
pFrom->sin_addr.s_addr == pclient->from.sin_addr.s_addr)
|
||||
break;
|
||||
}
|
||||
|
||||
if(!pclient){
|
||||
pclient = (struct one_client *)calloc (1, sizeof(*pclient));
|
||||
if(pclient){
|
||||
pclient->from = *pFrom;
|
||||
ellAdd (&client_list, &pclient->node);
|
||||
#ifdef DEBUG
|
||||
ca_printf (
|
||||
"Added %d\n",
|
||||
pFrom->sin_port);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
memset((char *)&confirm, 0, sizeof confirm);
|
||||
confirm.m_cmmd = htons(REPEATER_CONFIRM);
|
||||
confirm.m_available = pLocal->sin_addr.s_addr;
|
||||
status = sendto(
|
||||
sock,
|
||||
(char *)&confirm,
|
||||
sizeof(confirm),
|
||||
0,
|
||||
(struct sockaddr *)pFrom, /* back to sender */
|
||||
sizeof(*pFrom));
|
||||
if(status != sizeof(confirm)){
|
||||
ca_printf("CA Repeater: confirm err %s\n",
|
||||
strerror(MYERRNO));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* check to see if this client is still around
|
||||
*
|
||||
* NOTE:
|
||||
* This closes the socket only whenever we are
|
||||
* able to bind so that we free the port.
|
||||
*/
|
||||
LOCAL int clean_client(struct one_client *pclient, int sock)
|
||||
LOCAL int clean_client(struct one_client *pclient)
|
||||
{
|
||||
static int sockExists;
|
||||
static SOCKET sock;
|
||||
int port = pclient->from.sin_port;
|
||||
struct sockaddr_in bd;
|
||||
int status;
|
||||
int present = FALSE;
|
||||
|
||||
memset((char *)&bd,0,sizeof bd);
|
||||
bd.sin_family = AF_INET;
|
||||
bd.sin_addr.s_addr = INADDR_ANY;
|
||||
bd.sin_port = port;
|
||||
status = bind(sock, (struct sockaddr *)&bd, sizeof bd);
|
||||
if(status<0){
|
||||
if(MYERRNO == EADDRINUSE)
|
||||
present = TRUE;
|
||||
/*
|
||||
* allocate a socket
|
||||
* (no lock required because this is implemented with
|
||||
* a single thread)
|
||||
*/
|
||||
if(!sockExists){
|
||||
sock = socket(
|
||||
AF_INET, /* domain */
|
||||
SOCK_DGRAM, /* type */
|
||||
0); /* deflt proto */
|
||||
if(sock != INVALID_SOCKET){
|
||||
sockExists = TRUE;
|
||||
}
|
||||
else{
|
||||
ca_printf("CA Repeater: client cleanup err %s\n",
|
||||
ca_printf("CA Repeater: no bind test sock err %s\n",
|
||||
strerror(MYERRNO));
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
memset((char *)&bd, 0, sizeof(bd));
|
||||
bd.sin_family = AF_INET;
|
||||
bd.sin_addr.s_addr = INADDR_ANY;
|
||||
bd.sin_port = port;
|
||||
status = bind(sock, (struct sockaddr *)&bd, sizeof(bd));
|
||||
if(status>=0){
|
||||
socket_close (sock);
|
||||
sockExists = FALSE;
|
||||
}
|
||||
else{
|
||||
if(MYERRNO == EADDRINUSE){
|
||||
present = TRUE;
|
||||
}
|
||||
else{
|
||||
ca_printf("CA Repeater: client cleanup err %s\n",
|
||||
strerror(MYERRNO));
|
||||
ca_printf("CA Repeater: sock=%d family=%d addr=%x port=%d\n",
|
||||
sock, bd.sin_family, bd.sin_addr.s_addr,
|
||||
bd.sin_port);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!present){
|
||||
#ifdef DEBUG
|
||||
ca_printf("Deleted %d\n", pclient->from.sin_port);
|
||||
#endif
|
||||
ellDelete(&client_list, &pclient->node);
|
||||
free(pclient);
|
||||
#ifdef DEBUG
|
||||
ca_printf("Deleted\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
246
src/ca/service.c
246
src/ca/service.c
@@ -68,7 +68,7 @@
|
||||
/************************************************************************/
|
||||
/*_end */
|
||||
|
||||
static char *sccsId = "$Id$";
|
||||
static char *sccsId = "@(#) $Id$";
|
||||
|
||||
#include "iocinf.h"
|
||||
#include "net_convert.h"
|
||||
@@ -90,7 +90,7 @@ struct in_addr *pnet_addr
|
||||
);
|
||||
|
||||
#ifdef CONVERSION_REQUIRED
|
||||
globalref CACVRTFUNC *cac_dbr_cvrt[];
|
||||
extern CACVRTFUNC *cac_dbr_cvrt[];
|
||||
#endif /*CONVERSION_REQUIRED*/
|
||||
|
||||
|
||||
@@ -230,7 +230,6 @@ struct in_addr *pnet_addr
|
||||
)
|
||||
{
|
||||
evid monix;
|
||||
int status;
|
||||
|
||||
switch (piiu->curMsg.m_cmmd) {
|
||||
|
||||
@@ -243,13 +242,21 @@ struct in_addr *pnet_addr
|
||||
|
||||
case IOC_WRITE_NOTIFY:
|
||||
{
|
||||
/*
|
||||
* run the user's event handler
|
||||
* m_available points to event descriptor
|
||||
*/
|
||||
struct event_handler_args args;
|
||||
|
||||
monix = (evid) piiu->curMsg.m_available;
|
||||
/*
|
||||
* run the user's event handler
|
||||
*/
|
||||
LOCK;
|
||||
monix = (evid) bucketLookupItemUnsignedId(
|
||||
pFastBucket,
|
||||
&piiu->curMsg.m_available);
|
||||
UNLOCK;
|
||||
if(!monix){
|
||||
ca_signal(ECA_INTERNAL,
|
||||
"bad client write io id from server");
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
@@ -276,21 +283,31 @@ struct in_addr *pnet_addr
|
||||
}
|
||||
LOCK;
|
||||
ellDelete(&pend_write_list, &monix->node);
|
||||
ellAdd(&free_event_list, &monix->node);
|
||||
UNLOCK;
|
||||
|
||||
caIOBlockFree(monix);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
case IOC_READ_NOTIFY:
|
||||
{
|
||||
/*
|
||||
* run the user's event handler
|
||||
* m_available points to event descriptor
|
||||
*/
|
||||
struct event_handler_args args;
|
||||
|
||||
monix = (evid) piiu->curMsg.m_available;
|
||||
/*
|
||||
* run the user's event handler
|
||||
*/
|
||||
|
||||
LOCK;
|
||||
monix = (evid) bucketLookupItemUnsignedId(
|
||||
pFastBucket,
|
||||
&piiu->curMsg.m_available);
|
||||
UNLOCK;
|
||||
if(!monix){
|
||||
ca_signal(ECA_INTERNAL,
|
||||
"bad client read notify io id from server");
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
@@ -339,8 +356,8 @@ struct in_addr *pnet_addr
|
||||
}
|
||||
LOCK;
|
||||
ellDelete(&pend_read_list, &monix->node);
|
||||
ellAdd(&free_event_list, &monix->node);
|
||||
UNLOCK;
|
||||
caIOBlockFree(monix);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -350,10 +367,18 @@ struct in_addr *pnet_addr
|
||||
struct event_handler_args args;
|
||||
|
||||
/*
|
||||
* run the user's event handler m_available
|
||||
* points to event descriptor
|
||||
* run the user's event handler
|
||||
*/
|
||||
monix = (evid) piiu->curMsg.m_available;
|
||||
LOCK;
|
||||
monix = (evid) bucketLookupItemUnsignedId(
|
||||
pFastBucket,
|
||||
&piiu->curMsg.m_available);
|
||||
UNLOCK;
|
||||
if(!monix){
|
||||
ca_signal(ECA_INTERNAL,
|
||||
"bad client event id from server");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -363,8 +388,8 @@ struct in_addr *pnet_addr
|
||||
if (!piiu->curMsg.m_postsize) {
|
||||
LOCK;
|
||||
ellDelete(&monix->chan->eventq, &monix->node);
|
||||
ellAdd(&free_event_list, &monix->node);
|
||||
UNLOCK;
|
||||
caIOBlockFree(monix);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -420,17 +445,19 @@ struct in_addr *pnet_addr
|
||||
}
|
||||
case IOC_READ:
|
||||
{
|
||||
chid chan;
|
||||
evid pIOBlock;
|
||||
|
||||
/*
|
||||
* verify the channel id
|
||||
* verify the event id
|
||||
*/
|
||||
LOCK;
|
||||
chan = bucketLookupItem(pBucket, piiu->curMsg.m_cid);
|
||||
pIOBlock = (evid) bucketLookupItemUnsignedId(
|
||||
pFastBucket,
|
||||
&piiu->curMsg.m_available);
|
||||
UNLOCK;
|
||||
if(!chan){
|
||||
if(!pIOBlock){
|
||||
ca_signal(ECA_INTERNAL,
|
||||
"bad client channel id from server");
|
||||
"bad client read io id from server");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -438,30 +465,35 @@ struct in_addr *pnet_addr
|
||||
* only count get returns if from the current
|
||||
* read seq
|
||||
*/
|
||||
if (!VALID_MSG(piiu))
|
||||
break;
|
||||
if (VALID_MSG(piiu)){
|
||||
|
||||
/*
|
||||
* convert the data buffer from net
|
||||
* format to host format
|
||||
*/
|
||||
# ifdef CONVERSION_REQUIRED
|
||||
(*cac_dbr_cvrt[piiu->curMsg.m_type])(
|
||||
piiu->pCurData,
|
||||
piiu->curMsg.m_available,
|
||||
FALSE,
|
||||
piiu->curMsg.m_count);
|
||||
# else
|
||||
memcpy(
|
||||
(char *)piiu->curMsg.m_available,
|
||||
piiu->pCurData,
|
||||
dbr_size_n(piiu->curMsg.m_type, piiu->curMsg.m_count));
|
||||
# endif
|
||||
/*
|
||||
* convert the data buffer from net
|
||||
* format to host format
|
||||
*/
|
||||
# ifdef CONVERSION_REQUIRED
|
||||
(*cac_dbr_cvrt[piiu->curMsg.m_type])(
|
||||
piiu->pCurData,
|
||||
pIOBlock->usr_arg,
|
||||
FALSE,
|
||||
piiu->curMsg.m_count);
|
||||
# else
|
||||
memcpy(
|
||||
(char *)pIOBlock->usr_arg,
|
||||
piiu->pCurData,
|
||||
dbr_size_n(piiu->curMsg.m_type,
|
||||
piiu->curMsg.m_count));
|
||||
# endif
|
||||
|
||||
/*
|
||||
* decrement the outstanding IO count
|
||||
*/
|
||||
CLRPENDRECV(TRUE);
|
||||
/*
|
||||
* decrement the outstanding IO count
|
||||
*/
|
||||
CLRPENDRECV(TRUE);
|
||||
}
|
||||
LOCK;
|
||||
ellDelete(&pend_read_list, &pIOBlock->node);
|
||||
UNLOCK;
|
||||
caIOBlockFree(pIOBlock);
|
||||
break;
|
||||
}
|
||||
case IOC_SEARCH:
|
||||
@@ -477,7 +509,7 @@ struct in_addr *pnet_addr
|
||||
{
|
||||
struct in_addr ina;
|
||||
|
||||
ina.s_addr = (long) piiu->curMsg.m_available;
|
||||
ina.s_addr = piiu->curMsg.m_available;
|
||||
mark_server_available(&ina);
|
||||
}
|
||||
UNLOCK;
|
||||
@@ -494,46 +526,12 @@ struct in_addr *pnet_addr
|
||||
break;
|
||||
|
||||
case IOC_CLEAR_CHANNEL:
|
||||
{
|
||||
chid chix = (chid) piiu->curMsg.m_available;
|
||||
struct ioc_in_use *piiu = chix->piiu;
|
||||
register evid monix;
|
||||
|
||||
|
||||
LOCK;
|
||||
/*
|
||||
* remove any orphaned get callbacks for this
|
||||
* channel
|
||||
*/
|
||||
for (monix = (evid) pend_read_list.node.next;
|
||||
monix;
|
||||
monix = (evid) monix->node.next){
|
||||
if (monix->chan == chix) {
|
||||
ellDelete(
|
||||
&pend_read_list,
|
||||
&monix->node);
|
||||
ellAdd(
|
||||
&free_event_list,
|
||||
&monix->node);
|
||||
}
|
||||
}
|
||||
ellConcat(&free_event_list, &chix->eventq);
|
||||
ellDelete(&piiu->chidlist, &chix->node);
|
||||
status = bucketRemoveItem(pBucket, chix->cid, chix);
|
||||
if(status != BUCKET_SUCCESS){
|
||||
ca_signal(
|
||||
ECA_INTERNAL,
|
||||
"bad id at channel delete");
|
||||
}
|
||||
free(chix);
|
||||
if (!piiu->chidlist.count){
|
||||
TAG_CONN_DOWN(piiu);
|
||||
}
|
||||
UNLOCK;
|
||||
clearChannelResources (piiu->curMsg.m_available);
|
||||
break;
|
||||
}
|
||||
|
||||
case IOC_ERROR:
|
||||
{
|
||||
evid monix;
|
||||
char nameBuf[64];
|
||||
char context[255];
|
||||
struct extmsg *req = piiu->pCurData;
|
||||
@@ -567,12 +565,36 @@ struct in_addr *pnet_addr
|
||||
* future. This is quite wasteful of space
|
||||
* however.
|
||||
*/
|
||||
monix = NULL;
|
||||
args.addr = NULL;
|
||||
switch (ntohs(req->m_cmmd)) {
|
||||
case IOC_READ_NOTIFY:
|
||||
LOCK;
|
||||
monix = (evid) bucketLookupItemUnsignedId(
|
||||
pFastBucket,
|
||||
&req->m_available);
|
||||
UNLOCK;
|
||||
op = CA_OP_GET;
|
||||
break;
|
||||
case IOC_READ:
|
||||
LOCK;
|
||||
monix = (evid) bucketLookupItemUnsignedId(
|
||||
pFastBucket,
|
||||
&req->m_available);
|
||||
UNLOCK;
|
||||
if(monix){
|
||||
args.addr = monix->usr_arg;
|
||||
}
|
||||
op = CA_OP_GET;
|
||||
break;
|
||||
case IOC_WRITE_NOTIFY:
|
||||
LOCK;
|
||||
monix = (evid) bucketLookupItemUnsignedId(
|
||||
pFastBucket,
|
||||
&req->m_available);
|
||||
UNLOCK;
|
||||
op = CA_OP_PUT;
|
||||
break;
|
||||
case IOC_WRITE:
|
||||
op = CA_OP_PUT;
|
||||
break;
|
||||
@@ -580,9 +602,19 @@ struct in_addr *pnet_addr
|
||||
op = CA_OP_SEARCH;
|
||||
break;
|
||||
case IOC_EVENT_ADD:
|
||||
LOCK;
|
||||
monix = (evid) bucketLookupItemUnsignedId(
|
||||
pFastBucket,
|
||||
&req->m_available);
|
||||
UNLOCK;
|
||||
op = CA_OP_ADD_EVENT;
|
||||
break;
|
||||
case IOC_EVENT_CANCEL:
|
||||
LOCK;
|
||||
monix = (evid) bucketLookupItemUnsignedId(
|
||||
pFastBucket,
|
||||
&req->m_available);
|
||||
UNLOCK;
|
||||
op = CA_OP_CLEAR_EVENT;
|
||||
break;
|
||||
default:
|
||||
@@ -590,14 +622,19 @@ struct in_addr *pnet_addr
|
||||
break;
|
||||
}
|
||||
|
||||
if (monix) {
|
||||
caIOBlockFree(monix);
|
||||
}
|
||||
|
||||
LOCK;
|
||||
args.chid = bucketLookupItem(pBucket, piiu->curMsg.m_cid);
|
||||
args.chid = bucketLookupItemUnsignedId
|
||||
(pSlowBucket, &piiu->curMsg.m_cid);
|
||||
UNLOCK;
|
||||
args.usr = ca_static->ca_exception_arg;
|
||||
args.type = ntohs(req->m_type);
|
||||
args.count = ntohs(req->m_count);
|
||||
args.addr = (void *) (req->m_available);
|
||||
args.stat = ntohl((long) piiu->curMsg.m_available); args.op = op;
|
||||
args.type = ntohs (req->m_type);
|
||||
args.count = ntohs (req->m_count);
|
||||
args.stat = ntohl (piiu->curMsg.m_available);
|
||||
args.op = op;
|
||||
args.ctx = context;
|
||||
|
||||
LOCKEVENTS;
|
||||
@@ -611,11 +648,17 @@ struct in_addr *pnet_addr
|
||||
chid chan;
|
||||
|
||||
LOCK;
|
||||
chan = bucketLookupItem(pBucket, piiu->curMsg.m_cid);
|
||||
chan = bucketLookupItemUnsignedId(pSlowBucket, &piiu->curMsg.m_cid);
|
||||
UNLOCK;
|
||||
assert(chan);
|
||||
if(!chan){
|
||||
/*
|
||||
* end up here if they delete the channel
|
||||
* prior to connecting
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
ar = ntohl(piiu->curMsg.m_available);
|
||||
ar = ntohl (piiu->curMsg.m_available);
|
||||
chan->ar.read_access = (ar&CA_ACCESS_RIGHT_READ)?1:0;
|
||||
chan->ar.write_access = (ar&CA_ACCESS_RIGHT_WRITE)?1:0;
|
||||
|
||||
@@ -633,9 +676,20 @@ struct in_addr *pnet_addr
|
||||
chid chan;
|
||||
|
||||
LOCK;
|
||||
chan = bucketLookupItem(pBucket, piiu->curMsg.m_cid);
|
||||
chan = bucketLookupItemUnsignedId(
|
||||
pSlowBucket, &piiu->curMsg.m_cid);
|
||||
UNLOCK;
|
||||
assert(chan);
|
||||
if(!chan){
|
||||
/*
|
||||
* end up here if they delete the channel
|
||||
* prior to connecting
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
if (CA_V44(CA_PROTOCOL_VERSION,piiu->minor_version_number)) {
|
||||
chan->id.sid = ntohl (piiu->curMsg.m_available);
|
||||
}
|
||||
reconnect_channel(piiu, chan);
|
||||
break;
|
||||
}
|
||||
@@ -674,7 +728,9 @@ struct in_addr *pnet_addr
|
||||
* lock required around use of the sprintf buffer
|
||||
*/
|
||||
LOCK;
|
||||
chan = bucketLookupItem(pBucket, piiu->curMsg.m_available);
|
||||
chan = bucketLookupItemUnsignedId(
|
||||
pSlowBucket,
|
||||
&piiu->curMsg.m_available);
|
||||
if(!chan){
|
||||
UNLOCK;
|
||||
return;
|
||||
|
||||
@@ -60,11 +60,23 @@ void ca_sg_init(void)
|
||||
*/
|
||||
void ca_sg_shutdown(struct ca_static *ca_temp)
|
||||
{
|
||||
CASG *pcasg;
|
||||
int status;
|
||||
|
||||
/*
|
||||
* free all sync group lists
|
||||
*/
|
||||
LOCK;
|
||||
pcasg = (CASG *) ellFirst (&ca_temp->activeCASG);
|
||||
while (pcasg) {
|
||||
status = bucketRemoveItemUnsignedId (
|
||||
ca_temp->ca_pSlowBucket, &pcasg->id);
|
||||
assert (status == BUCKET_SUCCESS);
|
||||
pcasg = (CASG *) ellNext(&pcasg->node);
|
||||
}
|
||||
ellFree(&ca_temp->activeCASG);
|
||||
ellFree(&ca_temp->freeCASG);
|
||||
UNLOCK;
|
||||
ellInit(&ca_temp->activeCASGOP);
|
||||
ellInit(&ca_temp->freeCASGOP);
|
||||
|
||||
@@ -108,13 +120,13 @@ int ca_sg_create(CA_SYNC_GID *pgid)
|
||||
*/
|
||||
memset((char *)pcasg,0,sizeof(*pcasg));
|
||||
pcasg->magic = CASG_MAGIC;
|
||||
pcasg->id = CLIENT_ID_ALLOC;
|
||||
pcasg->id = CLIENT_SLOW_ID_ALLOC;
|
||||
pcasg->opPendCount = 0;
|
||||
pcasg->seqNo = 0;
|
||||
|
||||
os_specific_sg_create(pcasg);
|
||||
|
||||
status = bucketAddItem(pBucket, pcasg->id, pcasg);
|
||||
status = bucketAddItemUnsignedId(pSlowBucket, &pcasg->id, pcasg);
|
||||
if(status == BUCKET_SUCCESS){
|
||||
/*
|
||||
* place it on the active sync group list
|
||||
@@ -154,13 +166,13 @@ int ca_sg_delete(CA_SYNC_GID gid)
|
||||
|
||||
LOCK;
|
||||
|
||||
pcasg = bucketLookupItem(pBucket, gid);
|
||||
pcasg = bucketLookupItemUnsignedId(pSlowBucket, &gid);
|
||||
if(!pcasg || pcasg->magic != CASG_MAGIC){
|
||||
UNLOCK;
|
||||
return ECA_BADSYNCGRP;
|
||||
}
|
||||
|
||||
status = bucketRemoveItem(pBucket, gid, pcasg);
|
||||
status = bucketRemoveItemUnsignedId(pSlowBucket, &gid);
|
||||
assert(status == BUCKET_SUCCESS);
|
||||
|
||||
os_specific_sg_delete(pcasg);
|
||||
@@ -180,9 +192,11 @@ int ca_sg_delete(CA_SYNC_GID gid)
|
||||
*/
|
||||
int ca_sg_block(CA_SYNC_GID gid, ca_real timeout)
|
||||
{
|
||||
time_t beg_time;
|
||||
int status;
|
||||
CASG *pcasg;
|
||||
struct timeval beg_time;
|
||||
struct timeval cur_time;
|
||||
ca_real delay;
|
||||
int status;
|
||||
CASG *pcasg;
|
||||
|
||||
/*
|
||||
* Force the CA client id bucket to
|
||||
@@ -191,6 +205,10 @@ int ca_sg_block(CA_SYNC_GID gid, ca_real timeout)
|
||||
*/
|
||||
INITCHK;
|
||||
|
||||
if(timeout<0.0){
|
||||
return ECA_TIMEOUT;
|
||||
}
|
||||
|
||||
/*
|
||||
* until CAs input mechanism is
|
||||
* revised we have to dissallow
|
||||
@@ -202,7 +220,7 @@ int ca_sg_block(CA_SYNC_GID gid, ca_real timeout)
|
||||
}
|
||||
|
||||
LOCK;
|
||||
pcasg = bucketLookupItem(pBucket, gid);
|
||||
pcasg = bucketLookupItemUnsignedId(pSlowBucket, &gid);
|
||||
if(!pcasg || pcasg->magic != CASG_MAGIC){
|
||||
UNLOCK;
|
||||
return ECA_BADSYNCGRP;
|
||||
@@ -216,21 +234,35 @@ int ca_sg_block(CA_SYNC_GID gid, ca_real timeout)
|
||||
*/
|
||||
ca_flush_io();
|
||||
|
||||
cac_gettimeval(&beg_time);
|
||||
|
||||
status = ECA_NORMAL;
|
||||
beg_time = time(NULL);
|
||||
while(pcasg->opPendCount){
|
||||
/*
|
||||
* wait for asynch notification
|
||||
*/
|
||||
cac_block_for_sg_completion(pcasg);
|
||||
ca_real remaining;
|
||||
struct timeval tmo;
|
||||
|
||||
/*
|
||||
* Exit if the timeout has expired
|
||||
*/
|
||||
if(timeout < time(NULL)-beg_time){
|
||||
cac_gettimeval (&cur_time);
|
||||
delay = cac_time_diff (&cur_time, &beg_time);
|
||||
remaining = timeout-delay;
|
||||
if (remaining<=0.0) {
|
||||
status = ECA_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow for CA background labor
|
||||
*/
|
||||
remaining = min(SELECT_POLL, remaining);
|
||||
|
||||
/*
|
||||
* wait for asynch notification
|
||||
*/
|
||||
tmo.tv_sec = remaining;
|
||||
tmo.tv_usec = (remaining-tmo.tv_sec)*USEC_PER_SEC;
|
||||
cac_block_for_sg_completion (pcasg, &tmo);
|
||||
}
|
||||
pcasg->opPendCount = 0;
|
||||
pcasg->seqNo++;
|
||||
@@ -246,7 +278,7 @@ int ca_sg_reset(CA_SYNC_GID gid)
|
||||
CASG *pcasg;
|
||||
|
||||
LOCK;
|
||||
pcasg = bucketLookupItem(pBucket, gid);
|
||||
pcasg = bucketLookupItemUnsignedId(pSlowBucket, &gid);
|
||||
if(!pcasg || pcasg->magic != CASG_MAGIC){
|
||||
UNLOCK;
|
||||
return ECA_BADSYNCGRP;
|
||||
@@ -268,7 +300,7 @@ int ca_sg_test(CA_SYNC_GID gid)
|
||||
CASG *pcasg;
|
||||
|
||||
LOCK;
|
||||
pcasg = bucketLookupItem(pBucket, gid);
|
||||
pcasg = bucketLookupItemUnsignedId(pSlowBucket, &gid);
|
||||
if(!pcasg || pcasg->magic != CASG_MAGIC){
|
||||
UNLOCK;
|
||||
return ECA_BADSYNCGRP;
|
||||
@@ -301,7 +333,7 @@ void *pvalue)
|
||||
CASG *pcasg;
|
||||
|
||||
LOCK;
|
||||
pcasg = bucketLookupItem(pBucket, gid);
|
||||
pcasg = bucketLookupItemUnsignedId(pSlowBucket, &gid);
|
||||
if(!pcasg || pcasg->magic != CASG_MAGIC){
|
||||
UNLOCK;
|
||||
return ECA_BADSYNCGRP;
|
||||
@@ -338,14 +370,15 @@ void *pvalue)
|
||||
pcasgop);
|
||||
|
||||
if(status != ECA_NORMAL){
|
||||
LOCK;
|
||||
pcasg->opPendCount--;
|
||||
ellDelete(&ca_static->activeCASGOP, &pcasgop->node);
|
||||
ellAdd(&ca_static->freeCASGOP, &pcasgop->node);
|
||||
UNLOCK;
|
||||
}
|
||||
LOCK;
|
||||
pcasg->opPendCount--;
|
||||
ellDelete(&ca_static->activeCASGOP, &pcasgop->node);
|
||||
ellAdd(&ca_static->freeCASGOP, &pcasgop->node);
|
||||
UNLOCK;
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -365,7 +398,7 @@ void *pvalue)
|
||||
CASG *pcasg;
|
||||
|
||||
LOCK;
|
||||
pcasg = bucketLookupItem(pBucket, gid);
|
||||
pcasg = bucketLookupItemUnsignedId(pSlowBucket, &gid);
|
||||
if(!pcasg || pcasg->magic != CASG_MAGIC){
|
||||
UNLOCK;
|
||||
return ECA_BADSYNCGRP;
|
||||
@@ -391,6 +424,7 @@ void *pvalue)
|
||||
pcasgop->pValue = pvalue;
|
||||
ellAdd(&ca_static->activeCASGOP, &pcasgop->node);
|
||||
pcasg->opPendCount++;
|
||||
|
||||
UNLOCK;
|
||||
|
||||
status = ca_array_get_callback(
|
||||
@@ -405,9 +439,8 @@ void *pvalue)
|
||||
pcasg->opPendCount--;
|
||||
ellDelete(&ca_static->activeCASGOP, &pcasgop->node);
|
||||
ellAdd(&ca_static->freeCASGOP, &pcasgop->node);
|
||||
UNLOCK;
|
||||
UNLOCK;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -425,7 +458,6 @@ LOCAL void io_complete(struct event_handler_args args)
|
||||
assert(pcasgop->magic == CASG_MAGIC);
|
||||
|
||||
LOCK;
|
||||
|
||||
ellDelete(&ca_static->activeCASGOP, &pcasgop->node);
|
||||
pcasgop->magic = 0;
|
||||
ellAdd(&ca_static->freeCASGOP, &pcasgop->node);
|
||||
@@ -433,7 +465,7 @@ LOCAL void io_complete(struct event_handler_args args)
|
||||
/*
|
||||
* ignore stale replies
|
||||
*/
|
||||
pcasg = bucketLookupItem(pBucket, pcasgop->id);
|
||||
pcasg = bucketLookupItemUnsignedId(pSlowBucket, &pcasgop->id);
|
||||
if(!pcasg || pcasg->seqNo != pcasgop->seqNo){
|
||||
UNLOCK;
|
||||
return;
|
||||
@@ -441,6 +473,7 @@ LOCAL void io_complete(struct event_handler_args args)
|
||||
|
||||
assert(pcasg->magic == CASG_MAGIC);
|
||||
|
||||
|
||||
if(!(args.status&CA_M_SUCCESS)){
|
||||
ca_printf(
|
||||
"CA Sync Group (id=%d) request failed because \"%s\"\n",
|
||||
|
||||
@@ -52,7 +52,7 @@ void ca_test_event(struct event_handler_args args)
|
||||
ca_printf("CAC: Value:\t<%f>\n",*(float *)args.dbr);
|
||||
break;
|
||||
case DBR_DOUBLE:
|
||||
ca_printf("CAC: Value:\t<%f>\n",*(double *)args.dbr);
|
||||
ca_printf("CAC: Value:\t<%lf>\n",*(double *)args.dbr);
|
||||
break;
|
||||
case DBR_STS_STRING:
|
||||
ca_printf("CAC: Value:\t<%s>\n",((struct dbr_sts_string *)args.dbr)->value);
|
||||
|
||||
27
src/ca/ucx.h
27
src/ca/ucx.h
@@ -1,10 +1,11 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* U C X . H
|
||||
* UNIX ioctl structures and defines used for VAX/UCX
|
||||
* Author: Gerhard Grygiel (GeG)
|
||||
*
|
||||
* GeG 09-DEC-1992 initial edit
|
||||
* CJM 13-Jul-1994 add fd_set etc for R3.12
|
||||
*
|
||||
*/
|
||||
#ifndef _UCX_H_
|
||||
@@ -14,6 +15,7 @@
|
||||
#define IFF_UP 0x1 /* interface is up */
|
||||
#define IFF_BROADCAST 0x2 /* broadcast address valid */
|
||||
#define IFF_LOOPBACK 0x8 /* is a loopback net */
|
||||
#define IFF_POINTOPOINT 0x10 /* interface is point to point */
|
||||
/*
|
||||
* Interface request structure used for socket
|
||||
* ioctl's. All interface ioctl's must have parameter
|
||||
@@ -54,6 +56,28 @@ struct ifconf {
|
||||
#define ifc_req ifc_ifcu.ifcu_req /* array of structures returned */
|
||||
};
|
||||
|
||||
#ifndef NBBY
|
||||
#define NBBY 8
|
||||
#endif
|
||||
|
||||
#ifndef FD_SETSIZE
|
||||
#define FD_SETSIZE 256
|
||||
#endif
|
||||
|
||||
typedef long fd_mask ;
|
||||
#define NFDBITS (sizeof (fd_mask) * NBBY ) /* bits per mask */
|
||||
#ifndef howmany
|
||||
#define howmany(x, y) (((x)+((y)-1))/(y))
|
||||
#endif
|
||||
|
||||
typedef struct fd_set {
|
||||
fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)] ;
|
||||
} fd_set ;
|
||||
|
||||
#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
|
||||
#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
|
||||
#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
|
||||
#define FD_ZERO(p) bzero((char *)(p), sizeof (*(p)))
|
||||
|
||||
#include <iodef.h>
|
||||
#define IO$_RECEIVE (IO$_WRITEVBLK)
|
||||
@@ -61,3 +85,4 @@ struct ifconf {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id$
|
||||
* $Id$
|
||||
* Author: Jeffrey O. Hill
|
||||
* hill@luke.lanl.gov
|
||||
* (505) 665 1831
|
||||
@@ -51,6 +51,19 @@
|
||||
|
||||
#define CONNECTION_TIMER_ID 56
|
||||
|
||||
|
||||
/*
|
||||
* cac_gettimeval
|
||||
*/
|
||||
void cac_gettimeval(struct timeval *pt)
|
||||
{
|
||||
struct timezone tz;
|
||||
int status;
|
||||
|
||||
status = gettimeofday(pt, &tz);
|
||||
assert(status==0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CAC_MUX_IO()
|
||||
@@ -67,14 +80,15 @@ void cac_mux_io(struct timeval *ptimeout)
|
||||
int newInput;
|
||||
struct timeval timeout;
|
||||
|
||||
if(!ca_static->ca_repeater_contacted){
|
||||
notify_ca_repeater();
|
||||
}
|
||||
|
||||
cac_clean_iiu_list();
|
||||
|
||||
timeout = *ptimeout;
|
||||
do{
|
||||
/*
|
||||
* manage search timers and detect disconnects
|
||||
*/
|
||||
manage_conn(TRUE);
|
||||
|
||||
newInput = FALSE;
|
||||
do{
|
||||
count = cac_select_io(
|
||||
@@ -89,13 +103,10 @@ void cac_mux_io(struct timeval *ptimeout)
|
||||
while(count>0);
|
||||
|
||||
ca_process_input_queue();
|
||||
|
||||
}
|
||||
while(newInput);
|
||||
|
||||
/*
|
||||
* manage search timers and detect disconnects
|
||||
*/
|
||||
manage_conn(TRUE);
|
||||
}
|
||||
|
||||
|
||||
@@ -103,13 +114,9 @@ void cac_mux_io(struct timeval *ptimeout)
|
||||
/*
|
||||
* cac_block_for_io_completion()
|
||||
*/
|
||||
void cac_block_for_io_completion()
|
||||
void cac_block_for_io_completion(struct timeval *pTV)
|
||||
{
|
||||
struct timeval itimeout;
|
||||
|
||||
itimeout.tv_usec = SELECT_POLL%USEC_PER_SEC;
|
||||
itimeout.tv_sec = SELECT_POLL/USEC_PER_SEC;
|
||||
cac_mux_io(&itimeout);
|
||||
cac_mux_io(pTV);
|
||||
}
|
||||
|
||||
|
||||
@@ -140,23 +147,9 @@ void os_specific_sg_io_complete(CASG *pcasg)
|
||||
/*
|
||||
* cac_block_for_sg_completion()
|
||||
*/
|
||||
void cac_block_for_sg_completion(CASG *pcasg)
|
||||
void cac_block_for_sg_completion(pTV)
|
||||
{
|
||||
struct timeval itimeout;
|
||||
|
||||
itimeout.tv_usec = SELECT_POLL%USEC_PER_SEC;
|
||||
itimeout.tv_sec = SELECT_POLL/USEC_PER_SEC;
|
||||
cac_mux_io(&itimeout);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CAC_ADD_TASK_VARIABLE()
|
||||
*/
|
||||
int cac_add_task_variable(struct ca_static *ca_temp)
|
||||
{
|
||||
ca_static = ca_temp;
|
||||
return ECA_NORMAL;
|
||||
cac_mux_io(pTV);
|
||||
}
|
||||
|
||||
|
||||
@@ -166,7 +159,26 @@ int cac_add_task_variable(struct ca_static *ca_temp)
|
||||
*/
|
||||
int cac_os_depen_init(struct ca_static *pcas)
|
||||
{
|
||||
return ECA_NORMAL;
|
||||
int status;
|
||||
|
||||
ca_static = pcas;
|
||||
|
||||
status = ca_os_independent_init ();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* cac_os_depen_exit ()
|
||||
*/
|
||||
void cac_os_depen_exit (struct ca_static *pcas)
|
||||
{
|
||||
ca_static = pcas;
|
||||
ca_process_exit();
|
||||
ca_static = NULL;
|
||||
|
||||
free ((char *)pcas);
|
||||
}
|
||||
|
||||
|
||||
@@ -296,12 +308,6 @@ void ca_spawn_repeater()
|
||||
}
|
||||
|
||||
|
||||
|
||||
cac_setup_recv_thread(IIU *piiu)
|
||||
{
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caHostFromInetAddr()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id$
|
||||
* $Id$
|
||||
* Author: Jeffrey O. Hill
|
||||
* hill@luke.lanl.gov
|
||||
* (505) 665 1831
|
||||
@@ -33,13 +33,61 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <callback.h>
|
||||
#include "iocinf.h"
|
||||
#include "remLib.h"
|
||||
|
||||
LOCAL void ca_repeater_task();
|
||||
LOCAL void ca_task_exit_tcb(WIND_TCB *ptcb);
|
||||
LOCAL void ca_extra_event_labor(void *pArg);
|
||||
LOCAL int cac_os_depen_exit(struct ca_static *pcas, int tid);
|
||||
LOCAL int cac_os_depen_exit_tid (struct ca_static *pcas, int tid);
|
||||
LOCAL int cac_add_task_variable (struct ca_static *ca_temp);
|
||||
LOCAL void deleteCallBack(CALLBACK *pcb);
|
||||
|
||||
#define USEC_PER_SEC 1000000
|
||||
|
||||
|
||||
/*
|
||||
* cac_gettimeval()
|
||||
*/
|
||||
void cac_gettimeval(struct timeval *pt)
|
||||
{
|
||||
unsigned long sec;
|
||||
unsigned long current;
|
||||
static unsigned long rate;
|
||||
static unsigned long last;
|
||||
static unsigned long offset;
|
||||
static SEM_ID sem;
|
||||
int status;
|
||||
|
||||
assert(pt);
|
||||
|
||||
/*
|
||||
* Lazy Init
|
||||
*/
|
||||
if(!rate){
|
||||
sem = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY);
|
||||
rate = sysClkRateGet();
|
||||
assert(rate);
|
||||
assert(sem!=NULL);
|
||||
}
|
||||
else {
|
||||
status = semTake(sem, WAIT_FOREVER);
|
||||
assert(status==OK);
|
||||
}
|
||||
|
||||
current = tickGet();
|
||||
if(current<last){
|
||||
offset += (~0UL)/rate;
|
||||
}
|
||||
last = current;
|
||||
status = semGive(sem);
|
||||
assert(status==OK);
|
||||
|
||||
sec = current/rate;
|
||||
pt->tv_sec = sec + offset;
|
||||
pt->tv_usec = ((current-sec*rate)*USEC_PER_SEC)/rate;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -60,7 +108,7 @@ void cac_mux_io(struct timeval *ptimeout)
|
||||
do{
|
||||
count = cac_select_io(
|
||||
&timeout,
|
||||
CA_DO_SENDS);
|
||||
CA_DO_SENDS | CA_DO_RECVS);
|
||||
timeout.tv_usec = 0;
|
||||
timeout.tv_sec = 0;
|
||||
}
|
||||
@@ -71,15 +119,24 @@ void cac_mux_io(struct timeval *ptimeout)
|
||||
/*
|
||||
* cac_block_for_io_completion()
|
||||
*/
|
||||
void cac_block_for_io_completion()
|
||||
void cac_block_for_io_completion(struct timeval *pTV)
|
||||
{
|
||||
struct timeval itimeout;
|
||||
unsigned long ticks;
|
||||
unsigned long rate = sysClkRateGet();
|
||||
|
||||
/*
|
||||
* flush outputs
|
||||
* (recv occurs in another thread)
|
||||
*/
|
||||
itimeout.tv_usec = 0;
|
||||
itimeout.tv_sec = 0;
|
||||
cac_mux_io(&itimeout);
|
||||
|
||||
semTake(io_done_sem, LOCALTICKS);
|
||||
ticks = pTV->tv_sec*rate + (pTV->tv_usec*rate)/USEC_PER_SEC;
|
||||
ticks = min(LOCALTICKS, ticks);
|
||||
|
||||
semTake(io_done_sem, ticks);
|
||||
}
|
||||
|
||||
|
||||
@@ -120,15 +177,24 @@ void os_specific_sg_io_complete(CASG *pcasg)
|
||||
/*
|
||||
* cac_block_for_sg_completion()
|
||||
*/
|
||||
void cac_block_for_sg_completion(CASG *pcasg)
|
||||
void cac_block_for_sg_completion(CASG *pcasg, struct timeval *pTV)
|
||||
{
|
||||
struct timeval itimeout;
|
||||
unsigned long ticks;
|
||||
unsigned long rate = sysClkRateGet();
|
||||
|
||||
/*
|
||||
* flush outputs
|
||||
* (recv occurs in another thread)
|
||||
*/
|
||||
itimeout.tv_usec = 0;
|
||||
itimeout.tv_sec = 0;
|
||||
cac_mux_io(&itimeout);
|
||||
|
||||
semTake(pcasg->sem, LOCALTICKS);
|
||||
ticks = pTV->tv_sec*rate + (pTV->tv_usec*rate)/USEC_PER_SEC;
|
||||
ticks = min(LOCALTICKS, ticks);
|
||||
|
||||
semTake(pcasg->sem, ticks);
|
||||
}
|
||||
|
||||
|
||||
@@ -136,7 +202,7 @@ void cac_block_for_sg_completion(CASG *pcasg)
|
||||
/*
|
||||
* CAC_ADD_TASK_VARIABLE()
|
||||
*/
|
||||
int cac_add_task_variable(struct ca_static *ca_temp)
|
||||
LOCAL int cac_add_task_variable (struct ca_static *ca_temp)
|
||||
{
|
||||
static char ca_installed;
|
||||
TVIU *ptviu;
|
||||
@@ -147,7 +213,7 @@ int cac_add_task_variable(struct ca_static *ca_temp)
|
||||
return status;
|
||||
}
|
||||
|
||||
# if DEBUG
|
||||
# ifdef DEBUG
|
||||
ca_printf("CAC: adding task variable\n");
|
||||
# endif
|
||||
|
||||
@@ -173,7 +239,7 @@ int cac_add_task_variable(struct ca_static *ca_temp)
|
||||
* taskDeleteHookAdd() if you use a task variable
|
||||
* in a task exit handler.
|
||||
*/
|
||||
# if DEBUG
|
||||
# ifdef DEBUG
|
||||
ca_printf("CAC: adding delete hook\n");
|
||||
# endif
|
||||
|
||||
@@ -188,13 +254,12 @@ int cac_add_task_variable(struct ca_static *ca_temp)
|
||||
}
|
||||
}
|
||||
|
||||
ptviu = calloc(1, sizeof(*ptviu));
|
||||
ptviu = (TVIU *) calloc(1, sizeof(*ptviu));
|
||||
if(!ptviu){
|
||||
return ECA_INTERNAL;
|
||||
}
|
||||
|
||||
ptviu->tid = taskIdSelf();
|
||||
ellAdd(&ca_temp->ca_taskVarList, &ptviu->node);
|
||||
|
||||
status = taskVarAdd(VXTHISTASKID, (int *)&ca_static);
|
||||
if (status != OK){
|
||||
@@ -203,6 +268,7 @@ int cac_add_task_variable(struct ca_static *ca_temp)
|
||||
}
|
||||
|
||||
ca_static = ca_temp;
|
||||
ellAdd(&ca_temp->ca_taskVarList, &ptviu->node);
|
||||
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
@@ -214,13 +280,13 @@ int cac_add_task_variable(struct ca_static *ca_temp)
|
||||
*/
|
||||
LOCAL void ca_task_exit_tcb(WIND_TCB *ptcb)
|
||||
{
|
||||
int status;
|
||||
struct ca_static *ca_temp;
|
||||
|
||||
# if DEBUG
|
||||
# ifdef DEBUG
|
||||
ca_printf("CAC: entering the exit handler %x\n", ptcb);
|
||||
# endif
|
||||
|
||||
|
||||
/*
|
||||
* NOTE: vxWorks provides no method at this time
|
||||
* to get the task id from the ptcb so I am
|
||||
@@ -228,18 +294,35 @@ LOCAL void ca_task_exit_tcb(WIND_TCB *ptcb)
|
||||
* the task id - somthing which may not be true
|
||||
* on future releases of vxWorks
|
||||
*/
|
||||
ca_temp = (struct ca_static *)taskVarGet((int)ptcb, (int *) &ca_static);
|
||||
ca_temp = (struct ca_static *)
|
||||
taskVarGet((int)ptcb, (int *) &ca_static);
|
||||
if (ca_temp == (struct ca_static *) ERROR){
|
||||
return;
|
||||
}
|
||||
|
||||
if(ca_temp->ca_exit_in_progress){
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Add CA task var for the exit handler
|
||||
*/
|
||||
if (ptcb != taskIdCurrent) {
|
||||
status = taskVarAdd (VXTHISTASKID, (int *)&ca_static);
|
||||
if (status == ERROR){
|
||||
ca_printf ("Couldnt add task var to CA exit task\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cac_os_depen_exit(ca_temp, (int) ptcb);
|
||||
/*
|
||||
* normal CA shut down
|
||||
*/
|
||||
cac_os_depen_exit_tid (ca_temp, (int) ptcb);
|
||||
|
||||
ca_process_exit(ca_temp);
|
||||
if (ptcb != taskIdCurrent) {
|
||||
status = taskVarDelete(VXTHISTASKID, (int *)&ca_static);
|
||||
if (status == ERROR){
|
||||
ca_printf ("Couldnt remove task var from CA exit task\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -270,6 +353,16 @@ int cac_os_depen_init(struct ca_static *pcas)
|
||||
pcas->ca_blockSem = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY);
|
||||
assert(pcas->ca_blockSem);
|
||||
|
||||
status = cac_add_task_variable (pcas);
|
||||
if (status != ECA_NORMAL) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = ca_os_independent_init ();
|
||||
if (status != ECA_NORMAL){
|
||||
return status;
|
||||
}
|
||||
|
||||
evuser = (void *) db_init_events();
|
||||
assert(evuser);
|
||||
|
||||
@@ -296,51 +389,85 @@ int cac_os_depen_init(struct ca_static *pcas)
|
||||
|
||||
|
||||
/*
|
||||
* cac_os_depen_exit()
|
||||
* cac_os_depen_exit ()
|
||||
*/
|
||||
LOCAL int cac_os_depen_exit(struct ca_static *pcas, int tid)
|
||||
void cac_os_depen_exit (struct ca_static *pcas)
|
||||
{
|
||||
int status;
|
||||
chid chix;
|
||||
evid monix;
|
||||
TVIU *ptviu;
|
||||
cac_os_depen_exit_tid (pcas, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* cac_os_depen_exit_tid ()
|
||||
*/
|
||||
LOCAL int cac_os_depen_exit_tid (struct ca_static *pcas, int tid)
|
||||
{
|
||||
int status;
|
||||
chid chix;
|
||||
evid monix;
|
||||
TVIU *ptviu;
|
||||
CALLBACK *pcb;
|
||||
|
||||
|
||||
# ifdef DEBUG
|
||||
ca_printf("CAC: entering the exit routine %x %x\n",
|
||||
tid, pcas);
|
||||
# endif
|
||||
|
||||
ca_static = pcas;
|
||||
LOCK;
|
||||
|
||||
/*
|
||||
* stop the socket recv task
|
||||
* !! only after we get the LOCK here !!
|
||||
*/
|
||||
if(taskIdVerify(pcas->recv_tid)==OK){
|
||||
taskwdRemove(pcas->recv_tid);
|
||||
if (taskIdVerify (pcas->recv_tid)==OK) {
|
||||
taskwdRemove (pcas->recv_tid);
|
||||
/*
|
||||
* dont do a task suspend if the exit handler is
|
||||
* running for this task - it botches vxWorks -
|
||||
*/
|
||||
if(pcas->recv_tid != tid){
|
||||
taskSuspend(pcas->recv_tid);
|
||||
if (pcas->recv_tid != tid) {
|
||||
status = taskSuspend (pcas->recv_tid);
|
||||
if (status<0) {
|
||||
ca_printf ("taskSuspend() error = %s\n",
|
||||
strerror (MYERRNO) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Cancel all local events
|
||||
* (and put call backs)
|
||||
*
|
||||
* !! temp release lock so that the event task
|
||||
* can finish !!
|
||||
*/
|
||||
UNLOCK;
|
||||
chix = (chid) & pcas->ca_local_chidlist.node;
|
||||
while (chix = (chid) chix->node.next){
|
||||
while (chix = (chid) chix->node.next) {
|
||||
while (monix = (evid) ellGet(&chix->eventq)) {
|
||||
status = db_cancel_event(monix + 1);
|
||||
assert(status == OK);
|
||||
free(monix);
|
||||
}
|
||||
if(chix->ppn){
|
||||
if (chix->ppn) {
|
||||
CACLIENTPUTNOTIFY *ppn;
|
||||
|
||||
ppn = chix->ppn;
|
||||
if(ppn->busy){
|
||||
dbNotifyCancel(&ppn->dbPutNotify);
|
||||
if (ppn->busy) {
|
||||
dbNotifyCancel (&ppn->dbPutNotify);
|
||||
}
|
||||
free(ppn);
|
||||
free (ppn);
|
||||
}
|
||||
}
|
||||
LOCK;
|
||||
|
||||
/*
|
||||
* set ca_static for access.c
|
||||
* (run this before deleting the task variable)
|
||||
*/
|
||||
ca_process_exit();
|
||||
|
||||
/*
|
||||
* cancel task vars for other tasks so this
|
||||
@@ -351,7 +478,11 @@ LOCAL int cac_os_depen_exit(struct ca_static *pcas, int tid)
|
||||
*
|
||||
* db_close_events() does not require a CA context.
|
||||
*/
|
||||
while(ptviu = (TVIU *)ellGet(&pcas->ca_taskVarList)){
|
||||
while (ptviu = (TVIU *)ellGet(&pcas->ca_taskVarList)) {
|
||||
# ifdef DEBUG
|
||||
ca_printf("CAC: removing task var %x\n", ptviu->tid);
|
||||
# endif
|
||||
|
||||
status = taskVarDelete(
|
||||
ptviu->tid,
|
||||
(int *)&ca_static);
|
||||
@@ -363,9 +494,15 @@ LOCAL int cac_os_depen_exit(struct ca_static *pcas, int tid)
|
||||
free(ptviu);
|
||||
}
|
||||
|
||||
if(taskIdVerify(pcas->recv_tid)==OK){
|
||||
if (taskIdVerify(pcas->recv_tid)==OK) {
|
||||
if(pcas->recv_tid != tid){
|
||||
taskDelete(pcas->recv_tid);
|
||||
pcb = (CALLBACK *) calloc(1,sizeof(*pcb));
|
||||
if (pcb) {
|
||||
pcb->callback = deleteCallBack;
|
||||
pcb->priority = priorityHigh;
|
||||
pcb->user = (void *) pcas->recv_tid;
|
||||
callbackRequest (pcb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,11 +521,38 @@ LOCAL int cac_os_depen_exit(struct ca_static *pcas, int tid)
|
||||
ellFree(&pcas->ca_local_chidlist);
|
||||
ellFree(&pcas->ca_dbfree_ev_list);
|
||||
|
||||
|
||||
/*
|
||||
* remove semaphores here so that ca_process_exit()
|
||||
* can use them.
|
||||
*/
|
||||
assert(semDelete(pcas->ca_client_lock)==OK);
|
||||
assert(semDelete(pcas->ca_event_lock)==OK);
|
||||
assert(semDelete(pcas->ca_putNotifyLock)==OK);
|
||||
assert(semDelete(pcas->ca_io_done_sem)==OK);
|
||||
assert(semDelete(pcas->ca_blockSem)==OK);
|
||||
|
||||
ca_static = NULL;
|
||||
free ((char *)pcas);
|
||||
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* deleteCallBack()
|
||||
*/
|
||||
LOCAL void deleteCallBack(CALLBACK *pcb)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = taskDelete ((int)pcb->user);
|
||||
if (status < 0) {
|
||||
ca_printf ("CAC: tak delete at exit failed: %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
free (pcb);
|
||||
}
|
||||
|
||||
|
||||
@@ -464,7 +628,7 @@ int ca_import(int tid)
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
ptviu = calloc(1, sizeof(*ptviu));
|
||||
ptviu = (TVIU *) calloc(1, sizeof(*ptviu));
|
||||
if(!ptviu){
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
@@ -530,13 +694,11 @@ int ca_import_cancel(int tid)
|
||||
*/
|
||||
int ca_check_for_fp()
|
||||
{
|
||||
{
|
||||
int options;
|
||||
int options;
|
||||
|
||||
assert(taskOptionsGet(taskIdSelf(), &options) == OK);
|
||||
if (!(options & VX_FP_TASK)) {
|
||||
return ECA_NEEDSFP;
|
||||
}
|
||||
assert(taskOptionsGet(taskIdSelf(), &options) == OK);
|
||||
if (!(options & VX_FP_TASK)) {
|
||||
return ECA_NEEDSFP;
|
||||
}
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
@@ -558,16 +720,16 @@ void ca_spawn_repeater()
|
||||
CA_REPEATER_OPT,
|
||||
CA_REPEATER_STACK,
|
||||
(FUNCPTR)ca_repeater_task,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
if (status < 0){
|
||||
SEVCHK(ECA_NOREPEATER, NULL);
|
||||
}
|
||||
@@ -583,16 +745,6 @@ void ca_repeater_task()
|
||||
ca_repeater();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Setup recv thread
|
||||
* (OS dependent)
|
||||
*/
|
||||
int cac_setup_recv_thread(IIU *piiu)
|
||||
{
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
@@ -657,13 +809,13 @@ LOCAL void ca_extra_event_labor(void *pArg)
|
||||
*/
|
||||
status = semGive(pcas->ca_blockSem);
|
||||
if(status != OK){
|
||||
logMsg("CA block sem corrupted\n",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
logMsg( "CA block sem corrupted\n",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -689,13 +841,11 @@ void cac_recv_task(int tid)
|
||||
* ca_task_exit() is called.
|
||||
*/
|
||||
while(TRUE){
|
||||
manage_conn(TRUE);
|
||||
|
||||
timeout.tv_usec = 0;
|
||||
timeout.tv_sec = 1;
|
||||
|
||||
if(!ca_static->ca_repeater_contacted){
|
||||
notify_ca_repeater();
|
||||
}
|
||||
|
||||
cac_clean_iiu_list();
|
||||
|
||||
cac_select_io(
|
||||
@@ -703,7 +853,6 @@ void cac_recv_task(int tid)
|
||||
CA_DO_RECVS);
|
||||
|
||||
ca_process_input_queue();
|
||||
manage_conn(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
254
src/ca/windows_depen.c
Normal file
254
src/ca/windows_depen.c
Normal file
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* $Id$
|
||||
* Author: Jeffrey O. Hill
|
||||
* hill@luke.lanl.gov
|
||||
* (505) 665 1831
|
||||
* Date: 9-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:
|
||||
* -----------------
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* ANSI includes
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "iocinf.h"
|
||||
|
||||
#ifndef _WINDOWS
|
||||
#error This source is specific to DOS/WINDOS
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* cac_gettimeval
|
||||
*/
|
||||
void cac_gettimeval(struct timeval *pt)
|
||||
{
|
||||
SYSTEMTIME st;
|
||||
|
||||
GetSystemTime(&st);
|
||||
pt->tv_sec = (long)st.wSecond + (long)st.wMinute*60 +
|
||||
(long)st.wHour*360;
|
||||
pt->tv_usec = st.wMilliseconds*1000;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CAC_MUX_IO()
|
||||
*
|
||||
* Asynch notification of incomming messages under UNIX
|
||||
* 1) Wait no longer than timeout
|
||||
* 2) Return early if nothing outstanding
|
||||
*
|
||||
*
|
||||
*/
|
||||
void cac_mux_io(struct timeval *ptimeout)
|
||||
{
|
||||
int count;
|
||||
int newInput;
|
||||
struct timeval timeout;
|
||||
|
||||
cac_clean_iiu_list();
|
||||
|
||||
timeout = *ptimeout;
|
||||
do{
|
||||
/*
|
||||
* manage search timers and detect disconnects
|
||||
*/
|
||||
manage_conn(TRUE); newInput = FALSE;
|
||||
|
||||
do{
|
||||
count = cac_select_io(
|
||||
&timeout,
|
||||
CA_DO_RECVS | CA_DO_SENDS);
|
||||
if(count>0){
|
||||
newInput = TRUE;
|
||||
}
|
||||
timeout.tv_usec = 0;
|
||||
timeout.tv_sec = 0;
|
||||
}
|
||||
while(count>0);
|
||||
|
||||
ca_process_input_queue();
|
||||
|
||||
}
|
||||
while(newInput);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* cac_block_for_io_completion()
|
||||
*/
|
||||
void cac_block_for_io_completion(struct timeval *pTV)
|
||||
{
|
||||
cac_mux_io(pTV);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* os_specific_sg_io_complete()
|
||||
*/
|
||||
void os_specific_sg_io_complete(CASG *pcasg)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* does nothing but satisfy undefined
|
||||
*/
|
||||
void os_specific_sg_create(CASG *pcasg)
|
||||
{
|
||||
}
|
||||
void os_specific_sg_delete(CASG *pcasg)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void cac_block_for_sg_completion(CASG *pcasg, struct timeval *pTV)
|
||||
{
|
||||
cac_mux_io(pTV);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* cac_os_depen_init()
|
||||
*/
|
||||
int cac_os_depen_init(struct ca_static *pcas)
|
||||
{
|
||||
int status;
|
||||
|
||||
ca_static = ca_temp;
|
||||
|
||||
/*
|
||||
* dont allow disconnect to terminate process
|
||||
* when running in UNIX enviroment
|
||||
*
|
||||
* allow error to be returned to sendto()
|
||||
* instead of handling disconnect at interrupt
|
||||
*/
|
||||
signal(SIGPIPE,SIG_IGN);
|
||||
|
||||
# ifdef _WINSOCKAPI_
|
||||
status = WSAStartup(MAKEWORD(1,1), &WsaData));
|
||||
assert (status==0);
|
||||
# endif
|
||||
|
||||
status = ca_os_independent_init ();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* cac_os_depen_exit ()
|
||||
*/
|
||||
void cac_os_depen_exit (struct ca_static *pcas)
|
||||
{
|
||||
ca_static = pcas;
|
||||
ca_process_exit();
|
||||
ca_static = NULL;
|
||||
|
||||
free ((char *)pcas);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* This should work on any POSIX compliant OS
|
||||
*
|
||||
* o Indicates failure by setting ptr to nill
|
||||
*/
|
||||
char *localUserName()
|
||||
{
|
||||
int length;
|
||||
char *pName;
|
||||
char *pTmp;
|
||||
|
||||
pName = "Joe PC";
|
||||
length = strlen(pName)+1;
|
||||
|
||||
pTmp = malloc(length);
|
||||
if(!pTmp){
|
||||
return pTmp;
|
||||
}
|
||||
strncpy(pTmp, pName, length-1);
|
||||
pTmp[length-1] = '\0';
|
||||
|
||||
return pTmp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ca_spawn_repeater()
|
||||
*/
|
||||
void ca_spawn_repeater()
|
||||
{
|
||||
int status;
|
||||
char *pImageName;
|
||||
|
||||
/*
|
||||
* running in the repeater process
|
||||
* if here
|
||||
*/
|
||||
pImageName = "caRepeater";
|
||||
status = system(pImageName);
|
||||
if(status<0){
|
||||
ca_printf("!!WARNING!!\n");
|
||||
ca_printf("Unable to locate the executable \"%s\".\n",
|
||||
pImageName);
|
||||
ca_printf("You may need to modify your environment.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ca_printf()
|
||||
*/
|
||||
int ca_printf(char *pformat, ...)
|
||||
{
|
||||
va_list args;
|
||||
int status;
|
||||
|
||||
va_start(args, pformat);
|
||||
|
||||
status = vfprintf(
|
||||
stderr,
|
||||
pformat,
|
||||
args);
|
||||
|
||||
va_end(args);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,11 @@ include $(EPICS)/config/CONFIG_BASE
|
||||
USR_LDLIBS = -lDb -lCom
|
||||
USR_LDFLAGS = -L.
|
||||
|
||||
LEX = $(ELEX)
|
||||
YACC = $(EYACC)
|
||||
YACCOPT = -l
|
||||
LEXOPT = -L
|
||||
|
||||
DEPLIBS_BASE = $(EPICS_BASE_LIB)
|
||||
DEPLIBS = ./libDb.a\
|
||||
$(DEPLIBS_BASE)/libCom.a
|
||||
@@ -13,10 +18,8 @@ DEPLIBS = ./libDb.a\
|
||||
|
||||
SRCS.c = \
|
||||
../dbStaticLib.c \
|
||||
atdb_lex.c \
|
||||
atdb_yacc.c \
|
||||
../dbta.c \
|
||||
../atdb.c \
|
||||
../dbl.c \
|
||||
../dbls.c
|
||||
|
||||
@@ -25,17 +28,17 @@ LIBOBJS = dbStaticLib.o
|
||||
|
||||
LIBNAME = libDb.a
|
||||
|
||||
PROD = dbta dbl dbls atdb
|
||||
PROD = atdb dbl dbls dbta
|
||||
|
||||
include $(EPICS)/config/RULES.Unix
|
||||
|
||||
atdb: atdb.o atdb_yacc.o $(DEPLIBS)
|
||||
$(LINK.c) -o $@ atdb.o atdb_yacc.o $(LDLIBS)
|
||||
atdb: atdb_yacc.o $(DEPLIBS)
|
||||
$(LINK.c) -o $@ atdb_yacc.o $(LDLIBS)
|
||||
|
||||
# Extra rule since atdb_lex.c is included in atdb_yacc.c
|
||||
# In my opinion, these objects should really be built
|
||||
# independently.
|
||||
atdb_yacc.o: atdb_lex.c
|
||||
atdb_yacc.o: atdb_lex.c ../atdb.c
|
||||
|
||||
clean::
|
||||
@$(RM) atdb_lex.c atdb_yacc.c
|
||||
|
||||
@@ -21,7 +21,7 @@ yyreset()
|
||||
|
||||
^"PV:" { return(PV); }
|
||||
"Type:" { return(TYPE); }
|
||||
{ return(CLOSE); }
|
||||
"" { return(CLOSE); }
|
||||
"$$end" { return(CLOSE); }
|
||||
|
||||
{d}+ { yylval.Str=(char *)malloc(strlen(yytext)+1);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
static int yy_start;
|
||||
#include <dbStaticLib.h>
|
||||
/* kludge for buggy lex/yacc. exploits the fact that we know the union */
|
||||
/* below will be given the name YYSTYPE. done so that ifndef YYSTYPE */
|
||||
@@ -130,6 +131,5 @@ char *str;
|
||||
sprintf(message,"Error line %d : %s\n",line_num, yytext);
|
||||
errMessage(-1,message);
|
||||
}
|
||||
|
||||
yywrap() { return(1); }
|
||||
|
||||
|
||||
#include "atdb.c"
|
||||
|
||||
@@ -1651,7 +1651,7 @@ char *pstring;
|
||||
plink->value.vmeio.parm[0] = 0;
|
||||
if(end = strchr(pstr,'@')) {
|
||||
pstr = end + 1;
|
||||
sscanf(pstr,"%31s",&plink->value.vmeio.parm[0]);
|
||||
strcpy(&plink->value.vmeio.parm[0],pstr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1678,7 +1678,7 @@ char *pstring;
|
||||
plink->value.camacio.parm[0] = 0;
|
||||
if(end = strchr(pstr,'@')) {
|
||||
pstr = end + 1;
|
||||
sscanf(pstr,"%25s",&plink->value.camacio.parm[0]);
|
||||
strcpy(&plink->value.camacio.parm[0],pstr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1708,7 +1708,7 @@ char *pstring;
|
||||
plink->value.abio.parm[0] = 0;
|
||||
if(end = strchr(pstr,'@')) {
|
||||
pstr = end + 1;
|
||||
sscanf(pstr,"%25s",&plink->value.abio.parm[0]);
|
||||
strcpy(&plink->value.abio.parm[0],pstr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1726,7 +1726,7 @@ char *pstring;
|
||||
plink->value.gpibio.parm[0] = 0;
|
||||
if(end = strchr(pstr,'@')) {
|
||||
pstr = end + 1;
|
||||
sscanf(pstr,"%31s",&plink->value.gpibio.parm[0]);
|
||||
strcpy(&plink->value.gpibio.parm[0],pstr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1758,7 +1758,7 @@ char *pstring;
|
||||
plink->value.bitbusio.parm[0] = 0;
|
||||
if(end = strchr(pstr,'@')) {
|
||||
pstr = end + 1;
|
||||
sscanf(pstr,"%31s",&plink->value.bitbusio.parm[0]);
|
||||
strcpy(&plink->value.bitbusio.parm[0],pstr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1786,7 +1786,7 @@ char *pstring;
|
||||
plink->value.bbgpibio.parm[0] = 0;
|
||||
if(end = strchr(pstr,'@')) {
|
||||
pstr = end + 1;
|
||||
sscanf(pstr,"%31s",&plink->value.bbgpibio.parm[0]);
|
||||
strcpy(&plink->value.bbgpibio.parm[0],pstr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1819,7 +1819,7 @@ char *pstring;
|
||||
plink->value.vxiio.parm[0] = 0;
|
||||
if(end = strchr(pstr,'@')) {
|
||||
pstr = end + 1;
|
||||
sscanf(pstr,"%27s",&plink->value.vxiio.parm[0]);
|
||||
strcpy(&plink->value.vxiio.parm[0],pstr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1829,7 +1829,7 @@ char *pstring;
|
||||
plink->value.instio.string[0] = 0;
|
||||
if(end = strchr(pstr,'@')) {
|
||||
pstr = end + 1;
|
||||
sscanf(pstr,"%35s",&plink->value.instio.string[0]);
|
||||
strcpy(&plink->value.instio.string[0],pstr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -5,69 +5,192 @@ include $(EPICS)/config/CONFIG_BASE
|
||||
USR_INCLUDES = -I../../drv
|
||||
|
||||
SRCS.c = \
|
||||
../devAiDvx2502.c ../devAiSoft.c ../devAiSoftRaw.c \
|
||||
../devAiSymb.c ../devAiTestAsyn.c ../devAiXy566Di.c \
|
||||
../devAiXy566DiL.c ../devAiXy566Se.c ../devAoSoft.c \
|
||||
../devApsEg.c ../devApsEr.c\
|
||||
../devAoSoftRaw.c ../devAoSymb.c ../devAoTestAsyn.c \
|
||||
../devAoVmiVme4100.c ../devBiMpv910.c ../devBiSoft.c \
|
||||
../devBiSoftRaw.c ../devBiTestAsyn.c ../devBiXVme210.c \
|
||||
../devBoMpv902.c ../devBoSoft.c ../devBoSoftRaw.c \
|
||||
../devBoTestAsyn.c ../devBoXVme220.c ../devCommonGpib.c \
|
||||
../devEventSoft.c ../devEventTestIoEvent.c ../devHistogramSoft.c \
|
||||
../devHistogramTestAsyn.c ../devLiSoft.c ../devLiSymb.c \
|
||||
../devLoSoft.c ../devLoSymb.c ../devMbbiMpv910.c \
|
||||
../devMbbiSoft.c ../devMbbiSoftRaw.c ../devMbbiTestAsyn.c \
|
||||
../devMbbiXVme210.c ../devMbboMpv902.c ../devMbboSoft.c \
|
||||
../devMbboSoftRaw.c ../devMbboTestAsyn.c ../devMbboXVme220.c \
|
||||
../devMbbiDirectMpv910.c ../devMbbiDirectSoft.c \
|
||||
../devMbbiDirectSoftRaw.c ../devMbbiDirectXVme210.c \
|
||||
../devMbboDirectMpv902.c ../devMbboDirectSoft.c \
|
||||
../devMbboDirectSoftRaw.c ../devMbboDirectXVme220.c \
|
||||
../devPtSoft.c ../devSmCompumotor1830.c ../devSmOms6Axis.c \
|
||||
../devSiSoft.c ../devSiSymb.c ../devSiTestAsyn.c ../devSoSoft.c \
|
||||
../devSASoft.c ../devSoSymb.c \
|
||||
../devSoTestAsyn.c ../devWfSoft.c ../devWfTestAsyn.c \
|
||||
../devWfXy566Sc.c ../devAllenBradley.c ../devAt5Vxi.c \
|
||||
../devMz8310.c ../devTimerMz8310.c \
|
||||
../devVxiTDM.c ../devAiKscV215.c ../devXy240.c \
|
||||
../devHpe1368a.c ../devAt8Fp.c ../devWfComet.c \
|
||||
../devWfDvx2502.c ../devWfJoergerVtr1.c \
|
||||
../devAvme9440.c \
|
||||
../devAiDvx2502.c\
|
||||
../devAiSoft.c\
|
||||
../devAiSoftRaw.c\
|
||||
../devAiSymb.c\
|
||||
../devAiTestAsyn.c\
|
||||
../devAiXy566Di.c\
|
||||
../devAiXy566DiL.c\
|
||||
../devAiXy566Se.c\
|
||||
../devAoSoft.c\
|
||||
../devApsEg.c\
|
||||
../devApsEr.c\
|
||||
../devAoSoftRaw.c\
|
||||
../devAoSymb.c\
|
||||
../devAoTestAsyn.c\
|
||||
../devAoVmiVme4100.c\
|
||||
../devBiMpv910.c\
|
||||
../devBiSoft.c\
|
||||
../devBiSoftRaw.c\
|
||||
../devBiTestAsyn.c\
|
||||
../devBiXVme210.c\
|
||||
../devBoMpv902.c\
|
||||
../devBoSoft.c\
|
||||
../devBoSoftRaw.c\
|
||||
../devBoTestAsyn.c\
|
||||
../devBoXVme220.c\
|
||||
../devCommonGpib.c\
|
||||
../devEventSoft.c\
|
||||
../devEventTestIoEvent.c\
|
||||
../devHistogramSoft.c\
|
||||
../devHistogramTestAsyn.c\
|
||||
../devLiSoft.c\
|
||||
../devLiSymb.c\
|
||||
../devLoSoft.c\
|
||||
../devLoSymb.c\
|
||||
../devMbbiMpv910.c\
|
||||
../devMbbiSoft.c\
|
||||
../devMbbiSoftRaw.c\
|
||||
../devMbbiTestAsyn.c\
|
||||
../devMbbiXVme210.c\
|
||||
../devMbboMpv902.c\
|
||||
../devMbboSoft.c\
|
||||
../devMbboSoftRaw.c\
|
||||
../devMbboTestAsyn.c\
|
||||
../devMbboXVme220.c\
|
||||
../devMbbiDirectMpv910.c\
|
||||
../devMbbiDirectSoft.c\
|
||||
../devMbbiDirectSoftRaw.c\
|
||||
../devMbbiDirectXVme210.c\
|
||||
../devMbboDirectMpv902.c\
|
||||
../devMbboDirectSoft.c\
|
||||
../devMbboDirectSoftRaw.c\
|
||||
../devMbboDirectXVme220.c\
|
||||
../devPtSoft.c\
|
||||
../devSmCompumotor1830.c\
|
||||
../devSmOms6Axis.c\
|
||||
../devSiSoft.c\
|
||||
../devSiSymb.c\
|
||||
../devSiTestAsyn.c\
|
||||
../devSoSoft.c\
|
||||
../devSASoft.c\
|
||||
../devSoSymb.c\
|
||||
../devSoTestAsyn.c\
|
||||
../devWfSoft.c\
|
||||
../devWfTestAsyn.c\
|
||||
../devWfXy566Sc.c\
|
||||
../devAllenBradley.c\
|
||||
../devAt5Vxi.c\
|
||||
../devMz8310.c\
|
||||
../devTimerMz8310.c\
|
||||
../devVxiTDM.c\
|
||||
../devAiKscV215.c\
|
||||
../devXy240.c\
|
||||
../devHpe1368a.c\
|
||||
../devAt8Fp.c\
|
||||
../devWfComet.c\
|
||||
../devWfDvx2502.c\
|
||||
../devWfJoergerVtr1.c\
|
||||
../devAvme9440.c\
|
||||
../devSysmon.c
|
||||
# ../devAiCamac.c ../devAaiCamac.c ../devBiCamac.c ../devLiCamac.c \
|
||||
# ../devMbbiCamac.c ../devMbbiDirectCamac.c ../devWfCamac.c \
|
||||
# ../devAoCamac.c ../devAaoCamac.c ../devBoCamac.c ../devLoCamac.c \
|
||||
# ../devMbboCamac.c ../devMbboDirectCamac.c
|
||||
# ../devAiCamac.c\
|
||||
# ../devAaiCamac.c\
|
||||
# ../devBiCamac.c\
|
||||
# ../devLiCamac.c\
|
||||
# ../devMbbiCamac.c\
|
||||
# ../devMbbiDirectCamac.c\
|
||||
# ../devWfCamac.c\
|
||||
# ../devAoCamac.c\
|
||||
# ../devAaoCamac.c\
|
||||
# ../devBoCamac.c\
|
||||
# ../devLoCamac.c\
|
||||
# ../devMbboCamac.c\
|
||||
# ../devMbboDirectCamac.c
|
||||
|
||||
OBJS = \
|
||||
devAiDvx2502.o devAiSoft.o devAiSoftRaw.o devAiSymb.o \
|
||||
devAiTestAsyn.o devAiXy566Di.o devAiXy566DiL.o devAiXy566Se.o \
|
||||
devAoSoft.o devAoSoftRaw.o devAoSymb.o devAoTestAsyn.o \
|
||||
devAoVmiVme4100.o devBiMpv910.o devApsEg.o devApsEr.o \
|
||||
devBiSoft.o devBiSoftRaw.o \
|
||||
devBiTestAsyn.o devBiXVme210.o devBoMpv902.o devBoSoft.o \
|
||||
devBoSoftRaw.o devBoTestAsyn.o devBoXVme220.o devCommonGpib.o \
|
||||
devEventSoft.o devEventTestIoEvent.o devHistogramSoft.o \
|
||||
devHistogramTestAsyn.o devLiSoft.o devLiSymb.o \
|
||||
devLoSoft.o devLoSymb.o devMbbiMpv910.o devMbbiSoft.o \
|
||||
devMbbiSoftRaw.o devMbbiTestAsyn.o devMbbiXVme210.o devMbboMpv902.o \
|
||||
devMbboSoft.o devMbboSoftRaw.o devMbboTestAsyn.o devMbboXVme220.o \
|
||||
devMbbiDirectMpv910.o devMbbiDirectSoft.o devMbbiDirectSoftRaw.o \
|
||||
devMbbiDirectXVme210.o devMbboDirectMpv902.o devMbboDirectSoft.o \
|
||||
devMbboDirectSoftRaw.o devMbboDirectXVme220.o devPtSoft.o \
|
||||
devSmCompumotor1830.o devSmOms6Axis.o devSASoft.o devSiSoft.o \
|
||||
devSiSymb.o devSiTestAsyn.o devSoSoft.o devSoSymb.o devSoTestAsyn.o \
|
||||
devWfSoft.o devWfTestAsyn.o devWfXy566Sc.o devAllenBradley.o \
|
||||
devAt5Vxi.o devMz8310.o devTimerMz8310.o devVxiTDM.o devAiKscV215.o \
|
||||
devXy240.o devHpe1368a.o devAt8Fp.o devWfComet.o \
|
||||
devWfDvx2502.o devWfJoergerVtr1.o \
|
||||
devAvme9440.o \
|
||||
devAiDvx2502.o\
|
||||
devAiSoft.o\
|
||||
devAiSoftRaw.o\
|
||||
devAiSymb.o\
|
||||
devAiTestAsyn.o\
|
||||
devAiXy566Di.o\
|
||||
devAiXy566DiL.o\
|
||||
devAiXy566Se.o\
|
||||
devAoSoft.o\
|
||||
devAoSoftRaw.o\
|
||||
devAoSymb.o\
|
||||
devAoTestAsyn.o\
|
||||
devAoVmiVme4100.o\
|
||||
devBiMpv910.o\
|
||||
devApsEg.o\
|
||||
devApsEr.o\
|
||||
devBiSoft.o\
|
||||
devBiSoftRaw.o\
|
||||
devBiTestAsyn.o\
|
||||
devBiXVme210.o\
|
||||
devBoMpv902.o\
|
||||
devBoSoft.o\
|
||||
devBoSoftRaw.o\
|
||||
devBoTestAsyn.o\
|
||||
devBoXVme220.o\
|
||||
devCommonGpib.o\
|
||||
devEventSoft.o\
|
||||
devEventTestIoEvent.o\
|
||||
devHistogramSoft.o\
|
||||
devHistogramTestAsyn.o\
|
||||
devLiSoft.o\
|
||||
devLiSymb.o\
|
||||
devLoSoft.o\
|
||||
devLoSymb.o\
|
||||
devMbbiMpv910.o\
|
||||
devMbbiSoft.o\
|
||||
devMbbiSoftRaw.o\
|
||||
devMbbiTestAsyn.o\
|
||||
devMbbiXVme210.o\
|
||||
devMbboMpv902.o\
|
||||
devMbboSoft.o\
|
||||
devMbboSoftRaw.o\
|
||||
devMbboTestAsyn.o\
|
||||
devMbboXVme220.o\
|
||||
devMbbiDirectMpv910.o\
|
||||
devMbbiDirectSoft.o\
|
||||
devMbbiDirectSoftRaw.o\
|
||||
devMbbiDirectXVme210.o\
|
||||
devMbboDirectMpv902.o\
|
||||
devMbboDirectSoft.o\
|
||||
devMbboDirectSoftRaw.o\
|
||||
devMbboDirectXVme220.o\
|
||||
devPtSoft.o\
|
||||
devSmCompumotor1830.o\
|
||||
devSmOms6Axis.o\
|
||||
devSASoft.o\
|
||||
devSiSoft.o\
|
||||
devSiSymb.o\
|
||||
devSiTestAsyn.o\
|
||||
devSoSoft.o\
|
||||
devSoSymb.o\
|
||||
devSoTestAsyn.o\
|
||||
devWfSoft.o\
|
||||
devWfTestAsyn.o\
|
||||
devWfXy566Sc.o\
|
||||
devAllenBradley.o\
|
||||
devAt5Vxi.o\
|
||||
devMz8310.o\
|
||||
devTimerMz8310.o\
|
||||
devVxiTDM.o\
|
||||
devAiKscV215.o\
|
||||
devXy240.o\
|
||||
devHpe1368a.o\
|
||||
devAt8Fp.o\
|
||||
devWfComet.o\
|
||||
devWfDvx2502.o\
|
||||
devWfJoergerVtr1.o\
|
||||
devAvme9440.o\
|
||||
devSysmon.o
|
||||
# devAiCamac.o devAaiCamac.o devBiCamac.o devLiCamac.o \
|
||||
# devMbbiCamac.o devMbbiDirectCamac.o devWfCamac.o \
|
||||
# devAoCamac.o devAaoCamac.o devBoCamac.o devLoCamac.o \
|
||||
# devMbboCamac.o devMbboDirectCamac.o
|
||||
# devAiCamac.o\
|
||||
# devAaiCamac.o\
|
||||
# devBiCamac.o\
|
||||
# devLiCamac.o\
|
||||
# devMbbiCamac.o\
|
||||
# devMbbiDirectCamac.o\
|
||||
# devWfCamac.o\
|
||||
# devAoCamac.o\
|
||||
# devAaoCamac.o\
|
||||
# devBoCamac.o\
|
||||
# devLoCamac.o\
|
||||
# devMbboCamac.o\
|
||||
# devMbboDirectCamac.o
|
||||
|
||||
PROD = devSup
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ static long read_ai(pai)
|
||||
return(2); /* don`t convert*/
|
||||
} else {
|
||||
wait_time = (int)(pai->disv * vxTicksPerSecond);
|
||||
if(wait_time<=0) return(0);
|
||||
if(wait_time<=0) return(2);
|
||||
callbackSetPriority(pai->prio,&pcallback->callback);
|
||||
printf("Starting asynchronous processing: %s\n",pai->name);
|
||||
wdStart(pcallback->wd_id,wait_time,(FUNCPTR)callbackRequest,(int)pcallback);
|
||||
|
||||
@@ -57,6 +57,12 @@
|
||||
* mgh 1/31/94 Started to add interrupt
|
||||
* ...
|
||||
* ...
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.3 1994/11/17 21:11:58 winans
|
||||
* Major restructuring of init code.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -74,7 +80,6 @@
|
||||
#include <dbAccess.h>
|
||||
#include <recSup.h>
|
||||
#include <devSup.h>
|
||||
#include <module_types.h>
|
||||
#include <link.h>
|
||||
#include <fast_lock.h>
|
||||
|
||||
@@ -87,15 +92,19 @@
|
||||
#include <errMdef.h>
|
||||
#include <eventRecord.h>
|
||||
|
||||
void SysmonInit();
|
||||
static long init();
|
||||
static long report();
|
||||
static long init_bo_record(), init_bi_record();
|
||||
static long init_mbbo_record(), init_mbbi_record();
|
||||
static long write_bo(), read_bi();
|
||||
static long write_mbbo(), read_mbbi();
|
||||
static long get_ioint_info();
|
||||
static void Sysmon_isr();
|
||||
|
||||
#define NUM_LINKS 1 /* max number of allowed sysmon cards */
|
||||
#define STATIC
|
||||
|
||||
int SysmonConfig();
|
||||
STATIC long SysmonInit();
|
||||
STATIC long SysmonReport();
|
||||
STATIC long SysmonInitBoRec(), SysmonInitBiRec();
|
||||
STATIC long SysmonInitMbboRec(), SysmonInitMbbiRec();
|
||||
STATIC long SysmonWriteBo(), SysmonReadBi();
|
||||
STATIC long SysmonWriteMbbo(), SysmonReadMbbi();
|
||||
static long SysmonGetIointInfoBi();
|
||||
STATIC void SysmonIsr();
|
||||
|
||||
int devSysmonDebug = 0;
|
||||
|
||||
@@ -108,29 +117,39 @@ int devSysmonDebug = 0;
|
||||
/** devSysmonDebug >= 20 -- read commands **/
|
||||
|
||||
|
||||
struct parm_table {
|
||||
typedef struct ParmTableStruct
|
||||
{
|
||||
char *parm_name;
|
||||
int index;
|
||||
};
|
||||
typedef struct parm_table PARM_TABLE;
|
||||
} ParmTableStruct;
|
||||
|
||||
#define SYSMON_PARM_STATUS 0
|
||||
#define SYSMON_PARM_DIO 1
|
||||
#define SYSMON_PARM_TEMP 2
|
||||
#define SYSMON_PARM_WATCHDOG 3
|
||||
|
||||
static PARM_TABLE table[]={
|
||||
{"StatusLink", 0},
|
||||
{"Dio", 1},
|
||||
{"IntMask", 2},
|
||||
{"Temperature", 3},
|
||||
{"Watchdog", 4},
|
||||
{"VXIVector", 5},
|
||||
{"IntVector", 6},
|
||||
{"IRQ1", 7},
|
||||
{"IRQ2", 8},
|
||||
{"IRQ3", 9},
|
||||
{"IRQ4", 10},
|
||||
{"IRQ5", 11},
|
||||
{"IRQ6", 12},
|
||||
{"IRQ7", 13}
|
||||
static ParmTableStruct ParmTable[]=
|
||||
{
|
||||
{"StatusLink", SYSMON_PARM_STATUS},
|
||||
{"Dio", SYSMON_PARM_DIO},
|
||||
{"Temperature", SYSMON_PARM_TEMP},
|
||||
{"Watchdog", SYSMON_PARM_WATCHDOG},
|
||||
|
||||
#if 0 /* This crap is pointless -- JRW */
|
||||
|
||||
{"IntMask", 2},
|
||||
{"VXIVector", 5},
|
||||
{"IntVector", 6},
|
||||
{"IRQ1", 7},
|
||||
{"IRQ2", 8},
|
||||
{"IRQ3", 9},
|
||||
{"IRQ4", 10},
|
||||
{"IRQ5", 11},
|
||||
{"IRQ6", 12},
|
||||
{"IRQ7", 13}
|
||||
#endif
|
||||
};
|
||||
#define PARM_TABLE_SIZE (sizeof(ParmTable)/sizeof(ParmTable[0]))
|
||||
|
||||
/*** SysMonStatusLink Rx, Tx ***/
|
||||
/*** SysmonDio output, input ***/
|
||||
@@ -147,7 +166,7 @@ static PARM_TABLE table[]={
|
||||
/*** SysmonIRQ6 IRQ 1 vector ***/
|
||||
/*** SysmonIRQ7 IRQ 1 vector ***/
|
||||
|
||||
struct sysmon {
|
||||
typedef struct SysmonStruct {
|
||||
char Pad[36]; /*** nF0 - nF17 36 bytes ***/
|
||||
unsigned short SysmonStatusLink; /*** nF18 ***/
|
||||
unsigned short SysmonDio; /*** nF19 ***/
|
||||
@@ -163,43 +182,42 @@ struct sysmon {
|
||||
unsigned short SysmonIRQ5; /*** nF29 ***/
|
||||
unsigned short SysmonIRQ6; /*** nF30 ***/
|
||||
unsigned short SysmonIRQ7; /*** nF31 ***/
|
||||
};
|
||||
}SysmonStruct;
|
||||
|
||||
struct pvtarea {
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Per-record private structure hooked onto dpvt.
|
||||
*
|
||||
*****************************************************************************/
|
||||
typedef struct PvtStruct
|
||||
{
|
||||
int index;
|
||||
unsigned short mask;
|
||||
};
|
||||
} PvtStruct;
|
||||
|
||||
struct ioCard { /* structure maintained for each card */
|
||||
int cardValid; /* card exists */
|
||||
volatile unsigned short *ThisCard; /* address of this cards registers */
|
||||
FAST_LOCK lock; /* semaphore */
|
||||
IOSCANPVT ioscanpvt; /* list of records that are processed at interrupt */
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Per-card global variables.
|
||||
*
|
||||
*****************************************************************************/
|
||||
struct ioCard { /* structure maintained for each card */
|
||||
int CardValid; /* card exists */
|
||||
unsigned long SysmonBaseA16; /* A16 card address */
|
||||
volatile SysmonStruct *SysmonBase; /* Physical card address */
|
||||
FAST_LOCK lock; /* semaphore */
|
||||
IOSCANPVT ioscanpvt; /* Token for I/O intr scanned records */
|
||||
int VMEintVector; /* IRQ vector used by sysmon */
|
||||
int VMEintLevel; /* IRQ level */
|
||||
int VXIintVector; /* Generated when C008 is written to (VXI silliness) */
|
||||
int IrqInfo[2];
|
||||
};
|
||||
|
||||
|
||||
#define CONST_NUM_LINKS 1
|
||||
#define STATIC
|
||||
|
||||
static int VMEintVector = 0x71;
|
||||
static int VMEintLevel = 0x06;
|
||||
static int VXIintVector = 0x72;
|
||||
static unsigned short *SYSMON_BASE = (unsigned short *) 0x8b80;
|
||||
#define INITLEDS 0x01
|
||||
|
||||
/* #define int1 0x71 */
|
||||
/* #define int2 0x72 */
|
||||
/* #define intlevel 0x06 */
|
||||
/* #define SYSMON_BASE 0x8b80 hard coded base address */
|
||||
static struct ioCard cards[NUM_LINKS]; /* card information structure */
|
||||
|
||||
#define INITLEDS 0xff
|
||||
#define mikeOFFSET 0x24 /* where first function starts */
|
||||
|
||||
volatile static struct sysmon *sysmon_base; /*base pointer of board */
|
||||
static struct ioCard cards[CONST_NUM_LINKS]; /* card information structure */
|
||||
static int init_flag = 0;
|
||||
static int interrupt_info[2]; /*0x71, 0x72*/
|
||||
|
||||
/* Create the dset for devBoSysmon */
|
||||
struct dset_sysmon {
|
||||
long number;
|
||||
DEVSUPFUN report; /* used by dbior */
|
||||
@@ -210,113 +228,152 @@ struct dset_sysmon {
|
||||
};
|
||||
typedef struct dset_sysmon DSET_SYSMON;
|
||||
|
||||
DSET_SYSMON devEventSysmon={
|
||||
5,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
get_ioint_info,
|
||||
NULL
|
||||
};
|
||||
|
||||
DSET_SYSMON devBoSysmon={
|
||||
5,
|
||||
NULL,
|
||||
SysmonInit,
|
||||
SysmonInitBoRec,
|
||||
NULL,
|
||||
init_bo_record,
|
||||
NULL,
|
||||
write_bo
|
||||
SysmonWriteBo
|
||||
};
|
||||
|
||||
/* Create the dset for devBiSysmon */
|
||||
DSET_SYSMON devBiSysmon={
|
||||
5,
|
||||
NULL,
|
||||
NULL,
|
||||
init_bi_record,
|
||||
NULL,
|
||||
read_bi
|
||||
SysmonReport,
|
||||
SysmonInit,
|
||||
SysmonInitBiRec,
|
||||
SysmonGetIointInfoBi,
|
||||
SysmonReadBi
|
||||
};
|
||||
|
||||
/* Create the dset for devMbboSysmon */
|
||||
DSET_SYSMON devMbboSysmon={
|
||||
5,
|
||||
NULL,
|
||||
SysmonInit,
|
||||
SysmonInitMbboRec,
|
||||
NULL,
|
||||
init_mbbo_record,
|
||||
NULL,
|
||||
write_mbbo
|
||||
SysmonWriteMbbo
|
||||
};
|
||||
|
||||
/* Create the dset for devMbbiSysmon */
|
||||
DSET_SYSMON devMbbiSysmon={
|
||||
5,
|
||||
NULL,
|
||||
SysmonInit,
|
||||
SysmonInitMbbiRec,
|
||||
NULL,
|
||||
init_mbbi_record,
|
||||
NULL,
|
||||
read_mbbi
|
||||
SysmonReadMbbi
|
||||
};
|
||||
|
||||
|
||||
STATIC long SysmonReport(void)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j=0; j<NUM_LINKS; j++)
|
||||
{
|
||||
if (cards[j].CardValid)
|
||||
{
|
||||
printf(" card %d: 0x%4.4X VME-IRQ 0x%2.2X VXI-IRQ 0x%2.2X IRQ-level %d\n",
|
||||
j, cards[j].SysmonBaseA16, cards[j].VMEintVector,
|
||||
cards[j].VXIintVector, cards[j].VMEintLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************
|
||||
initialization of the device support
|
||||
************************/
|
||||
|
||||
void SysmonInit(
|
||||
unsigned long xSYSMON_BASE,
|
||||
int xVMEintVector,
|
||||
int xVMEintLevel,
|
||||
int xVXIintVector
|
||||
int SysmonConfig(
|
||||
int Card, /* Which card to set parms for */
|
||||
unsigned long SysmonBaseA16, /* Base address in A16 */
|
||||
int VMEintVector, /* IRQ vector used by sysmon */
|
||||
int VMEintLevel, /* IRQ level */
|
||||
int VXIintVector /* Generated when C008 is written to (VXI silliness) */
|
||||
)
|
||||
{
|
||||
if ( 64 < xVMEintVector || xVMEintVector < 256 )
|
||||
VMEintVector = xVMEintVector;
|
||||
if (devSysmonDebug >= 5)
|
||||
printf("devSysmon: SysmonInit VME int vector = 0x%X\n", VMEintVector);
|
||||
if ((Card < 0) || (Card >= NUM_LINKS))
|
||||
{
|
||||
printf("ERROR: Invalid card number specified %d\n", Card);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if ( 0 > xVMEintLevel || xVMEintLevel < 8)
|
||||
VMEintLevel = xVMEintLevel;
|
||||
if (devSysmonDebug >= 5)
|
||||
printf("devSysmon: SysmonInit VME int level = %d\n", VMEintLevel);
|
||||
cards[Card].CardValid = 0;
|
||||
cards[Card].VMEintVector = 0;
|
||||
cards[Card].VMEintLevel = 0;
|
||||
cards[Card].VXIintVector = 0;
|
||||
cards[Card].SysmonBaseA16 = 0;
|
||||
cards[Card].IrqInfo[0] = 0;
|
||||
cards[Card].IrqInfo[1] = 0;
|
||||
|
||||
if ( 64 < xVXIintVector || xVXIintVector < 256 )
|
||||
VXIintVector = xVXIintVector;
|
||||
if (devSysmonDebug >= 5)
|
||||
printf("devSysmon: SysmonInit VXI int vector = 0x%X\n", VXIintVector);
|
||||
if ((VMEintVector < 64) || (VMEintVector > 255))
|
||||
{
|
||||
printf("devSysmon: ERROR VME IRQ vector out of range\n");
|
||||
return(-1);
|
||||
}
|
||||
if (devSysmonDebug >= 5)
|
||||
printf("devSysmon: SysmonInit VME int vector = 0x%2.2X\n", VMEintVector);
|
||||
|
||||
SYSMON_BASE = (unsigned short *) xSYSMON_BASE;
|
||||
if (devSysmonDebug >= 5)
|
||||
printf("devSysmon: SysmonInit VME (VXI) base address = 0x%X\n", SYSMON_BASE);
|
||||
if ((VMEintLevel < 0) || (VMEintLevel > 7))
|
||||
{
|
||||
printf("devSysmon: ERROR VME IRQ level out of range\n");
|
||||
return(-1);
|
||||
}
|
||||
if (devSysmonDebug >= 5)
|
||||
printf("devSysmon: SysmonInit VME int level = %d\n", VMEintLevel);
|
||||
|
||||
interrupt_info[0] = VMEintVector; /*0x71*/
|
||||
interrupt_info[1] = VXIintVector; /*0x72*/
|
||||
init(0);
|
||||
if ((VXIintVector < 64) || (VXIintVector > 255))
|
||||
{
|
||||
printf("devSysmon: ERROR VXI IRQ vector out of range\n");
|
||||
return(-1);
|
||||
}
|
||||
if (devSysmonDebug >= 5)
|
||||
printf("devSysmon: SysmonInit VXI int vector = 0x%2.2X\n", VXIintVector);
|
||||
|
||||
}
|
||||
if ((SysmonBaseA16 > 0xffff) || (SysmonBaseA16 & 0x003f))
|
||||
{
|
||||
printf("devSysmon: ERROR Invalid address specified 0x4.4X\n", SysmonBaseA16);
|
||||
return(-1);
|
||||
}
|
||||
if (devSysmonDebug >= 5)
|
||||
printf("devSysmon: SysmonInit VME (VXI) base address = %p\n", SysmonBaseA16);
|
||||
|
||||
cards[Card].VMEintVector = VMEintVector;
|
||||
cards[Card].VMEintLevel = VMEintLevel;
|
||||
cards[Card].VXIintVector = VXIintVector;
|
||||
cards[Card].SysmonBaseA16 = SysmonBaseA16;
|
||||
|
||||
cards[Card].IrqInfo[0] = VMEintVector; /*0x71*/
|
||||
cards[Card].IrqInfo[1] = VXIintVector; /*0x72*/
|
||||
|
||||
cards[Card].CardValid = 1;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
initialization of isr
|
||||
************************************************/
|
||||
**************************************************/
|
||||
|
||||
static void Sysmon_isr(IOSCANPVT ioscanpvt)
|
||||
STATIC void SysmonIsr(int Card)
|
||||
{
|
||||
logMsg("In Sysmon_isr\n");
|
||||
scanIoRequest(ioscanpvt);
|
||||
if (devSysmonDebug >= 10)
|
||||
logMsg("In SysmonIsr\n");
|
||||
scanIoRequest(cards[Card].ioscanpvt);
|
||||
cards[Card].SysmonBase->SysmonIntMask |= 0xff00;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Initialization of SYSMON Binary I/O Card
|
||||
*
|
||||
***************************************************************************/
|
||||
static long init(int flag)
|
||||
STATIC long SysmonInit(int flag)
|
||||
{
|
||||
int j;
|
||||
unsigned char probeVal, initVal;
|
||||
struct sysmon *sm;
|
||||
int Card;
|
||||
unsigned short probeVal;
|
||||
static int init_flag = 0;
|
||||
|
||||
|
||||
if (init_flag != 0)
|
||||
@@ -324,60 +381,59 @@ static long init(int flag)
|
||||
|
||||
init_flag = 1;
|
||||
|
||||
if (sysBusToLocalAdrs(VME_AM_SUP_SHORT_IO, (char *)SYSMON_BASE, (char **)&sysmon_base) == ERROR)
|
||||
{
|
||||
if (devSysmonDebug >= 5)
|
||||
printf("devSysmon: can not find short address space\n");
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
/* We end up here 1 time before all records are initialized */
|
||||
for (j=0; j < CONST_NUM_LINKS; j++)
|
||||
for (Card=0; Card < NUM_LINKS; Card++)
|
||||
{
|
||||
if (cards[Card].CardValid != 0)
|
||||
{
|
||||
if (devSysmonDebug >= 5)
|
||||
printf("devSysmon: init link %d\n", j);
|
||||
printf("devSysmon: init link %d\n", Card);
|
||||
|
||||
if (sysBusToLocalAdrs(VME_AM_SUP_SHORT_IO, (char *)cards[Card].SysmonBaseA16, (char **)&(cards[Card].SysmonBase)) == ERROR)
|
||||
{
|
||||
if (devSysmonDebug >= 5)
|
||||
printf("devSysmon: can not find short address space\n");
|
||||
return(ERROR); /* BUG */
|
||||
}
|
||||
|
||||
probeVal = INITLEDS;
|
||||
|
||||
if (devSysmonDebug >= 5)
|
||||
printf("devSysmon: init SysmonWatchdog 0x%X\n", (char *)&sysmon_base[j].SysmonWatchdog);
|
||||
printf("devSysmon: init SysmonWatchdog 0x%X\n", (char *)&cards[Card].SysmonBase->SysmonWatchdog);
|
||||
|
||||
if (vxMemProbe((char *)&sysmon_base[j].SysmonWatchdog, WRITE, sizeof(probeVal), &probeVal) != OK)
|
||||
if (vxMemProbe((char *)&cards[Card].SysmonBase->SysmonWatchdog, WRITE, sizeof(cards[Card].SysmonBase->SysmonWatchdog), (char *)&probeVal) != OK)
|
||||
{
|
||||
cards[j].cardValid = 0; /* No card found */
|
||||
cards[Card].CardValid = 0; /* No card found */
|
||||
if (devSysmonDebug >= 5)
|
||||
printf("devSysmon: init vxMemProbe FAILED\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
probeVal = 0;
|
||||
vxMemProbe((char *)&sysmon_base[j].SysmonIntMask, WRITE, sizeof(probeVal), &probeVal);
|
||||
cards[j].cardValid = 1; /* Remember address of the board */
|
||||
FASTLOCKINIT(&(cards[j].lock));
|
||||
FASTUNLOCK(&(cards[j].lock)); /* Init the board lock */
|
||||
cards[j].ThisCard = &sysmon_base[j].SysmonStatusLink;
|
||||
cards[Card].SysmonBase->SysmonIntMask = 0;
|
||||
|
||||
FASTLOCKINIT(&(cards[Card].lock));
|
||||
/* FASTUNLOCK(&(cards[Card].lock)); /* Init the board lock */
|
||||
|
||||
if (devSysmonDebug >= 5)
|
||||
printf("devSysmon: init address\n");
|
||||
|
||||
|
||||
scanIoInit(&cards[j].ioscanpvt); /* interrupt initialized */
|
||||
scanIoInit(&cards[Card].ioscanpvt); /* interrupt initialized */
|
||||
|
||||
if (devSysmonDebug >= 5)
|
||||
printf("devSysmon: init ScanIoInit \n");
|
||||
|
||||
sm = (struct sysmon *) &sysmon_base[j];
|
||||
if (devSysmonDebug >= 5)
|
||||
printf("devSysmon: init address of System Monitor %8.8x \n", sm);
|
||||
printf("devSysmon: init address of System Monitor %8.8x \n", cards[Card].SysmonBase);
|
||||
|
||||
sm->SysmonIntVector = interrupt_info[0];
|
||||
cards[Card].SysmonBase->SysmonIntVector = cards[Card].VMEintVector;
|
||||
|
||||
if (devSysmonDebug >= 5)
|
||||
printf("devSysmon: init Interrupt vector loaded \n");
|
||||
|
||||
if(intConnect(INUM_TO_IVEC(interrupt_info[j]),(FUNCPTR)Sysmon_isr,
|
||||
(int)cards[j].ioscanpvt)!=OK) {
|
||||
errPrintf(M_devSup, __FILE__, __LINE__, "devSysmon (init) intConnect failed \n");
|
||||
return(M_devSup);
|
||||
if(intConnect(INUM_TO_IVEC(cards[Card].VMEintVector),(FUNCPTR)SysmonIsr, Card)!=OK)
|
||||
{
|
||||
printf("devSysmon (init) intConnect failed \n");
|
||||
return(ERROR);
|
||||
|
||||
if (devSysmonDebug >= 5)
|
||||
printf("devSysmon: init intConnect\n");
|
||||
@@ -388,6 +444,8 @@ static long init(int flag)
|
||||
printf("devSysmon: init vxMemProbe OK\n");
|
||||
|
||||
}
|
||||
sysIntEnable(cards[Card].VMEintLevel);
|
||||
}
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
@@ -398,21 +456,19 @@ static long init(int flag)
|
||||
|
||||
static long generic_init_record(struct dbCommon *pr, DBLINK *link)
|
||||
{
|
||||
struct vmeio* pvmeio = (struct vmeio*)&(link->value);
|
||||
int table_size, j;
|
||||
struct pvtarea * pvt;
|
||||
struct vmeio *pvmeio = (struct vmeio*)&(link->value);
|
||||
int j;
|
||||
PvtStruct *pvt;
|
||||
|
||||
switch (link->type)
|
||||
if (link->type != VME_IO)
|
||||
{
|
||||
case (VME_IO) : break;
|
||||
default:
|
||||
recGblRecordError(S_dev_badBus,(void *)pr,
|
||||
"devSysmon (init_record) Illegal Bus Type");
|
||||
return(S_dev_badBus);
|
||||
}
|
||||
|
||||
/* makes sure that signal is valid */
|
||||
if (pvmeio->signal > 15)
|
||||
/* make sure that signal is valid */
|
||||
if ((pvmeio->signal > 15) || (pvmeio->signal < 0))
|
||||
{
|
||||
pr->pact = 1; /* make sure we don't process this thing */
|
||||
|
||||
@@ -425,14 +481,14 @@ static long generic_init_record(struct dbCommon *pr, DBLINK *link)
|
||||
}
|
||||
|
||||
/* makes sure that card is valid */
|
||||
if (pvmeio->card > CONST_NUM_LINKS || !cards[pvmeio->card].cardValid )
|
||||
if ((pvmeio->card > NUM_LINKS) || (pvmeio->card < 0) || (!cards[pvmeio->card].CardValid))
|
||||
{
|
||||
pr->pact = 1; /* make sure we don't process this thing */
|
||||
|
||||
if (devSysmonDebug >= 10)
|
||||
{
|
||||
printf("devSysmon: Illegal CARD field ->%s, %d<- \n", pr->name, pvmeio->card);
|
||||
if(!cards[pvmeio->card].cardValid)
|
||||
if(!cards[pvmeio->card].CardValid)
|
||||
printf("devSysmon: Illegal CARD field card NOT VALID \n\n");
|
||||
}
|
||||
|
||||
@@ -442,11 +498,9 @@ static long generic_init_record(struct dbCommon *pr, DBLINK *link)
|
||||
}
|
||||
|
||||
/* verifies that parm field is valid */
|
||||
|
||||
table_size = sizeof(table) / sizeof(PARM_TABLE);
|
||||
for (j = 0; (j < table_size) && strcmp(table[j].parm_name, pvmeio->parm); j++ );
|
||||
for (j = 0; (j < PARM_TABLE_SIZE) && strcmp(ParmTable[j].parm_name, pvmeio->parm); j++ );
|
||||
|
||||
if (j >= table_size)
|
||||
if (j >= PARM_TABLE_SIZE)
|
||||
{
|
||||
pr->pact = 1; /* make sure we don't process this thing */
|
||||
|
||||
@@ -458,9 +512,9 @@ static long generic_init_record(struct dbCommon *pr, DBLINK *link)
|
||||
return(S_dev_badSignal);
|
||||
}
|
||||
if (devSysmonDebug >= 10)
|
||||
printf("devSysmon: %s of record type %d - %s\n", pr->name, j, table[j].parm_name);
|
||||
printf("devSysmon: %s of record type %d - %s\n", pr->name, j, ParmTable[j].parm_name);
|
||||
|
||||
pvt = (struct pvtarea *) malloc(sizeof(struct pvtarea));
|
||||
pvt = (PvtStruct *) malloc(sizeof(PvtStruct));
|
||||
pvt->index = j;
|
||||
|
||||
pr->dpvt = pvt;
|
||||
@@ -474,21 +528,17 @@ static long generic_init_record(struct dbCommon *pr, DBLINK *link)
|
||||
* BO Initialization (Called one time for each BO SYSMON card record)
|
||||
*
|
||||
**************************************************************************/
|
||||
static long init_bo_record(struct boRecord *pbo)
|
||||
STATIC long SysmonInitBoRec(struct boRecord *pbo)
|
||||
{
|
||||
struct vmeio* pvmeio = (struct vmeio*)&(pbo->out.value);
|
||||
int status = 0;
|
||||
int table_size;
|
||||
struct pvtarea * pvt;
|
||||
|
||||
|
||||
status = generic_init_record((struct dbCommon *)pbo, &pbo->out);
|
||||
|
||||
if(status)
|
||||
return(status);
|
||||
|
||||
pvt = pbo->dpvt;
|
||||
|
||||
pvt->mask = 1<<pvmeio->signal;
|
||||
((PvtStruct *)(pbo->dpvt))->mask = 1<<pvmeio->signal;
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -498,21 +548,17 @@ static long init_bo_record(struct boRecord *pbo)
|
||||
* BI Initialization (Called one time for each BI SYSMON card record)
|
||||
*
|
||||
**************************************************************************/
|
||||
static long init_bi_record(struct biRecord *pbi)
|
||||
STATIC long SysmonInitBiRec(struct biRecord *pbi)
|
||||
{
|
||||
struct vmeio* pvmeio = (struct vmeio*)&(pbi->inp.value);
|
||||
int status = 0;
|
||||
int table_size;
|
||||
struct pvtarea * pvt;
|
||||
|
||||
status = generic_init_record((struct dbCommon *)pbi, &pbi->inp);
|
||||
|
||||
if(status)
|
||||
return(status);
|
||||
|
||||
pvt = pbi->dpvt;
|
||||
|
||||
pvt->mask = 1<<pvmeio->signal;
|
||||
((PvtStruct *)(pbi->dpvt))->mask = 1<<pvmeio->signal;
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -523,26 +569,16 @@ static long init_bi_record(struct biRecord *pbi)
|
||||
* MBBO Initialization (Called one time for each MBBO SYSMON card record)
|
||||
*
|
||||
**************************************************************************/
|
||||
static long init_mbbo_record(struct mbboRecord *pmbbo)
|
||||
STATIC long SysmonInitMbboRec(struct mbboRecord *pmbbo)
|
||||
{
|
||||
struct vmeio* pvmeio = (struct vmeio*)&(pmbbo->out.value);
|
||||
int status = 0;
|
||||
int table_size;
|
||||
struct pvtarea * pvt;
|
||||
|
||||
status = generic_init_record((struct dbCommon *)pmbbo, &pmbbo->out);
|
||||
|
||||
if(status)
|
||||
return(status);
|
||||
|
||||
if (pvmeio->signal > 15)
|
||||
{
|
||||
recGblRecordError(S_dev_badSignal,(void *)pmbbo,
|
||||
"devSysmon(init_mbbo_record) Illegal OUT signal number");
|
||||
return(S_dev_badSignal);
|
||||
}
|
||||
|
||||
pvt = pmbbo->dpvt;
|
||||
pmbbo->shft = pvmeio->signal;
|
||||
pmbbo->mask <<= pmbbo->shft;
|
||||
|
||||
@@ -556,18 +592,16 @@ static long init_mbbo_record(struct mbboRecord *pmbbo)
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
static long init_mbbi_record(struct mbbiRecord *pmbbi)
|
||||
STATIC long SysmonInitMbbiRec(struct mbbiRecord *pmbbi)
|
||||
{
|
||||
struct vmeio* pvmeio = (struct vmeio*)&(pmbbi->inp.value);
|
||||
int status = 0;
|
||||
int table_size;
|
||||
struct pvtarea * pvt;
|
||||
|
||||
status = generic_init_record((struct dbCommon *)pmbbi, &pmbbi->inp);
|
||||
|
||||
/* load temperature values up */
|
||||
/* load temperature values up */
|
||||
|
||||
if (!strcmp(table[3].parm_name, pvmeio->parm))
|
||||
if (!strcmp(ParmTable[3].parm_name, pvmeio->parm))
|
||||
{
|
||||
if (devSysmonDebug >= 10)
|
||||
printf("devSysmon: mbbi record is Temperature\n");
|
||||
@@ -614,14 +648,6 @@ static long init_mbbi_record(struct mbbiRecord *pmbbi)
|
||||
if(status)
|
||||
return(status);
|
||||
|
||||
if (pvmeio->signal > 15)
|
||||
{
|
||||
recGblRecordError(S_dev_badSignal,(void *)pmbbi,
|
||||
"devSysmon(init_mbbi_record) Illegal IN signal number");
|
||||
return(S_dev_badSignal);
|
||||
}
|
||||
|
||||
pvt = pmbbi->dpvt;
|
||||
pmbbi->shft = pvmeio->signal;
|
||||
pmbbi->mask <<= pmbbi->shft;
|
||||
|
||||
@@ -633,29 +659,33 @@ static long init_mbbi_record(struct mbbiRecord *pmbbi)
|
||||
* Perform a write operation from a BO record
|
||||
*
|
||||
**************************************************************************/
|
||||
static long write_bo(struct boRecord *pbo)
|
||||
STATIC long SysmonWriteBo(struct boRecord *pbo)
|
||||
{
|
||||
struct pvtarea *pvt = pbo->dpvt;
|
||||
struct vmeio *pvmeio = (struct vmeio*)&(pbo->out.value);
|
||||
volatile unsigned short *reg;
|
||||
unsigned short regVal;
|
||||
PvtStruct *pvt = (PvtStruct *)pbo->dpvt;
|
||||
|
||||
FASTLOCK(&cards[pvmeio->card].lock);
|
||||
reg = &cards[pvmeio->card].ThisCard[pvt->index];
|
||||
regVal = *reg;
|
||||
|
||||
if(pbo->val)
|
||||
switch (pvt->index)
|
||||
{
|
||||
regVal |= pvt->mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
regVal &= ~pvt->mask;
|
||||
case SYSMON_PARM_DIO:
|
||||
|
||||
if (pbo->val)
|
||||
cards[pvmeio->card].SysmonBase->SysmonDio |= pvt->mask;
|
||||
else
|
||||
cards[pvmeio->card].SysmonBase->SysmonDio &= ~pvt->mask;
|
||||
break;
|
||||
|
||||
case SYSMON_PARM_WATCHDOG:
|
||||
|
||||
if (pbo->val)
|
||||
cards[pvmeio->card].SysmonBase->SysmonWatchdog |= pvt->mask;
|
||||
else
|
||||
cards[pvmeio->card].SysmonBase->SysmonWatchdog &= ~pvt->mask;
|
||||
break;
|
||||
}
|
||||
|
||||
*reg = regVal;
|
||||
FASTUNLOCK(&cards[pvmeio->card].lock);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -664,19 +694,30 @@ static long write_bo(struct boRecord *pbo)
|
||||
* Perform a read operation from a BI record
|
||||
*
|
||||
**************************************************************************/
|
||||
static long read_bi(struct biRecord *pbi)
|
||||
STATIC long SysmonReadBi(struct biRecord *pbi)
|
||||
{
|
||||
struct pvtarea *pvt = pbi->dpvt;
|
||||
struct vmeio *pvmeio = (struct vmeio*)&(pbi->inp.value);
|
||||
volatile unsigned short *reg;
|
||||
unsigned short regVal;
|
||||
|
||||
reg = &cards[pvmeio->card].ThisCard[pvt->index];
|
||||
|
||||
unsigned short regVal = 0;
|
||||
PvtStruct *pvt = (PvtStruct *)pbi->dpvt;
|
||||
FASTLOCK(&cards[pvmeio->card].lock);
|
||||
regVal = *reg;
|
||||
|
||||
switch (pvt->index)
|
||||
{
|
||||
case SYSMON_PARM_STATUS:
|
||||
regVal = cards[pvmeio->card].SysmonBase->SysmonStatusLink;
|
||||
break;
|
||||
case SYSMON_PARM_DIO:
|
||||
regVal = cards[pvmeio->card].SysmonBase->SysmonDio;
|
||||
break;
|
||||
case SYSMON_PARM_WATCHDOG:
|
||||
regVal = cards[pvmeio->card].SysmonBase->SysmonWatchdog;
|
||||
break;
|
||||
}
|
||||
FASTUNLOCK(&cards[pvmeio->card].lock);
|
||||
|
||||
if (devSysmonDebug)
|
||||
printf("read 0x%2.2X, masking with 0x%2.2X\n", regVal, pvt->mask);
|
||||
|
||||
regVal &= pvt->mask;
|
||||
|
||||
if(regVal)
|
||||
@@ -693,18 +734,17 @@ static long read_bi(struct biRecord *pbi)
|
||||
* Perform a write operation from a MBBO record
|
||||
*
|
||||
**************************************************************************/
|
||||
static long write_mbbo(struct mbboRecord *pmbbo)
|
||||
STATIC long SysmonWriteMbbo(struct mbboRecord *pmbbo)
|
||||
{
|
||||
struct pvtarea *pvt = pmbbo->dpvt;
|
||||
struct vmeio *pvmeio = (struct vmeio*)&(pmbbo->out.value);
|
||||
volatile unsigned short *reg;
|
||||
unsigned short regVal;
|
||||
|
||||
FASTLOCK(&cards[pvmeio->card].lock);
|
||||
reg = &cards[pvmeio->card].ThisCard[pvt->index];
|
||||
regVal = *reg;
|
||||
|
||||
regVal = cards[pvmeio->card].SysmonBase->SysmonTemperature;
|
||||
regVal = (regVal & ~pmbbo->mask) | (pmbbo->rval & pmbbo->mask);
|
||||
*reg = regVal;
|
||||
cards[pvmeio->card].SysmonBase->SysmonTemperature = regVal;
|
||||
|
||||
FASTUNLOCK(&cards[pvmeio->card].lock);
|
||||
|
||||
return(0);
|
||||
@@ -715,48 +755,55 @@ static long write_mbbo(struct mbboRecord *pmbbo)
|
||||
* Perform a read operation from a MBBI record
|
||||
*
|
||||
**************************************************************************/
|
||||
static long read_mbbi(struct mbbiRecord *pmbbi)
|
||||
STATIC long SysmonReadMbbi(struct mbbiRecord *pmbbi)
|
||||
{
|
||||
|
||||
struct pvtarea *pvt = pmbbi->dpvt;
|
||||
struct vmeio *pvmeio = (struct vmeio*)&(pmbbi->inp.value);
|
||||
volatile unsigned short *reg;
|
||||
unsigned short regVal;
|
||||
|
||||
reg = &cards[pvmeio->card].ThisCard[pvt->index];
|
||||
|
||||
FASTLOCK(&cards[pvmeio->card].lock);
|
||||
regVal = *reg;
|
||||
|
||||
regVal = cards[pvmeio->card].SysmonBase->SysmonTemperature;
|
||||
|
||||
FASTUNLOCK(&cards[pvmeio->card].lock);
|
||||
|
||||
pmbbi->rval=regVal&pmbbi->mask;
|
||||
pmbbi->rval=regVal & pmbbi->mask;
|
||||
pmbbi->udf = 0;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
record support interrupt routine
|
||||
***************************************************/
|
||||
*
|
||||
* cmd = 0 if being added
|
||||
* cmd = 1 if taken off the I/O Event scanned list
|
||||
*
|
||||
****************************************************/
|
||||
|
||||
static long get_ioint_info(
|
||||
static long SysmonGetIointInfoBi(
|
||||
int cmd,
|
||||
struct eventRecord *pr,
|
||||
struct biRecord *pr,
|
||||
IOSCANPVT *ppvt)
|
||||
{
|
||||
struct vmeio *pvmeio = (struct vmeio *)(&pr->inp.value);
|
||||
unsigned int card,intvec;
|
||||
int intmask;
|
||||
|
||||
if(pvmeio->card > CONST_NUM_LINKS) {
|
||||
if(pvmeio->card > NUM_LINKS) {
|
||||
recGblRecordError(S_dev_badCard,(void *)pr,
|
||||
"devSysmon (get_int_info) exceeded maximum supported cards");
|
||||
return(S_dev_badCard);
|
||||
}
|
||||
*ppvt = cards[pvmeio->card].ioscanpvt;
|
||||
|
||||
|
||||
if (cmd == 0)
|
||||
sysIntEnable(VMEintLevel);
|
||||
{
|
||||
intmask = (((PvtStruct *)(pr->dpvt))->mask)>>8;
|
||||
|
||||
if (devSysmonDebug)
|
||||
printf("SysmonGetIointInfoBi mask is %2.2X\n", intmask);
|
||||
|
||||
cards[pvmeio->card].SysmonBase->SysmonIntMask |= intmask;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,28 +4,73 @@ include $(EPICS)/config/CONFIG_BASE
|
||||
|
||||
USR_CFLAGS = -fshared-data -fvolatile -mnobitfield -traditional
|
||||
|
||||
|
||||
SRCS.c = \
|
||||
../module_types.c ../drvXy010.c ../drvAb.c ../drvBb902.c \
|
||||
../drvBb910.c ../drvCompuSm.c ../drvDvx.c ../drvMz8310.c \
|
||||
../drvOms.c ../drvStc.c ../drvTime.c ../drvVmi4100.c \
|
||||
../drvXy210.c ../drvXy220.c ../drvXy240.c \
|
||||
../drvXy566.c ../drvAt5Vxi.c ../drvHp1404a.c ../drvEpvxi.c \
|
||||
../drvEpvxiMsg.c ../drvBitBus.c ../drvGpib.c \
|
||||
../drvMsg.c ../drvBB232.c ../drvHpe1368a.c ../drvHpe1445a.c \
|
||||
../drvKscV215.c ../drvComet.c ../drvJgvtr1.c ../drvFp.c \
|
||||
../drvMvme162.c ../drvFpm.c
|
||||
../module_types.c\
|
||||
../drvXy010.c\
|
||||
../drvAb.c\
|
||||
../drvBb902.c\
|
||||
../drvBb910.c\
|
||||
../drvCompuSm.c\
|
||||
../drvDvx.c\
|
||||
../drvMz8310.c\
|
||||
../drvOms.c\
|
||||
../drvStc.c\
|
||||
../drvTime.c\
|
||||
../drvVmi4100.c\
|
||||
../drvXy210.c\
|
||||
../drvXy220.c\
|
||||
../drvXy240.c\
|
||||
../drvXy566.c\
|
||||
../drvAt5Vxi.c\
|
||||
../drvHp1404a.c\
|
||||
../drvEpvxi.c\
|
||||
../drvEpvxiMsg.c\
|
||||
../drvBitBus.c\
|
||||
../drvGpib.c\
|
||||
../drvMsg.c\
|
||||
../drvBB232.c\
|
||||
../drvHpe1368a.c\
|
||||
../drvHpe1445a.c\
|
||||
../drvKscV215.c\
|
||||
../drvComet.c\
|
||||
../drvJgvtr1.c\
|
||||
../drvFp.c\
|
||||
../drvMvme162.c\
|
||||
../drvFpm.c
|
||||
|
||||
OBJS = \
|
||||
module_types.o drvXy010.o drvAb.o drvBb902.o \
|
||||
drvBb910.o drvCompuSm.o drvDvx.o drvMz8310.o \
|
||||
drvOms.o drvStc.o drvTime.o drvVmi4100.o \
|
||||
drvXy210.o drvXy220.o drvXy240.o \
|
||||
drvXy566.o drvAt5Vxi.o drvHp1404a.o drvEpvxi.o \
|
||||
drvEpvxiMsg.o drvBitBus.o drvGpib.o \
|
||||
drvMsg.o drvBB232.o drvHpe1368a.o drvHpe1445a.o \
|
||||
drvKscV215.o drvComet.o drvJgvtr1.o drvFp.o \
|
||||
drvMvme162.o drvFpm.o
|
||||
module_types.o\
|
||||
drvXy010.o\
|
||||
drvAb.o\
|
||||
drvBb902.o\
|
||||
drvBb910.o\
|
||||
drvCompuSm.o\
|
||||
drvDvx.o\
|
||||
drvMz8310.o\
|
||||
drvOms.o\
|
||||
drvStc.o\
|
||||
drvTime.o\
|
||||
drvVmi4100.o\
|
||||
drvXy210.o\
|
||||
drvXy220.o\
|
||||
drvXy240.o\
|
||||
drvXy566.o\
|
||||
drvAt5Vxi.o\
|
||||
drvHp1404a.o\
|
||||
drvEpvxi.o\
|
||||
drvEpvxiMsg.o\
|
||||
drvBitBus.o\
|
||||
drvGpib.o\
|
||||
drvMsg.o\
|
||||
drvBB232.o\
|
||||
drvHpe1368a.o\
|
||||
drvHpe1445a.o\
|
||||
drvKscV215.o\
|
||||
drvComet.o\
|
||||
drvJgvtr1.o\
|
||||
drvFp.o\
|
||||
drvMvme162.o\
|
||||
drvFpm.o
|
||||
|
||||
PROD = drvSup
|
||||
|
||||
@@ -35,3 +80,6 @@ $(PROD): $(OBJS)
|
||||
$(RM) $@
|
||||
$(LINK.c) $@ $(OBJS) $(LDLIBS)
|
||||
|
||||
|
||||
# ../drvCaenV265.c\
|
||||
# drvCaenV265.o\
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef EPICS_DRVBITBUS_H
|
||||
#define EPICS_DRVBITBUS_H
|
||||
|
||||
#define BB_SUPER_DEBUG
|
||||
/* #define BB_SUPER_DEBUG */
|
||||
|
||||
/*
|
||||
* Author: John Winans
|
||||
@@ -36,6 +36,9 @@
|
||||
* .03 07-01-94 jrw Bigtime hacking... merged PEP and Xycom.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.8 1994/10/04 18:42:44 winans
|
||||
* Added an extensive debugging facility.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
807
src/drv/drvCaenV265.c
Normal file
807
src/drv/drvCaenV265.c
Normal file
@@ -0,0 +1,807 @@
|
||||
/* share/src/drv @(#)drvCaenV265.c 1.1 9/2/94 */
|
||||
/* drvCaenV265.c - Driver/Device Support Routines for CAEN V265
|
||||
*
|
||||
* Author: Jeff Hill (johill@lanl.gov)
|
||||
* Date: 8-11-94
|
||||
*
|
||||
* 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
|
||||
* MIT Bates Lab
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* ANSI C Includes
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <types.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* vxWorks includes
|
||||
*/
|
||||
#include <vme.h>
|
||||
#include <iv.h>
|
||||
#include <sysLib.h>
|
||||
#include <intLib.h>
|
||||
#include <logLib.h>
|
||||
#include <vxLib.h>
|
||||
#include <rebootLib.h>
|
||||
#include <taskLib.h>
|
||||
#include <tickLib.h>
|
||||
#include <wdLib.h>
|
||||
|
||||
/*
|
||||
* EPICS include
|
||||
*/
|
||||
#include <dbDefs.h>
|
||||
#include <dbScan.h>
|
||||
#include <drvSup.h>
|
||||
#include <devSup.h>
|
||||
#include <recSup.h>
|
||||
#include <devLib.h>
|
||||
#include <aiRecord.h>
|
||||
#include <errMdef.h>
|
||||
|
||||
|
||||
/*
|
||||
* base address, base interrupt vector,
|
||||
* number of cards, & interrupt level
|
||||
*/
|
||||
#define CAIN_V265_A24_BASE (0x000000)
|
||||
#define CAIN_V265_INTVEC_BASE (0xA0)
|
||||
#define CAIN_V265_MAX_CARD_COUNT (8)
|
||||
#define CAIN_V265_INT_LEVEL (6)
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* all device registers declared
|
||||
* ANSI C volatile so we dont need to
|
||||
* use the -fvolatile flag (and dont
|
||||
* limit the optimizer)
|
||||
*/
|
||||
typedef volatile int16_t devReg;
|
||||
|
||||
struct caenV265 {
|
||||
devReg csr;
|
||||
devReg clear;
|
||||
devReg DAC;
|
||||
devReg gate;
|
||||
const devReg data;
|
||||
const devReg pad1[(0xf8-0x8)/2];
|
||||
const devReg fixed;
|
||||
const devReg identifier;
|
||||
const devReg version;
|
||||
};
|
||||
#define CAENV265ID 0x0812
|
||||
|
||||
/*
|
||||
* Insert or extract a bit field using the standard
|
||||
* masks and shifts defined below
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
#define INSERT(FIELD,VALUE)\
|
||||
(((VALUE)&(FD_ ## FIELD ## _M))<<(FD_ ## FIELD ## _S))
|
||||
#define EXTRACT(FIELD,VALUE)\
|
||||
( ((VALUE)>>(FD_ ## FIELD ## _S)) &(FD_ ## FIELD ## _M))
|
||||
#else /*__STDC__*/
|
||||
#define INSERT(FIELD,VALUE)\
|
||||
(((VALUE)&(FD_/* */FIELD/* */_M))<<(FD_/* */FIELD/* */_S))
|
||||
#define EXTRACT(FIELD,VALUE)\
|
||||
( ((VALUE)>>(FD_/* */FIELD/* */_S)) &(FD_/* */FIELD/* */_M))
|
||||
#endif /*__STDC__*/
|
||||
|
||||
/*
|
||||
* in the constants below _M is a right justified mask
|
||||
* and _S is a shift required to right justify the field
|
||||
*/
|
||||
|
||||
/*
|
||||
* csr register
|
||||
*/
|
||||
#define FD_FULL_M (0x1)
|
||||
#define FD_FULL_S (14)
|
||||
#define FD_READY_M (0x1)
|
||||
#define FD_READY_S (15)
|
||||
#define FD_BUSY_FULL_M (0x3)
|
||||
#define FD_BUSY_FULL_S (14)
|
||||
#define FD_IVEC_M (0xff)
|
||||
#define FD_IVEC_S (0)
|
||||
#define FD_ILEVEL_M (0x7)
|
||||
#define FD_ILEVEL_S (8)
|
||||
|
||||
/*
|
||||
* series/version register
|
||||
*/
|
||||
#define FD_SERIES_M (0xfff)
|
||||
#define FD_SERIES_S (0)
|
||||
#define FD_VERSION_M (0xf)
|
||||
#define FD_VERSION_S (12)
|
||||
|
||||
/*
|
||||
* data register
|
||||
*/
|
||||
#define FD_CHANNEL_M (0x7)
|
||||
#define FD_CHANNEL_S (13)
|
||||
#define FD_RANGE_M (1)
|
||||
#define FD_RANGE_S (12)
|
||||
#define FD_DATA_M (0xfff)
|
||||
#define FD_DATA_S (0)
|
||||
|
||||
struct channel{
|
||||
int16_t signal;
|
||||
char newData;
|
||||
};
|
||||
|
||||
enum adc_range {adc_12, adc_15, NUMBER_OF_ADC_RANGES};
|
||||
#define NUMBER_OF_SIGNALS 8
|
||||
#define NUMBER_OF_FIFO_ENTRIES (16*NUMBER_OF_SIGNALS*NUMBER_OF_ADC_RANGES)
|
||||
LOCAL struct caenV265Config{
|
||||
struct caenV265 *pCaenV265; /* pointer to the card */
|
||||
struct channel chan[NUMBER_OF_SIGNALS][NUMBER_OF_ADC_RANGES];
|
||||
IOSCANPVT scanpvt;
|
||||
WDOG_ID wdid;
|
||||
}caenV265Info[CAIN_V265_MAX_CARD_COUNT];
|
||||
|
||||
#ifdef __STDC__
|
||||
#define SHOW_OFFSET(STRUCT,FIELD) \
|
||||
printf( "%s.%s is at 0x%X\n", \
|
||||
#STRUCT, \
|
||||
#FIELD, \
|
||||
offsetof(struct STRUCT, FIELD))
|
||||
#endif
|
||||
|
||||
LOCAL void caenV265ISR(unsigned card);
|
||||
LOCAL int caenV265Shutdown(void);
|
||||
LOCAL int caenV265IdTest(struct caenV265 *pCaenV265);
|
||||
int caenV265Test(unsigned card);
|
||||
LOCAL void caenV265ReadData(struct caenV265Config *pCaenV256Config);
|
||||
LOCAL int caenV265TestVal(unsigned card, unsigned dacVal);
|
||||
LOCAL int caenV265IntEnable(unsigned card);
|
||||
|
||||
/*
|
||||
* device support entry table
|
||||
*/
|
||||
LOCAL long caenV265InitRecord(struct aiRecord *pai);
|
||||
LOCAL long caenV265AiRead(struct aiRecord *pai);
|
||||
LOCAL long caenV265SpecialLinconv(struct aiRecord *pai, int after);
|
||||
LOCAL long caenV265GetIoIntInfo(int cmd, struct aiRecord *pai, IOSCANPVT *ppvt);
|
||||
struct {
|
||||
long number;
|
||||
DEVSUPFUN report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record;
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_ai;
|
||||
DEVSUPFUN special_linconv;
|
||||
} devCaenV265 ={
|
||||
6,
|
||||
NULL,
|
||||
NULL,
|
||||
caenV265InitRecord,
|
||||
caenV265GetIoIntInfo,
|
||||
caenV265AiRead,
|
||||
caenV265SpecialLinconv};
|
||||
|
||||
/*
|
||||
* driver support entry table
|
||||
*/
|
||||
LOCAL long caenV265Init(void);
|
||||
LOCAL long caenV265IOReport(int level);
|
||||
struct {
|
||||
long number;
|
||||
DRVSUPFUN report;
|
||||
DRVSUPFUN init;
|
||||
} drvCaenV265 ={
|
||||
2,
|
||||
caenV265IOReport,
|
||||
caenV265Init};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* verify that register
|
||||
* offsets match the doc.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
void offsettest()
|
||||
{
|
||||
SHOW_OFFSET(caenV265, version);
|
||||
SHOW_OFFSET(caenV265, identifier);
|
||||
SHOW_OFFSET(caenV265, fixed);
|
||||
SHOW_OFFSET(caenV265, data);
|
||||
SHOW_OFFSET(caenV265, gate);
|
||||
SHOW_OFFSET(caenV265, DAC);
|
||||
SHOW_OFFSET(caenV265, clear);
|
||||
SHOW_OFFSET(caenV265, csr);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* caenV265InitRecord()
|
||||
*/
|
||||
LOCAL long caenV265InitRecord(struct aiRecord *pai)
|
||||
{
|
||||
struct vmeio *pvmeio;
|
||||
|
||||
/* ai.inp must be an VME_IO */
|
||||
switch (pai->inp.type) {
|
||||
case (VME_IO):
|
||||
break;
|
||||
default :
|
||||
recGblRecordError(S_db_badField,(void *)pai,
|
||||
"devAiXy566Se (init_record) Illegal INP field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
|
||||
pvmeio = (struct vmeio *)&(pai->inp.value);
|
||||
|
||||
/*
|
||||
* check for bad signal or card number
|
||||
*/
|
||||
if ( pvmeio->signal >= NUMBER_OF_SIGNALS ||
|
||||
pvmeio->card >= CAIN_V265_MAX_CARD_COUNT ) {
|
||||
|
||||
recGblRecordError(
|
||||
S_db_badField,
|
||||
(void *)pai,
|
||||
"devCaenV265 bad card or signal number");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!caenV265Info[pvmeio->card].pCaenV265){
|
||||
recGblRecordError(
|
||||
S_db_badField,
|
||||
(void *)pai,
|
||||
"devCaenV265 card does not exist");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* set linear conversion slope*/
|
||||
pai->eslo = (pai->eguf-pai->egul)/FD_DATA_M;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265AiRead()
|
||||
*/
|
||||
LOCAL long caenV265AiRead(struct aiRecord *pai)
|
||||
{
|
||||
int16_t value;
|
||||
struct vmeio *pvmeio;
|
||||
|
||||
pvmeio = (struct vmeio *)&(pai->inp.value);
|
||||
|
||||
/*
|
||||
* check for bad signal or card number
|
||||
*/
|
||||
if ( pvmeio->signal >= NUMBER_OF_SIGNALS ||
|
||||
pvmeio->card >= CAIN_V265_MAX_CARD_COUNT ) {
|
||||
|
||||
recGblSetSevr(pai, READ_ALARM, INVALID_ALARM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* uninitialized data?
|
||||
*/
|
||||
if (!caenV265Info[pvmeio->card].chan[pvmeio->signal][adc_12].newData) {
|
||||
recGblSetSevr(pai, READ_ALARM, INVALID_ALARM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
value = caenV265Info[pvmeio->card].chan[pvmeio->signal][adc_12].signal;
|
||||
pai->rval = value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265SpecialLinconv()
|
||||
*/
|
||||
LOCAL long caenV265SpecialLinconv(struct aiRecord *pai, int after)
|
||||
{
|
||||
if(!after) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set linear conversion slope*/
|
||||
pai->eslo = (pai->eguf-pai->egul)/FD_DATA_M;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265GetIoIntInfo()
|
||||
*/
|
||||
LOCAL long caenV265GetIoIntInfo(
|
||||
int cmd,
|
||||
struct aiRecord *pai,
|
||||
IOSCANPVT *ppvt)
|
||||
{
|
||||
struct vmeio *pvmeio;
|
||||
|
||||
pvmeio = (struct vmeio *)&(pai->inp.value);
|
||||
|
||||
/*
|
||||
* check for bad card number
|
||||
*/
|
||||
if ( pvmeio->card >= CAIN_V265_MAX_CARD_COUNT ) {
|
||||
logMsg(
|
||||
"%s.%d:devCaenV265 bad card number %d %s\n",
|
||||
(int)__FILE__,
|
||||
__LINE__,
|
||||
pvmeio->card,
|
||||
(int)pai->name,0,0);
|
||||
recGblRecordError(
|
||||
S_db_badField,
|
||||
(void *)pai,
|
||||
"devCaenV265 bad card number");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*ppvt = &caenV265Info[pvmeio->card].scanpvt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265Init()
|
||||
*/
|
||||
LOCAL long caenV265Init(void)
|
||||
{
|
||||
unsigned card;
|
||||
struct caenV265 *pCaenV265;
|
||||
int status;
|
||||
|
||||
status = rebootHookAdd(caenV265Shutdown);
|
||||
if(status){
|
||||
errMessage(S_dev_internal,"reboot hook add failed");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
status = sysBusToLocalAdrs(
|
||||
VME_AM_STD_SUP_DATA,
|
||||
CAIN_V265_A24_BASE,
|
||||
(char **)&pCaenV265);
|
||||
if(status!=OK){
|
||||
errPrintf(
|
||||
S_dev_badA24,
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
"caenV265Init");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
for(card=0; card<CAIN_V265_MAX_CARD_COUNT; card++, pCaenV265++){
|
||||
unsigned vec;
|
||||
|
||||
if(!caenV265IdTest(pCaenV265)){
|
||||
continue;
|
||||
}
|
||||
|
||||
caenV265Info[card].wdid = wdCreate();
|
||||
if(!caenV265Info[card].wdid){
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* flag that we have found a caen V265
|
||||
*/
|
||||
caenV265Info[card].pCaenV265 = pCaenV265;
|
||||
|
||||
/*
|
||||
* init the EPICS db int event scan block
|
||||
*/
|
||||
scanIoInit(&caenV265Info[card].scanpvt);
|
||||
|
||||
/*
|
||||
* reset the device
|
||||
*/
|
||||
pCaenV265->clear = 0; /* any rw op resets the device */
|
||||
pCaenV265->DAC = 0; /* set test-signal "offset" to zero */
|
||||
|
||||
/*
|
||||
* attach ISR
|
||||
*/
|
||||
vec = CAIN_V265_INTVEC_BASE+card;
|
||||
status = intConnect(
|
||||
INUM_TO_IVEC(vec),
|
||||
caenV265ISR,
|
||||
card);
|
||||
assert(status>=0);
|
||||
|
||||
/*
|
||||
* Enable interrupts
|
||||
*/
|
||||
caenV265IntEnable(card);
|
||||
}
|
||||
status = sysIntEnable(CAIN_V265_INT_LEVEL);
|
||||
assert(status>=0);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265ISR()
|
||||
*/
|
||||
LOCAL void caenV265ISR(unsigned card)
|
||||
{
|
||||
struct caenV265Config *pCaenV256Config = &caenV265Info[card];
|
||||
struct caenV265 *pCaenV265 = pCaenV256Config->pCaenV265;
|
||||
unsigned signal;
|
||||
int16_t csr;
|
||||
static unsigned ticks;
|
||||
unsigned newTicks;
|
||||
|
||||
/*
|
||||
* If its full then its more efficient
|
||||
* to read it out without checking
|
||||
* in between each read
|
||||
*/
|
||||
csr = pCaenV265->csr;
|
||||
if (EXTRACT(FULL,csr)) {
|
||||
for( signal=0;
|
||||
signal<NUMBER_OF_FIFO_ENTRIES;
|
||||
signal++){
|
||||
|
||||
caenV265ReadData(pCaenV256Config);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Not full so check to see if its ready before
|
||||
* reading
|
||||
*/
|
||||
while (EXTRACT(READY, csr)) {
|
||||
caenV265ReadData(pCaenV256Config);
|
||||
csr = pCaenV265->csr;
|
||||
}
|
||||
|
||||
/*
|
||||
* limit the EPICS scan rate
|
||||
*/
|
||||
newTicks = tickGet();
|
||||
if(newTicks == ticks){
|
||||
/*
|
||||
* Disable Interrupts
|
||||
*/
|
||||
pCaenV265->csr = 0;
|
||||
|
||||
/*
|
||||
* start a watch dog after one tick
|
||||
* so that we limit the int rate to
|
||||
* the system tick rate.
|
||||
*/
|
||||
wdStart(pCaenV256Config->wdid,
|
||||
1,
|
||||
caenV265IntEnable,
|
||||
card);
|
||||
|
||||
return;
|
||||
}
|
||||
else{
|
||||
ticks = newTicks;
|
||||
}
|
||||
|
||||
/*
|
||||
* tell EPICS to scan on int
|
||||
*/
|
||||
scanIoRequest(&caenV265Info[card].scanpvt);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265IntEnable
|
||||
*/
|
||||
LOCAL int caenV265IntEnable(unsigned card)
|
||||
{
|
||||
struct caenV265Config *pCaenV256Config = &caenV265Info[card];
|
||||
struct caenV265 *pCaenV265 = pCaenV256Config->pCaenV265;
|
||||
unsigned vec;
|
||||
int16_t newcsr;
|
||||
|
||||
|
||||
vec = CAIN_V265_INTVEC_BASE+card;
|
||||
newcsr = INSERT(IVEC, vec) | INSERT(ILEVEL, CAIN_V265_INT_LEVEL);
|
||||
pCaenV265->csr = newcsr;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265ReadData()
|
||||
*/
|
||||
LOCAL void caenV265ReadData(struct caenV265Config *pCaenV256Config)
|
||||
{
|
||||
struct caenV265 *pCaenV265 = pCaenV256Config->pCaenV265;
|
||||
int16_t val = pCaenV265->data;
|
||||
int16_t data = EXTRACT(DATA, val);
|
||||
unsigned range = EXTRACT(RANGE, val);
|
||||
unsigned signal = EXTRACT(CHANNEL, val);
|
||||
|
||||
if(range>=NUMBER_OF_ADC_RANGES){
|
||||
logMsg("caenV265ReadData: bad range number\n",0,0,0,0,0,0);
|
||||
return;
|
||||
}
|
||||
if(signal>=NUMBER_OF_SIGNALS){
|
||||
logMsg("caenV265ReadData: bad signal number\n",0,0,0,0,0,0);
|
||||
return;
|
||||
}
|
||||
pCaenV256Config->chan[signal][range].signal=data;
|
||||
pCaenV256Config->chan[signal][range].newData=TRUE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265IdTest()
|
||||
*/
|
||||
LOCAL int caenV265IdTest(struct caenV265 *pCaenV265)
|
||||
{
|
||||
int status;
|
||||
int16_t id;
|
||||
|
||||
/*
|
||||
* Is a card present
|
||||
*/
|
||||
status = vxMemProbe(
|
||||
(char *)&pCaenV265->identifier,
|
||||
READ,
|
||||
sizeof(id),
|
||||
(char *)&id);
|
||||
if(status!=OK){
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is the correct type of card present
|
||||
*/
|
||||
if(id!=CAENV265ID){
|
||||
errPrintf(
|
||||
S_dev_wrongDevice,
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
"caenV265IdTest");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265Shutdown()
|
||||
* turns off interrupts so that dont foul up the boot
|
||||
*/
|
||||
LOCAL int caenV265Shutdown(void)
|
||||
{
|
||||
struct caenV265 *pCaenV265;
|
||||
unsigned card;
|
||||
|
||||
for(card=0; card<CAIN_V265_MAX_CARD_COUNT; card++){
|
||||
pCaenV265 = caenV265Info[card].pCaenV265;
|
||||
if(!pCaenV265){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(caenV265IdTest(pCaenV265)){
|
||||
/*
|
||||
* disable interrupts
|
||||
*/
|
||||
pCaenV265->csr=0;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265Test()
|
||||
*/
|
||||
int caenV265Test(unsigned card)
|
||||
{
|
||||
unsigned dacVal;
|
||||
struct caenV265Config cofigCpy;
|
||||
unsigned range;
|
||||
unsigned signal;
|
||||
|
||||
|
||||
dacVal=0;
|
||||
caenV265TestVal(card, dacVal);
|
||||
while(dacVal<FD_DATA_M){
|
||||
|
||||
cofigCpy = caenV265Info[card];
|
||||
dacVal = dacVal+32;
|
||||
caenV265TestVal(card, dacVal);
|
||||
|
||||
for( range=0;
|
||||
range<NUMBER_OF_ADC_RANGES;
|
||||
range++){
|
||||
char *pRangeName[] = { "12 bit signal",
|
||||
"15 bit signal"};
|
||||
|
||||
printf( "\t%s with DAC = 0x%X\n",
|
||||
pRangeName[range],
|
||||
dacVal);
|
||||
|
||||
for( signal=0;
|
||||
signal<NUMBER_OF_SIGNALS;
|
||||
signal++){
|
||||
unsigned newdata;
|
||||
unsigned olddata;
|
||||
|
||||
olddata = cofigCpy.chan[signal][range].signal;
|
||||
newdata = caenV265Info[card].
|
||||
chan[signal][range].signal;
|
||||
|
||||
printf( "\t\tchan=0x%1X diff = 0x%03X\n",
|
||||
signal,
|
||||
newdata-olddata);
|
||||
}
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265TestVal()
|
||||
*/
|
||||
LOCAL int caenV265TestVal(unsigned card, unsigned dacVal)
|
||||
{
|
||||
struct caenV265Config *pCaenV256Config = &caenV265Info[card];
|
||||
struct caenV265 *pCaenV265 = pCaenV256Config->pCaenV265;
|
||||
unsigned signal;
|
||||
|
||||
if(!pCaenV265){
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if(!caenV265IdTest(pCaenV265)){
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* clear the module
|
||||
*/
|
||||
pCaenV265->clear=0;
|
||||
|
||||
/*
|
||||
* generate a test signal
|
||||
*/
|
||||
pCaenV265->DAC=dacVal;
|
||||
|
||||
/*
|
||||
* generate a test gate
|
||||
*/
|
||||
for( signal=0;
|
||||
signal<NUMBER_OF_SIGNALS;
|
||||
signal++){
|
||||
caenV265Info[card].chan[signal][adc_12].newData=FALSE;
|
||||
caenV265Info[card].chan[signal][adc_15].newData=FALSE;
|
||||
while(!caenV265Info[card].chan[signal][adc_15].newData){
|
||||
pCaenV265->gate=0;
|
||||
taskDelay(1);
|
||||
}
|
||||
while(!caenV265Info[card].chan[signal][adc_12].newData){
|
||||
pCaenV265->gate=0;
|
||||
taskDelay(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* turn off test signal
|
||||
*/
|
||||
pCaenV265->clear=0;
|
||||
pCaenV265->DAC=0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caenV265IOReport()
|
||||
*/
|
||||
LOCAL long caenV265IOReport(int level)
|
||||
{
|
||||
struct caenV265 *pCaenV265;
|
||||
unsigned card;
|
||||
unsigned signal;
|
||||
unsigned range;
|
||||
char *pVersion[] = {"NIM","ECL"};
|
||||
char *pState[] = {
|
||||
"FIFO empty",
|
||||
"FIFO full",
|
||||
"FIFO partially filled",
|
||||
"FIFO full"};
|
||||
|
||||
for (card=0; card<CAIN_V265_MAX_CARD_COUNT; card++) {
|
||||
pCaenV265 = caenV265Info[card].pCaenV265;
|
||||
if (!pCaenV265) {
|
||||
continue;
|
||||
}
|
||||
if (!caenV265IdTest(pCaenV265)) {
|
||||
continue;
|
||||
}
|
||||
printf("AI: caen V265:\tcard %d\n", card);
|
||||
if (level == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("\tversion = %s\n",
|
||||
pVersion[EXTRACT(VERSION, pCaenV265->version)]);
|
||||
printf("\tseries = %d\n",
|
||||
EXTRACT(SERIES, pCaenV265->version));
|
||||
printf("\tstate = %s\n",
|
||||
pState[EXTRACT(BUSY_FULL,pCaenV265->csr)]);
|
||||
printf("\tint level = %d\n",
|
||||
EXTRACT(ILEVEL,pCaenV265->csr));
|
||||
printf("\tint vec = 0x%02X\n",
|
||||
EXTRACT(IVEC,pCaenV265->csr));
|
||||
printf( "\tbase addr= 0x%X on the %s\n",
|
||||
(unsigned)caenV265Info[card].pCaenV265,
|
||||
sysModel());
|
||||
|
||||
for( range=0;
|
||||
range<NUMBER_OF_ADC_RANGES;
|
||||
range++){
|
||||
char *pRangeName[] = { "12 bit signal",
|
||||
"15 bit signal"};
|
||||
|
||||
printf("\t%s\n", pRangeName[range]);
|
||||
|
||||
for( signal=0;
|
||||
signal<NUMBER_OF_SIGNALS;
|
||||
signal++){
|
||||
int16_t data;
|
||||
|
||||
data = caenV265Info[card].
|
||||
chan[signal][range].signal;
|
||||
|
||||
if(caenV265Info[card].chan[signal][range].newData){
|
||||
printf( "\t\tchan=0x%1X val = 0x%03X\n",
|
||||
signal,
|
||||
data);
|
||||
}
|
||||
else{
|
||||
printf( "\t\tchan=0x%1X <NO GATE>\n",
|
||||
signal);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
@@ -22,10 +22,12 @@ PROD = iocCore vxWorks vxWorks.sym
|
||||
include $(EPICS)/config/RULES.Vx
|
||||
|
||||
vxWorks: $(VX_IMAGE)
|
||||
@$(INSTALL) -m 444 $? $@
|
||||
cp $< .
|
||||
chmod 444 $@
|
||||
|
||||
vxWorks.sym: $(VX_IMAGE_SYM)
|
||||
@$(INSTALL) -m 444 $? $@
|
||||
cp $< .
|
||||
chmod 444 $@
|
||||
|
||||
iocCore: $(IOC_CORE_OBJS)
|
||||
$(LINK.c) $@ $(IOC_CORE_OBJS)
|
||||
|
||||
@@ -15,7 +15,7 @@ SRCS.c = \
|
||||
OBJS = \
|
||||
calcPerform.o cvtBpt.o cvtFast.o ellLib.o envSubr.o errSymLib.o \
|
||||
errSymTbl.o genSubr.o genTaskSubr.o nextFieldSubr.o postfix.o \
|
||||
bucketLib.o tsSubr.o gpHashLib.o freeListLib.o pal.o paldef.o
|
||||
bucketLib.o tsSubr.o gpHashLib.o freeListLib.o pal.o paldef.o
|
||||
|
||||
OBJS1 = \
|
||||
cmdSubr.o cvtNumbers.o cvtFast.o ezsSockSubr.o helpSubr.o
|
||||
|
||||
@@ -29,12 +29,16 @@
|
||||
* -----------------
|
||||
* .01 091493 joh fixed overzealous parameter check
|
||||
* .02 121693 joh added bucketFree()
|
||||
*
|
||||
* NOTES:
|
||||
* .01 Storage for identifier must persist until an item is deleted
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <bucketLib.h>
|
||||
|
||||
@@ -48,142 +52,319 @@
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif /* FALSE */
|
||||
#ifndef LOCAL
|
||||
#define LOCAL static
|
||||
#endif /* LOCAL */
|
||||
#ifndef max
|
||||
#define max(A,B) ((A)>(B)?(A):(B))
|
||||
#endif /* max */
|
||||
|
||||
#define BUCKET_IX_WIDTH 12
|
||||
#define BUCKET_IX_N (1<<BUCKET_IX_WIDTH)
|
||||
#define BUCKET_IX_MASK (BUCKET_IX_N-1)
|
||||
/*
|
||||
* these data type dependent routines are
|
||||
* provided in the bucketLib.c
|
||||
*/
|
||||
typedef BUCKETID bucketHash(BUCKET *pb, const void *pId);
|
||||
typedef ITEM **bucketCompare(ITEM **ppi, const void *pId);
|
||||
|
||||
LOCAL bucketCompare bucketUnsignedCompare;
|
||||
LOCAL bucketCompare bucketPointerCompare;
|
||||
LOCAL bucketCompare bucketStringCompare;
|
||||
LOCAL bucketHash bucketUnsignedHash;
|
||||
LOCAL bucketHash bucketPointerHash;
|
||||
LOCAL bucketHash bucketStringHash;
|
||||
|
||||
typedef struct {
|
||||
bucketHash *pHash;
|
||||
bucketCompare *pCompare;
|
||||
buckTypeOfId type;
|
||||
}bucketSET;
|
||||
|
||||
LOCAL bucketSET BSET[] = {
|
||||
{bucketUnsignedHash, bucketUnsignedCompare, bidtUnsigned},
|
||||
{bucketPointerHash, bucketPointerCompare, bidtPointer},
|
||||
{bucketStringHash, bucketStringCompare, bidtString}
|
||||
};
|
||||
|
||||
LOCAL int bucketAddItem(BUCKET *prb, bucketSET *pBSET, const void *pId, void *pApp);
|
||||
LOCAL int bucketRemoveItem (BUCKET *prb, bucketSET *pBSET, const void *pId);
|
||||
LOCAL void *bucketLookupItem(BUCKET *pb, bucketSET *pBSET, const void *pId);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* bucket id bit width
|
||||
*/
|
||||
#define BUCKETID_BIT_WIDTH (sizeof(BUCKETID)*NBBY)
|
||||
|
||||
/*
|
||||
* Maximum bucket size
|
||||
*/
|
||||
#define BUCKET_MAX_WIDTH 12
|
||||
|
||||
#ifdef DEBUG
|
||||
#error This is out of date
|
||||
main()
|
||||
{
|
||||
BUCKETID id;
|
||||
BUCKETID id1;
|
||||
BUCKETID id2;
|
||||
char *pValSave1;
|
||||
char *pValSave2;
|
||||
int s;
|
||||
BUCKET *pb;
|
||||
char *pValSave;
|
||||
char *pVal;
|
||||
unsigned i;
|
||||
clock_t start, finish;
|
||||
double duration;
|
||||
const int LOOPS = 500000;
|
||||
|
||||
pb = bucketCreate(NBBY*sizeof(BUCKETID));
|
||||
pb = bucketCreate(8);
|
||||
if(!pb){
|
||||
return BUCKET_FAILURE;
|
||||
}
|
||||
|
||||
id = 444;
|
||||
pValSave = "fred";
|
||||
s = bucketAddItem(pb, id, pValSave);
|
||||
if(s != BUCKET_SUCCESS){
|
||||
return BUCKET_FAILURE;
|
||||
}
|
||||
id1 = 0x1000a432;
|
||||
pValSave1 = "fred";
|
||||
s = bucketAddItemUnsignedId(pb, &id1, pValSave1);
|
||||
assert(s == BUCKET_SUCCESS);
|
||||
|
||||
printf("Begin\n");
|
||||
for(i=0; i<500000; i++){
|
||||
pVal = bucketLookupItem(pb, id);
|
||||
if(pVal != pValSave){
|
||||
printf("failure\n");
|
||||
break;
|
||||
}
|
||||
pVal = bucketLookupItem(pb, id);
|
||||
if(pVal != pValSave){
|
||||
printf("failure\n");
|
||||
break;
|
||||
}
|
||||
pVal = bucketLookupItem(pb, id);
|
||||
if(pVal != pValSave){
|
||||
printf("failure\n");
|
||||
break;
|
||||
}
|
||||
pVal = bucketLookupItem(pb, id);
|
||||
if(pVal != pValSave){
|
||||
printf("failure\n");
|
||||
break;
|
||||
}
|
||||
pVal = bucketLookupItem(pb, id);
|
||||
if(pVal != pValSave){
|
||||
printf("failure\n");
|
||||
break;
|
||||
}
|
||||
pVal = bucketLookupItem(pb, id);
|
||||
if(pVal != pValSave){
|
||||
printf("failure\n");
|
||||
break;
|
||||
}
|
||||
pVal = bucketLookupItem(pb, id);
|
||||
if(pVal != pValSave){
|
||||
printf("failure\n");
|
||||
break;
|
||||
}
|
||||
pVal = bucketLookupItem(pb, id);
|
||||
if(pVal != pValSave){
|
||||
printf("failure\n");
|
||||
break;
|
||||
}
|
||||
pVal = bucketLookupItem(pb, id);
|
||||
if(pVal != pValSave){
|
||||
printf("failure\n");
|
||||
break;
|
||||
}
|
||||
pVal = bucketLookupItem(pb, id);
|
||||
if(pVal != pValSave){
|
||||
printf("failure\n");
|
||||
break;
|
||||
}
|
||||
pValSave2 = "jane";
|
||||
s = bucketAddItemStringId(pb, pValSave2, pValSave2);
|
||||
assert(s == BUCKET_SUCCESS);
|
||||
|
||||
start = clock();
|
||||
for(i=0; i<LOOPS; i++){
|
||||
pVal = bucketLookupItem(pb, id1);
|
||||
assert(pVal == pValSave1);
|
||||
pVal = bucketLookupItem(pb, id1);
|
||||
assert(pVal == pValSave1);
|
||||
pVal = bucketLookupItem(pb, id1);
|
||||
assert(pVal == pValSave1);
|
||||
pVal = bucketLookupItem(pb, id1);
|
||||
assert(pVal == pValSave1);
|
||||
pVal = bucketLookupItem(pb, id1);
|
||||
assert(pVal == pValSave1);
|
||||
pVal = bucketLookupItem(pb, id1);
|
||||
assert(pVal == pValSave1);
|
||||
pVal = bucketLookupItem(pb, id1);
|
||||
assert(pVal == pValSave1);
|
||||
pVal = bucketLookupItem(pb, id1);
|
||||
assert(pVal == pValSave1);
|
||||
pVal = bucketLookupItem(pb, id1);
|
||||
assert(pVal == pValSave1);
|
||||
pVal = bucketLookupItem(pb, id2);
|
||||
assert(pVal == pValSave2);
|
||||
}
|
||||
printf("End\n");
|
||||
finish = clock();
|
||||
|
||||
duration = finish-start;
|
||||
duration = duration/CLOCKS_PER_SEC;
|
||||
printf("It took %15.10f total sec\n", duration);
|
||||
duration = duration/LOOPS;
|
||||
duration = duration/10;
|
||||
duration = duration * 1e6;
|
||||
printf("It took %15.10f u sec per hash lookup\n", duration);
|
||||
|
||||
bucketShow(pb);
|
||||
|
||||
return BUCKET_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* bucketUnsignedCompare()
|
||||
*/
|
||||
LOCAL ITEM **bucketUnsignedCompare (ITEM **ppi, const void *pId)
|
||||
{
|
||||
unsigned id;
|
||||
unsigned *pItemId;
|
||||
ITEM *pi;
|
||||
|
||||
id = * (unsigned *) pId;
|
||||
while (pi = *ppi) {
|
||||
if (bidtUnsigned == pi->type) {
|
||||
pItemId = (unsigned *) pi->pId;
|
||||
if (id == *pItemId) {
|
||||
return ppi;
|
||||
}
|
||||
}
|
||||
ppi = &pi->pItem;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* bucketPointerCompare()
|
||||
*/
|
||||
ITEM **bucketPointerCompare (ITEM **ppi, const void *pId)
|
||||
{
|
||||
void *ptr;
|
||||
void **pItemId;
|
||||
ITEM *pi;
|
||||
|
||||
ptr = * (void **) pId;
|
||||
while (pi = *ppi) {
|
||||
if (bidtPointer == pi->type ) {
|
||||
pItemId = (void **) pi->pId;
|
||||
if (ptr == *pItemId) {
|
||||
return ppi;
|
||||
}
|
||||
}
|
||||
ppi = &pi->pItem;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* bucketStringCompare ()
|
||||
*/
|
||||
ITEM **bucketStringCompare (ITEM **ppi, const void *pId)
|
||||
{
|
||||
const char *pStr = pId;
|
||||
ITEM *pi;
|
||||
int status;
|
||||
|
||||
while (pi = *ppi) {
|
||||
if (bidtString == pi->type) {
|
||||
status = strcmp (pStr, (char *)pi->pId);
|
||||
if (status == '\0') {
|
||||
return ppi;
|
||||
}
|
||||
}
|
||||
ppi = &pi->pItem;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* bucketUnsignedHash ()
|
||||
*/
|
||||
BUCKETID bucketUnsignedHash (BUCKET *pb, const void *pId)
|
||||
{
|
||||
const unsigned *pUId = pId;
|
||||
unsigned src;
|
||||
BUCKETID hashid;
|
||||
|
||||
src = *pUId;
|
||||
hashid = src;
|
||||
src = src >> pb->hashIdNBits;
|
||||
while (src) {
|
||||
hashid = hashid ^ src;
|
||||
src = src >> pb->hashIdNBits;
|
||||
}
|
||||
hashid = hashid & pb->hashIdMask;
|
||||
|
||||
return hashid;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* bucketPointerHash ()
|
||||
*
|
||||
*/
|
||||
BUCKETID bucketPointerHash (BUCKET *pb, const void *pId)
|
||||
{
|
||||
void * const *ppId = pId;
|
||||
unsigned long src;
|
||||
BUCKETID hashid;
|
||||
|
||||
/*
|
||||
* This makes the assumption that
|
||||
* a pointer will fit inside of a long
|
||||
* (this assumption may not port to all
|
||||
* CPU architectures)
|
||||
*/
|
||||
src = (unsigned long) *ppId;
|
||||
hashid = src;
|
||||
src = src >> pb->hashIdNBits;
|
||||
while(src){
|
||||
hashid = hashid ^ src;
|
||||
src = src >> pb->hashIdNBits;
|
||||
}
|
||||
hashid = hashid & pb->hashIdMask;
|
||||
|
||||
return hashid;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* bucketStringHash ()
|
||||
*/
|
||||
BUCKETID bucketStringHash (BUCKET *pb, const void *pId)
|
||||
{
|
||||
const char *pStr = pId;
|
||||
BUCKETID hashid;
|
||||
unsigned i;
|
||||
|
||||
hashid = 0;
|
||||
i = 1;
|
||||
while(*pStr){
|
||||
hashid += *pStr * i;
|
||||
pStr++;
|
||||
i++;
|
||||
}
|
||||
|
||||
hashid = hashid % (pb->hashIdMask+1);
|
||||
|
||||
return hashid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* bucketCreate()
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
BUCKET *bucketCreate(unsigned indexWidth)
|
||||
#else
|
||||
BUCKET *bucketCreate(indexWidth)
|
||||
unsigned indexWidth;
|
||||
#endif
|
||||
BUCKET *bucketCreate (unsigned nHashTableEntries)
|
||||
{
|
||||
BUCKETID mask;
|
||||
unsigned nbits;
|
||||
BUCKET *pb;
|
||||
|
||||
/*
|
||||
* no absurd sized buckets
|
||||
*/
|
||||
if (nHashTableEntries<=1) {
|
||||
fprintf (stderr, "Tiny bucket create failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* count the number of bits in the bucket id
|
||||
*/
|
||||
for (nbits=0; nbits<BUCKETID_BIT_WIDTH; nbits++) {
|
||||
mask = (1<<nbits) - 1;
|
||||
if ( ((nHashTableEntries-1) & ~mask) == 0){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* indexWidth must be specified at least one
|
||||
* bit less than the bit size of type BUCKETID
|
||||
*/
|
||||
if(indexWidth>sizeof(BUCKETID)*NBBY){
|
||||
printf("%s at %d: Requested index width=%d is to large. max=%d\n" ,
|
||||
if (nbits>=BUCKETID_BIT_WIDTH) {
|
||||
fprintf (
|
||||
stderr,
|
||||
"%s at %d: Requested index width=%d to large. max=%d\n",
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
indexWidth,
|
||||
sizeof(BUCKETID)*NBBY-1);
|
||||
nbits,
|
||||
BUCKETID_BIT_WIDTH-1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pb = (BUCKET *) calloc(1, sizeof(*pb));
|
||||
if(!pb){
|
||||
if (!pb) {
|
||||
return pb;
|
||||
}
|
||||
|
||||
if(indexWidth>BUCKET_IX_WIDTH){
|
||||
pb->indexShift = indexWidth - BUCKET_IX_WIDTH;
|
||||
}
|
||||
else{
|
||||
pb->indexShift = 0;
|
||||
}
|
||||
pb->nextIndexMask = (1<<pb->indexShift)-1;
|
||||
pb->nEntries = 1<<(indexWidth-pb->indexShift);
|
||||
if(indexWidth == sizeof(BUCKETID)*NBBY){
|
||||
pb->indexMask = 0;
|
||||
pb->indexMask = ~pb->indexMask;
|
||||
}
|
||||
else{
|
||||
pb->indexMask = (1<<indexWidth)-1;
|
||||
}
|
||||
pb->hashIdMask = mask;
|
||||
pb->hashIdNBits = nbits;
|
||||
|
||||
pb->pTable = (ITEMPTR *) calloc(
|
||||
pb->nEntries,
|
||||
sizeof(ITEMPTR));
|
||||
pb->pTable = (ITEM **) calloc (mask+1, sizeof(*pb->pTable));
|
||||
if(!pb->pTable){
|
||||
free(pb);
|
||||
return NULL;
|
||||
@@ -202,14 +383,24 @@ int bucketFree(prb)
|
||||
BUCKET *prb;
|
||||
#endif
|
||||
{
|
||||
ITEM *pi;
|
||||
ITEM *pni;
|
||||
|
||||
/*
|
||||
* deleting a bucket with entries in use
|
||||
* will cause memory leaks and is not allowed
|
||||
*/
|
||||
if(prb->nInUse){
|
||||
return BUCKET_FAILURE;
|
||||
}
|
||||
assert(prb->nInUse==0);
|
||||
|
||||
/*
|
||||
* free the free list
|
||||
*/
|
||||
pi = prb->pFreeItems;
|
||||
while (pi) {
|
||||
pni = pi->pItem;
|
||||
free (pi);
|
||||
pi = pni;
|
||||
}
|
||||
free(prb->pTable);
|
||||
free(prb);
|
||||
|
||||
@@ -220,69 +411,49 @@ BUCKET *prb;
|
||||
/*
|
||||
* bucketAddItem()
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
int bucketAddItem(BUCKET *prb, BUCKETID id, void *pItem)
|
||||
#else
|
||||
int bucketAddItem(prb, id, pItem)
|
||||
BUCKET *prb;
|
||||
BUCKETID id;
|
||||
void *pItem;
|
||||
#endif
|
||||
int bucketAddItemUnsignedId(BUCKET *prb, const unsigned *pId, void *pApp)
|
||||
{
|
||||
int s;
|
||||
ITEMPTR *pi;
|
||||
return bucketAddItem(prb, &BSET[bidtUnsigned], pId, pApp);
|
||||
}
|
||||
int bucketAddItemPointerId(BUCKET *prb, void * const *pId, void *pApp)
|
||||
{
|
||||
return bucketAddItem(prb, &BSET[bidtPointer], pId, pApp);
|
||||
}
|
||||
int bucketAddItemStringId(BUCKET *prb, const char *pId, void *pApp)
|
||||
{
|
||||
return bucketAddItem(prb, &BSET[bidtString], pId, pApp);
|
||||
}
|
||||
LOCAL int bucketAddItem(BUCKET *prb, bucketSET *pBSET, const void *pId, void *pApp)
|
||||
{
|
||||
BUCKETID hashid;
|
||||
ITEM *pi;
|
||||
|
||||
/*
|
||||
* is the id to big ?
|
||||
* try to get it off the free list first. If
|
||||
* that fails then malloc()
|
||||
*/
|
||||
if(id&~prb->indexMask){
|
||||
return BUCKET_FAILURE;
|
||||
pi = prb->pFreeItems;
|
||||
if (pi) {
|
||||
prb->pFreeItems = pi->pItem;
|
||||
}
|
||||
|
||||
if(prb->indexShift){
|
||||
int new;
|
||||
BUCKET *pb;
|
||||
|
||||
pi = &prb->pTable[id>>prb->indexShift];
|
||||
pb = pi->pBucket;
|
||||
|
||||
if(!pb){
|
||||
pb = bucketCreate(prb->indexShift);
|
||||
if(!pb){
|
||||
return BUCKET_FAILURE;
|
||||
}
|
||||
pi->pBucket = pb;
|
||||
prb->nInUse++;
|
||||
new = TRUE;
|
||||
}
|
||||
else{
|
||||
new = FALSE;
|
||||
else {
|
||||
pi = (ITEM *) malloc(sizeof(ITEM));
|
||||
if(!pi){
|
||||
return BUCKET_FAILURE;
|
||||
}
|
||||
|
||||
s = bucketAddItem(
|
||||
pb,
|
||||
id&prb->nextIndexMask,
|
||||
pItem);
|
||||
/*
|
||||
* if memory cant be allocated at a lower
|
||||
* level dont leak everything allocated for this new
|
||||
* item so far
|
||||
*/
|
||||
if(s != BUCKET_SUCCESS && new){
|
||||
s = bucketFree(pb);
|
||||
assert(s == BUCKET_SUCCESS);
|
||||
pi->pBucket = NULL;
|
||||
prb->nInUse--;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
pi = &prb->pTable[id];
|
||||
if(pi->pItem){
|
||||
return BUCKET_FAILURE;
|
||||
}
|
||||
|
||||
pi->pItem = pItem;
|
||||
/*
|
||||
* create the hash index
|
||||
*/
|
||||
hashid = (*pBSET->pHash) (prb, pId);
|
||||
|
||||
pi->pApp = pApp;
|
||||
pi->pId = pId;
|
||||
pi->type = pBSET->type;
|
||||
assert((hashid & ~prb->hashIdMask) == 0);
|
||||
pi->pItem = prb->pTable[hashid];
|
||||
prb->pTable[hashid] = pi;
|
||||
prb->nInUse++;
|
||||
|
||||
return BUCKET_SUCCESS;
|
||||
@@ -292,97 +463,85 @@ void *pItem;
|
||||
/*
|
||||
* bucketRemoveItem()
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
int bucketRemoveItem (BUCKET *prb, BUCKETID id, void *pItem)
|
||||
#else
|
||||
int bucketRemoveItem (prb, id, pItem)
|
||||
BUCKET *prb;
|
||||
BUCKETID id;
|
||||
void *pItem;
|
||||
#endif
|
||||
int bucketRemoveItemUnsignedId (BUCKET *prb, const unsigned *pId)
|
||||
{
|
||||
ITEMPTR *ppi;
|
||||
return bucketRemoveItem(prb, &BSET[bidtUnsigned], pId);
|
||||
}
|
||||
int bucketRemoveItemPointerId (BUCKET *prb, void * const *pId)
|
||||
{
|
||||
return bucketRemoveItem(prb, &BSET[bidtPointer], pId);
|
||||
}
|
||||
int bucketRemoveItemStringId (BUCKET *prb, const char *pId)
|
||||
{
|
||||
return bucketRemoveItem(prb, &BSET[bidtString], pId);
|
||||
}
|
||||
LOCAL int bucketRemoveItem (BUCKET *prb, bucketSET *pBSET, const void *pId)
|
||||
{
|
||||
BUCKETID hashid;
|
||||
ITEM **ppi;
|
||||
ITEM *pi;
|
||||
|
||||
/*
|
||||
* is the id to big ?
|
||||
* create the hash index
|
||||
*/
|
||||
if(id&~prb->indexMask){
|
||||
hashid = (*pBSET->pHash) (prb, pId);
|
||||
|
||||
assert((hashid & ~prb->hashIdMask) == 0);
|
||||
ppi = &prb->pTable[hashid];
|
||||
ppi = (*pBSET->pCompare) (ppi, pId);
|
||||
if(!ppi){
|
||||
return BUCKET_FAILURE;
|
||||
}
|
||||
|
||||
if(prb->indexShift){
|
||||
BUCKET *pb;
|
||||
int s;
|
||||
|
||||
ppi = &prb->pTable[id>>prb->indexShift];
|
||||
pb = ppi->pBucket;
|
||||
|
||||
if(!pb){
|
||||
return BUCKET_FAILURE;
|
||||
}
|
||||
|
||||
s = bucketRemoveItem(
|
||||
pb,
|
||||
id&prb->nextIndexMask,
|
||||
pItem);
|
||||
if(s!=BUCKET_SUCCESS){
|
||||
return s;
|
||||
}
|
||||
|
||||
if(pb->nInUse==0){
|
||||
free(pb->pTable);
|
||||
free(pb);
|
||||
ppi->pBucket = NULL;
|
||||
prb->nInUse--;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
ppi = &prb->pTable[id];
|
||||
if(ppi->pItem != pItem){
|
||||
return BUCKET_FAILURE;
|
||||
}
|
||||
|
||||
prb->nInUse--;
|
||||
ppi->pItem = NULL;
|
||||
pi = *ppi;
|
||||
*ppi = pi->pItem;
|
||||
|
||||
/*
|
||||
* stuff it on the free list
|
||||
*/
|
||||
pi->pItem = prb->pFreeItems;
|
||||
prb->pFreeItems = pi;
|
||||
|
||||
return BUCKET_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* bucketLookupItem()
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
void *bucketLookupItem(BUCKET *pb, BUCKETID id)
|
||||
#else
|
||||
void *bucketLookupItem(pb, id)
|
||||
BUCKET *pb;
|
||||
BUCKETID id;
|
||||
#endif
|
||||
void *bucketLookupItemUnsignedId (BUCKET *prb, const unsigned *pId)
|
||||
{
|
||||
unsigned shift;
|
||||
return bucketLookupItem(prb, &BSET[bidtUnsigned], pId);
|
||||
}
|
||||
void *bucketLookupItemPointerId (BUCKET *prb, void * const *pId)
|
||||
{
|
||||
return bucketLookupItem(prb, &BSET[bidtPointer], pId);
|
||||
}
|
||||
void *bucketLookupItemStringId (BUCKET *prb, const char *pId)
|
||||
{
|
||||
return bucketLookupItem(prb, &BSET[bidtString], pId);
|
||||
}
|
||||
LOCAL void *bucketLookupItem(BUCKET *pb, bucketSET *pBSET, const void *pId)
|
||||
{
|
||||
BUCKETID hashid;
|
||||
ITEM **ppi;
|
||||
|
||||
/*
|
||||
* is the id to big ?
|
||||
* create the hash index
|
||||
*/
|
||||
if(id&~pb->indexMask){
|
||||
return NULL;
|
||||
hashid = (*pBSET->pHash) (pb, pId);
|
||||
assert((hashid & ~pb->hashIdMask) == 0);
|
||||
|
||||
/*
|
||||
* at the bottom level just
|
||||
* linear search for it.
|
||||
*/
|
||||
ppi = (*pBSET->pCompare) (&pb->pTable[hashid], pId);
|
||||
if(ppi){
|
||||
return (*ppi)->pApp;
|
||||
}
|
||||
|
||||
while(shift = pb->indexShift){
|
||||
BUCKETID nextId;
|
||||
|
||||
nextId = id & pb->nextIndexMask;
|
||||
|
||||
pb = pb->pTable[id>>shift].pBucket;
|
||||
if(!pb){
|
||||
return pb;
|
||||
}
|
||||
id = nextId;
|
||||
}
|
||||
|
||||
return pb->pTable[id].pItem;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -397,24 +556,62 @@ int bucketShow(pb)
|
||||
BUCKET *pb;
|
||||
#endif
|
||||
{
|
||||
ITEMPTR *pi;
|
||||
ITEM **ppi;
|
||||
ITEM *pi;
|
||||
ITEM *pni;
|
||||
unsigned nElem;
|
||||
double X;
|
||||
double XX;
|
||||
double mean;
|
||||
double stdDev;
|
||||
unsigned count;
|
||||
unsigned maxEntries;
|
||||
unsigned freeListCount;
|
||||
|
||||
pi = pb->pTable;
|
||||
|
||||
printf( "Bucket: mask=%x entries in use=%d bytes in use=%d\n",
|
||||
(pb->nEntries-1)<<pb->indexShift,
|
||||
pb->nInUse,
|
||||
sizeof(*pb)+pb->nEntries*sizeof(*pi));
|
||||
|
||||
if(pb->indexShift){
|
||||
for( pi = pb->pTable;
|
||||
pi<&pb->pTable[pb->nEntries];
|
||||
pi++){
|
||||
if(pi->pBucket){
|
||||
bucketShow(pi->pBucket);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* count bytes on the free list
|
||||
*/
|
||||
pi = pb->pFreeItems;
|
||||
freeListCount = 0;
|
||||
while (pi) {
|
||||
freeListCount++;
|
||||
pni = pi->pItem;
|
||||
pi = pni;
|
||||
}
|
||||
|
||||
printf( "Bucket entries in use = %d bytes in use = %d\n",
|
||||
pb->nInUse,
|
||||
sizeof(*pb)+(pb->hashIdMask+1)*
|
||||
sizeof(ITEM *)+pb->nInUse*sizeof(ITEM));
|
||||
|
||||
printf( "Free list bytes in use = %d\n",
|
||||
freeListCount*sizeof(ITEM));
|
||||
|
||||
ppi = pb->pTable;
|
||||
nElem = pb->hashIdMask+1;
|
||||
X = 0.0;
|
||||
XX = 0.0;
|
||||
maxEntries = 0;
|
||||
while (ppi < &pb->pTable[nElem]) {
|
||||
pi = *ppi;
|
||||
count = 0;
|
||||
while (pi) {
|
||||
count++;
|
||||
pi = pi->pItem;
|
||||
}
|
||||
X += count;
|
||||
XX += count*count;
|
||||
maxEntries = max (count, maxEntries);
|
||||
ppi++;
|
||||
}
|
||||
|
||||
mean = X/nElem;
|
||||
stdDev = sqrt(XX/nElem - mean*mean);
|
||||
printf( "Bucket entries/hash id - mean = %f std dev = %f max = %d\n",
|
||||
mean,
|
||||
stdDev,
|
||||
maxEntries);
|
||||
|
||||
return BUCKET_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,12 +29,16 @@
|
||||
* -----------------
|
||||
* .01 091493 joh fixed overzealous parameter check
|
||||
* .02 121693 joh added bucketFree()
|
||||
*
|
||||
* NOTES:
|
||||
* .01 Storage for identifier must persist until an item is deleted
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <bucketLib.h>
|
||||
|
||||
@@ -48,142 +52,319 @@
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif /* FALSE */
|
||||
#ifndef LOCAL
|
||||
#define LOCAL static
|
||||
#endif /* LOCAL */
|
||||
#ifndef max
|
||||
#define max(A,B) ((A)>(B)?(A):(B))
|
||||
#endif /* max */
|
||||
|
||||
#define BUCKET_IX_WIDTH 12
|
||||
#define BUCKET_IX_N (1<<BUCKET_IX_WIDTH)
|
||||
#define BUCKET_IX_MASK (BUCKET_IX_N-1)
|
||||
/*
|
||||
* these data type dependent routines are
|
||||
* provided in the bucketLib.c
|
||||
*/
|
||||
typedef BUCKETID bucketHash(BUCKET *pb, const void *pId);
|
||||
typedef ITEM **bucketCompare(ITEM **ppi, const void *pId);
|
||||
|
||||
LOCAL bucketCompare bucketUnsignedCompare;
|
||||
LOCAL bucketCompare bucketPointerCompare;
|
||||
LOCAL bucketCompare bucketStringCompare;
|
||||
LOCAL bucketHash bucketUnsignedHash;
|
||||
LOCAL bucketHash bucketPointerHash;
|
||||
LOCAL bucketHash bucketStringHash;
|
||||
|
||||
typedef struct {
|
||||
bucketHash *pHash;
|
||||
bucketCompare *pCompare;
|
||||
buckTypeOfId type;
|
||||
}bucketSET;
|
||||
|
||||
LOCAL bucketSET BSET[] = {
|
||||
{bucketUnsignedHash, bucketUnsignedCompare, bidtUnsigned},
|
||||
{bucketPointerHash, bucketPointerCompare, bidtPointer},
|
||||
{bucketStringHash, bucketStringCompare, bidtString}
|
||||
};
|
||||
|
||||
LOCAL int bucketAddItem(BUCKET *prb, bucketSET *pBSET, const void *pId, void *pApp);
|
||||
LOCAL int bucketRemoveItem (BUCKET *prb, bucketSET *pBSET, const void *pId);
|
||||
LOCAL void *bucketLookupItem(BUCKET *pb, bucketSET *pBSET, const void *pId);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* bucket id bit width
|
||||
*/
|
||||
#define BUCKETID_BIT_WIDTH (sizeof(BUCKETID)*NBBY)
|
||||
|
||||
/*
|
||||
* Maximum bucket size
|
||||
*/
|
||||
#define BUCKET_MAX_WIDTH 12
|
||||
|
||||
#ifdef DEBUG
|
||||
#error This is out of date
|
||||
main()
|
||||
{
|
||||
BUCKETID id;
|
||||
BUCKETID id1;
|
||||
BUCKETID id2;
|
||||
char *pValSave1;
|
||||
char *pValSave2;
|
||||
int s;
|
||||
BUCKET *pb;
|
||||
char *pValSave;
|
||||
char *pVal;
|
||||
unsigned i;
|
||||
clock_t start, finish;
|
||||
double duration;
|
||||
const int LOOPS = 500000;
|
||||
|
||||
pb = bucketCreate(NBBY*sizeof(BUCKETID));
|
||||
pb = bucketCreate(8);
|
||||
if(!pb){
|
||||
return BUCKET_FAILURE;
|
||||
}
|
||||
|
||||
id = 444;
|
||||
pValSave = "fred";
|
||||
s = bucketAddItem(pb, id, pValSave);
|
||||
if(s != BUCKET_SUCCESS){
|
||||
return BUCKET_FAILURE;
|
||||
}
|
||||
id1 = 0x1000a432;
|
||||
pValSave1 = "fred";
|
||||
s = bucketAddItemUnsignedId(pb, &id1, pValSave1);
|
||||
assert(s == BUCKET_SUCCESS);
|
||||
|
||||
printf("Begin\n");
|
||||
for(i=0; i<500000; i++){
|
||||
pVal = bucketLookupItem(pb, id);
|
||||
if(pVal != pValSave){
|
||||
printf("failure\n");
|
||||
break;
|
||||
}
|
||||
pVal = bucketLookupItem(pb, id);
|
||||
if(pVal != pValSave){
|
||||
printf("failure\n");
|
||||
break;
|
||||
}
|
||||
pVal = bucketLookupItem(pb, id);
|
||||
if(pVal != pValSave){
|
||||
printf("failure\n");
|
||||
break;
|
||||
}
|
||||
pVal = bucketLookupItem(pb, id);
|
||||
if(pVal != pValSave){
|
||||
printf("failure\n");
|
||||
break;
|
||||
}
|
||||
pVal = bucketLookupItem(pb, id);
|
||||
if(pVal != pValSave){
|
||||
printf("failure\n");
|
||||
break;
|
||||
}
|
||||
pVal = bucketLookupItem(pb, id);
|
||||
if(pVal != pValSave){
|
||||
printf("failure\n");
|
||||
break;
|
||||
}
|
||||
pVal = bucketLookupItem(pb, id);
|
||||
if(pVal != pValSave){
|
||||
printf("failure\n");
|
||||
break;
|
||||
}
|
||||
pVal = bucketLookupItem(pb, id);
|
||||
if(pVal != pValSave){
|
||||
printf("failure\n");
|
||||
break;
|
||||
}
|
||||
pVal = bucketLookupItem(pb, id);
|
||||
if(pVal != pValSave){
|
||||
printf("failure\n");
|
||||
break;
|
||||
}
|
||||
pVal = bucketLookupItem(pb, id);
|
||||
if(pVal != pValSave){
|
||||
printf("failure\n");
|
||||
break;
|
||||
}
|
||||
pValSave2 = "jane";
|
||||
s = bucketAddItemStringId(pb, pValSave2, pValSave2);
|
||||
assert(s == BUCKET_SUCCESS);
|
||||
|
||||
start = clock();
|
||||
for(i=0; i<LOOPS; i++){
|
||||
pVal = bucketLookupItem(pb, id1);
|
||||
assert(pVal == pValSave1);
|
||||
pVal = bucketLookupItem(pb, id1);
|
||||
assert(pVal == pValSave1);
|
||||
pVal = bucketLookupItem(pb, id1);
|
||||
assert(pVal == pValSave1);
|
||||
pVal = bucketLookupItem(pb, id1);
|
||||
assert(pVal == pValSave1);
|
||||
pVal = bucketLookupItem(pb, id1);
|
||||
assert(pVal == pValSave1);
|
||||
pVal = bucketLookupItem(pb, id1);
|
||||
assert(pVal == pValSave1);
|
||||
pVal = bucketLookupItem(pb, id1);
|
||||
assert(pVal == pValSave1);
|
||||
pVal = bucketLookupItem(pb, id1);
|
||||
assert(pVal == pValSave1);
|
||||
pVal = bucketLookupItem(pb, id1);
|
||||
assert(pVal == pValSave1);
|
||||
pVal = bucketLookupItem(pb, id2);
|
||||
assert(pVal == pValSave2);
|
||||
}
|
||||
printf("End\n");
|
||||
finish = clock();
|
||||
|
||||
duration = finish-start;
|
||||
duration = duration/CLOCKS_PER_SEC;
|
||||
printf("It took %15.10f total sec\n", duration);
|
||||
duration = duration/LOOPS;
|
||||
duration = duration/10;
|
||||
duration = duration * 1e6;
|
||||
printf("It took %15.10f u sec per hash lookup\n", duration);
|
||||
|
||||
bucketShow(pb);
|
||||
|
||||
return BUCKET_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* bucketUnsignedCompare()
|
||||
*/
|
||||
LOCAL ITEM **bucketUnsignedCompare (ITEM **ppi, const void *pId)
|
||||
{
|
||||
unsigned id;
|
||||
unsigned *pItemId;
|
||||
ITEM *pi;
|
||||
|
||||
id = * (unsigned *) pId;
|
||||
while (pi = *ppi) {
|
||||
if (bidtUnsigned == pi->type) {
|
||||
pItemId = (unsigned *) pi->pId;
|
||||
if (id == *pItemId) {
|
||||
return ppi;
|
||||
}
|
||||
}
|
||||
ppi = &pi->pItem;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* bucketPointerCompare()
|
||||
*/
|
||||
ITEM **bucketPointerCompare (ITEM **ppi, const void *pId)
|
||||
{
|
||||
void *ptr;
|
||||
void **pItemId;
|
||||
ITEM *pi;
|
||||
|
||||
ptr = * (void **) pId;
|
||||
while (pi = *ppi) {
|
||||
if (bidtPointer == pi->type ) {
|
||||
pItemId = (void **) pi->pId;
|
||||
if (ptr == *pItemId) {
|
||||
return ppi;
|
||||
}
|
||||
}
|
||||
ppi = &pi->pItem;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* bucketStringCompare ()
|
||||
*/
|
||||
ITEM **bucketStringCompare (ITEM **ppi, const void *pId)
|
||||
{
|
||||
const char *pStr = pId;
|
||||
ITEM *pi;
|
||||
int status;
|
||||
|
||||
while (pi = *ppi) {
|
||||
if (bidtString == pi->type) {
|
||||
status = strcmp (pStr, (char *)pi->pId);
|
||||
if (status == '\0') {
|
||||
return ppi;
|
||||
}
|
||||
}
|
||||
ppi = &pi->pItem;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* bucketUnsignedHash ()
|
||||
*/
|
||||
BUCKETID bucketUnsignedHash (BUCKET *pb, const void *pId)
|
||||
{
|
||||
const unsigned *pUId = pId;
|
||||
unsigned src;
|
||||
BUCKETID hashid;
|
||||
|
||||
src = *pUId;
|
||||
hashid = src;
|
||||
src = src >> pb->hashIdNBits;
|
||||
while (src) {
|
||||
hashid = hashid ^ src;
|
||||
src = src >> pb->hashIdNBits;
|
||||
}
|
||||
hashid = hashid & pb->hashIdMask;
|
||||
|
||||
return hashid;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* bucketPointerHash ()
|
||||
*
|
||||
*/
|
||||
BUCKETID bucketPointerHash (BUCKET *pb, const void *pId)
|
||||
{
|
||||
void * const *ppId = pId;
|
||||
unsigned long src;
|
||||
BUCKETID hashid;
|
||||
|
||||
/*
|
||||
* This makes the assumption that
|
||||
* a pointer will fit inside of a long
|
||||
* (this assumption may not port to all
|
||||
* CPU architectures)
|
||||
*/
|
||||
src = (unsigned long) *ppId;
|
||||
hashid = src;
|
||||
src = src >> pb->hashIdNBits;
|
||||
while(src){
|
||||
hashid = hashid ^ src;
|
||||
src = src >> pb->hashIdNBits;
|
||||
}
|
||||
hashid = hashid & pb->hashIdMask;
|
||||
|
||||
return hashid;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* bucketStringHash ()
|
||||
*/
|
||||
BUCKETID bucketStringHash (BUCKET *pb, const void *pId)
|
||||
{
|
||||
const char *pStr = pId;
|
||||
BUCKETID hashid;
|
||||
unsigned i;
|
||||
|
||||
hashid = 0;
|
||||
i = 1;
|
||||
while(*pStr){
|
||||
hashid += *pStr * i;
|
||||
pStr++;
|
||||
i++;
|
||||
}
|
||||
|
||||
hashid = hashid % (pb->hashIdMask+1);
|
||||
|
||||
return hashid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* bucketCreate()
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
BUCKET *bucketCreate(unsigned indexWidth)
|
||||
#else
|
||||
BUCKET *bucketCreate(indexWidth)
|
||||
unsigned indexWidth;
|
||||
#endif
|
||||
BUCKET *bucketCreate (unsigned nHashTableEntries)
|
||||
{
|
||||
BUCKETID mask;
|
||||
unsigned nbits;
|
||||
BUCKET *pb;
|
||||
|
||||
/*
|
||||
* no absurd sized buckets
|
||||
*/
|
||||
if (nHashTableEntries<=1) {
|
||||
fprintf (stderr, "Tiny bucket create failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* count the number of bits in the bucket id
|
||||
*/
|
||||
for (nbits=0; nbits<BUCKETID_BIT_WIDTH; nbits++) {
|
||||
mask = (1<<nbits) - 1;
|
||||
if ( ((nHashTableEntries-1) & ~mask) == 0){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* indexWidth must be specified at least one
|
||||
* bit less than the bit size of type BUCKETID
|
||||
*/
|
||||
if(indexWidth>sizeof(BUCKETID)*NBBY){
|
||||
printf("%s at %d: Requested index width=%d is to large. max=%d\n" ,
|
||||
if (nbits>=BUCKETID_BIT_WIDTH) {
|
||||
fprintf (
|
||||
stderr,
|
||||
"%s at %d: Requested index width=%d to large. max=%d\n",
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
indexWidth,
|
||||
sizeof(BUCKETID)*NBBY-1);
|
||||
nbits,
|
||||
BUCKETID_BIT_WIDTH-1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pb = (BUCKET *) calloc(1, sizeof(*pb));
|
||||
if(!pb){
|
||||
if (!pb) {
|
||||
return pb;
|
||||
}
|
||||
|
||||
if(indexWidth>BUCKET_IX_WIDTH){
|
||||
pb->indexShift = indexWidth - BUCKET_IX_WIDTH;
|
||||
}
|
||||
else{
|
||||
pb->indexShift = 0;
|
||||
}
|
||||
pb->nextIndexMask = (1<<pb->indexShift)-1;
|
||||
pb->nEntries = 1<<(indexWidth-pb->indexShift);
|
||||
if(indexWidth == sizeof(BUCKETID)*NBBY){
|
||||
pb->indexMask = 0;
|
||||
pb->indexMask = ~pb->indexMask;
|
||||
}
|
||||
else{
|
||||
pb->indexMask = (1<<indexWidth)-1;
|
||||
}
|
||||
pb->hashIdMask = mask;
|
||||
pb->hashIdNBits = nbits;
|
||||
|
||||
pb->pTable = (ITEMPTR *) calloc(
|
||||
pb->nEntries,
|
||||
sizeof(ITEMPTR));
|
||||
pb->pTable = (ITEM **) calloc (mask+1, sizeof(*pb->pTable));
|
||||
if(!pb->pTable){
|
||||
free(pb);
|
||||
return NULL;
|
||||
@@ -202,14 +383,24 @@ int bucketFree(prb)
|
||||
BUCKET *prb;
|
||||
#endif
|
||||
{
|
||||
ITEM *pi;
|
||||
ITEM *pni;
|
||||
|
||||
/*
|
||||
* deleting a bucket with entries in use
|
||||
* will cause memory leaks and is not allowed
|
||||
*/
|
||||
if(prb->nInUse){
|
||||
return BUCKET_FAILURE;
|
||||
}
|
||||
assert(prb->nInUse==0);
|
||||
|
||||
/*
|
||||
* free the free list
|
||||
*/
|
||||
pi = prb->pFreeItems;
|
||||
while (pi) {
|
||||
pni = pi->pItem;
|
||||
free (pi);
|
||||
pi = pni;
|
||||
}
|
||||
free(prb->pTable);
|
||||
free(prb);
|
||||
|
||||
@@ -220,69 +411,49 @@ BUCKET *prb;
|
||||
/*
|
||||
* bucketAddItem()
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
int bucketAddItem(BUCKET *prb, BUCKETID id, void *pItem)
|
||||
#else
|
||||
int bucketAddItem(prb, id, pItem)
|
||||
BUCKET *prb;
|
||||
BUCKETID id;
|
||||
void *pItem;
|
||||
#endif
|
||||
int bucketAddItemUnsignedId(BUCKET *prb, const unsigned *pId, void *pApp)
|
||||
{
|
||||
int s;
|
||||
ITEMPTR *pi;
|
||||
return bucketAddItem(prb, &BSET[bidtUnsigned], pId, pApp);
|
||||
}
|
||||
int bucketAddItemPointerId(BUCKET *prb, void * const *pId, void *pApp)
|
||||
{
|
||||
return bucketAddItem(prb, &BSET[bidtPointer], pId, pApp);
|
||||
}
|
||||
int bucketAddItemStringId(BUCKET *prb, const char *pId, void *pApp)
|
||||
{
|
||||
return bucketAddItem(prb, &BSET[bidtString], pId, pApp);
|
||||
}
|
||||
LOCAL int bucketAddItem(BUCKET *prb, bucketSET *pBSET, const void *pId, void *pApp)
|
||||
{
|
||||
BUCKETID hashid;
|
||||
ITEM *pi;
|
||||
|
||||
/*
|
||||
* is the id to big ?
|
||||
* try to get it off the free list first. If
|
||||
* that fails then malloc()
|
||||
*/
|
||||
if(id&~prb->indexMask){
|
||||
return BUCKET_FAILURE;
|
||||
pi = prb->pFreeItems;
|
||||
if (pi) {
|
||||
prb->pFreeItems = pi->pItem;
|
||||
}
|
||||
|
||||
if(prb->indexShift){
|
||||
int new;
|
||||
BUCKET *pb;
|
||||
|
||||
pi = &prb->pTable[id>>prb->indexShift];
|
||||
pb = pi->pBucket;
|
||||
|
||||
if(!pb){
|
||||
pb = bucketCreate(prb->indexShift);
|
||||
if(!pb){
|
||||
return BUCKET_FAILURE;
|
||||
}
|
||||
pi->pBucket = pb;
|
||||
prb->nInUse++;
|
||||
new = TRUE;
|
||||
}
|
||||
else{
|
||||
new = FALSE;
|
||||
else {
|
||||
pi = (ITEM *) malloc(sizeof(ITEM));
|
||||
if(!pi){
|
||||
return BUCKET_FAILURE;
|
||||
}
|
||||
|
||||
s = bucketAddItem(
|
||||
pb,
|
||||
id&prb->nextIndexMask,
|
||||
pItem);
|
||||
/*
|
||||
* if memory cant be allocated at a lower
|
||||
* level dont leak everything allocated for this new
|
||||
* item so far
|
||||
*/
|
||||
if(s != BUCKET_SUCCESS && new){
|
||||
s = bucketFree(pb);
|
||||
assert(s == BUCKET_SUCCESS);
|
||||
pi->pBucket = NULL;
|
||||
prb->nInUse--;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
pi = &prb->pTable[id];
|
||||
if(pi->pItem){
|
||||
return BUCKET_FAILURE;
|
||||
}
|
||||
|
||||
pi->pItem = pItem;
|
||||
/*
|
||||
* create the hash index
|
||||
*/
|
||||
hashid = (*pBSET->pHash) (prb, pId);
|
||||
|
||||
pi->pApp = pApp;
|
||||
pi->pId = pId;
|
||||
pi->type = pBSET->type;
|
||||
assert((hashid & ~prb->hashIdMask) == 0);
|
||||
pi->pItem = prb->pTable[hashid];
|
||||
prb->pTable[hashid] = pi;
|
||||
prb->nInUse++;
|
||||
|
||||
return BUCKET_SUCCESS;
|
||||
@@ -292,97 +463,85 @@ void *pItem;
|
||||
/*
|
||||
* bucketRemoveItem()
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
int bucketRemoveItem (BUCKET *prb, BUCKETID id, void *pItem)
|
||||
#else
|
||||
int bucketRemoveItem (prb, id, pItem)
|
||||
BUCKET *prb;
|
||||
BUCKETID id;
|
||||
void *pItem;
|
||||
#endif
|
||||
int bucketRemoveItemUnsignedId (BUCKET *prb, const unsigned *pId)
|
||||
{
|
||||
ITEMPTR *ppi;
|
||||
return bucketRemoveItem(prb, &BSET[bidtUnsigned], pId);
|
||||
}
|
||||
int bucketRemoveItemPointerId (BUCKET *prb, void * const *pId)
|
||||
{
|
||||
return bucketRemoveItem(prb, &BSET[bidtPointer], pId);
|
||||
}
|
||||
int bucketRemoveItemStringId (BUCKET *prb, const char *pId)
|
||||
{
|
||||
return bucketRemoveItem(prb, &BSET[bidtString], pId);
|
||||
}
|
||||
LOCAL int bucketRemoveItem (BUCKET *prb, bucketSET *pBSET, const void *pId)
|
||||
{
|
||||
BUCKETID hashid;
|
||||
ITEM **ppi;
|
||||
ITEM *pi;
|
||||
|
||||
/*
|
||||
* is the id to big ?
|
||||
* create the hash index
|
||||
*/
|
||||
if(id&~prb->indexMask){
|
||||
hashid = (*pBSET->pHash) (prb, pId);
|
||||
|
||||
assert((hashid & ~prb->hashIdMask) == 0);
|
||||
ppi = &prb->pTable[hashid];
|
||||
ppi = (*pBSET->pCompare) (ppi, pId);
|
||||
if(!ppi){
|
||||
return BUCKET_FAILURE;
|
||||
}
|
||||
|
||||
if(prb->indexShift){
|
||||
BUCKET *pb;
|
||||
int s;
|
||||
|
||||
ppi = &prb->pTable[id>>prb->indexShift];
|
||||
pb = ppi->pBucket;
|
||||
|
||||
if(!pb){
|
||||
return BUCKET_FAILURE;
|
||||
}
|
||||
|
||||
s = bucketRemoveItem(
|
||||
pb,
|
||||
id&prb->nextIndexMask,
|
||||
pItem);
|
||||
if(s!=BUCKET_SUCCESS){
|
||||
return s;
|
||||
}
|
||||
|
||||
if(pb->nInUse==0){
|
||||
free(pb->pTable);
|
||||
free(pb);
|
||||
ppi->pBucket = NULL;
|
||||
prb->nInUse--;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
ppi = &prb->pTable[id];
|
||||
if(ppi->pItem != pItem){
|
||||
return BUCKET_FAILURE;
|
||||
}
|
||||
|
||||
prb->nInUse--;
|
||||
ppi->pItem = NULL;
|
||||
pi = *ppi;
|
||||
*ppi = pi->pItem;
|
||||
|
||||
/*
|
||||
* stuff it on the free list
|
||||
*/
|
||||
pi->pItem = prb->pFreeItems;
|
||||
prb->pFreeItems = pi;
|
||||
|
||||
return BUCKET_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* bucketLookupItem()
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
void *bucketLookupItem(BUCKET *pb, BUCKETID id)
|
||||
#else
|
||||
void *bucketLookupItem(pb, id)
|
||||
BUCKET *pb;
|
||||
BUCKETID id;
|
||||
#endif
|
||||
void *bucketLookupItemUnsignedId (BUCKET *prb, const unsigned *pId)
|
||||
{
|
||||
unsigned shift;
|
||||
return bucketLookupItem(prb, &BSET[bidtUnsigned], pId);
|
||||
}
|
||||
void *bucketLookupItemPointerId (BUCKET *prb, void * const *pId)
|
||||
{
|
||||
return bucketLookupItem(prb, &BSET[bidtPointer], pId);
|
||||
}
|
||||
void *bucketLookupItemStringId (BUCKET *prb, const char *pId)
|
||||
{
|
||||
return bucketLookupItem(prb, &BSET[bidtString], pId);
|
||||
}
|
||||
LOCAL void *bucketLookupItem(BUCKET *pb, bucketSET *pBSET, const void *pId)
|
||||
{
|
||||
BUCKETID hashid;
|
||||
ITEM **ppi;
|
||||
|
||||
/*
|
||||
* is the id to big ?
|
||||
* create the hash index
|
||||
*/
|
||||
if(id&~pb->indexMask){
|
||||
return NULL;
|
||||
hashid = (*pBSET->pHash) (pb, pId);
|
||||
assert((hashid & ~pb->hashIdMask) == 0);
|
||||
|
||||
/*
|
||||
* at the bottom level just
|
||||
* linear search for it.
|
||||
*/
|
||||
ppi = (*pBSET->pCompare) (&pb->pTable[hashid], pId);
|
||||
if(ppi){
|
||||
return (*ppi)->pApp;
|
||||
}
|
||||
|
||||
while(shift = pb->indexShift){
|
||||
BUCKETID nextId;
|
||||
|
||||
nextId = id & pb->nextIndexMask;
|
||||
|
||||
pb = pb->pTable[id>>shift].pBucket;
|
||||
if(!pb){
|
||||
return pb;
|
||||
}
|
||||
id = nextId;
|
||||
}
|
||||
|
||||
return pb->pTable[id].pItem;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -397,24 +556,62 @@ int bucketShow(pb)
|
||||
BUCKET *pb;
|
||||
#endif
|
||||
{
|
||||
ITEMPTR *pi;
|
||||
ITEM **ppi;
|
||||
ITEM *pi;
|
||||
ITEM *pni;
|
||||
unsigned nElem;
|
||||
double X;
|
||||
double XX;
|
||||
double mean;
|
||||
double stdDev;
|
||||
unsigned count;
|
||||
unsigned maxEntries;
|
||||
unsigned freeListCount;
|
||||
|
||||
pi = pb->pTable;
|
||||
|
||||
printf( "Bucket: mask=%x entries in use=%d bytes in use=%d\n",
|
||||
(pb->nEntries-1)<<pb->indexShift,
|
||||
pb->nInUse,
|
||||
sizeof(*pb)+pb->nEntries*sizeof(*pi));
|
||||
|
||||
if(pb->indexShift){
|
||||
for( pi = pb->pTable;
|
||||
pi<&pb->pTable[pb->nEntries];
|
||||
pi++){
|
||||
if(pi->pBucket){
|
||||
bucketShow(pi->pBucket);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* count bytes on the free list
|
||||
*/
|
||||
pi = pb->pFreeItems;
|
||||
freeListCount = 0;
|
||||
while (pi) {
|
||||
freeListCount++;
|
||||
pni = pi->pItem;
|
||||
pi = pni;
|
||||
}
|
||||
|
||||
printf( "Bucket entries in use = %d bytes in use = %d\n",
|
||||
pb->nInUse,
|
||||
sizeof(*pb)+(pb->hashIdMask+1)*
|
||||
sizeof(ITEM *)+pb->nInUse*sizeof(ITEM));
|
||||
|
||||
printf( "Free list bytes in use = %d\n",
|
||||
freeListCount*sizeof(ITEM));
|
||||
|
||||
ppi = pb->pTable;
|
||||
nElem = pb->hashIdMask+1;
|
||||
X = 0.0;
|
||||
XX = 0.0;
|
||||
maxEntries = 0;
|
||||
while (ppi < &pb->pTable[nElem]) {
|
||||
pi = *ppi;
|
||||
count = 0;
|
||||
while (pi) {
|
||||
count++;
|
||||
pi = pi->pItem;
|
||||
}
|
||||
X += count;
|
||||
XX += count*count;
|
||||
maxEntries = max (count, maxEntries);
|
||||
ppi++;
|
||||
}
|
||||
|
||||
mean = X/nElem;
|
||||
stdDev = sqrt(XX/nElem - mean*mean);
|
||||
printf( "Bucket entries/hash id - mean = %f std dev = %f max = %d\n",
|
||||
mean,
|
||||
stdDev,
|
||||
maxEntries);
|
||||
|
||||
return BUCKET_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
#include <ellLib.h>
|
||||
|
||||
#if !defined(NULL) || (NULL!=0)
|
||||
#if !defined(NULL)
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
#include <ellLib.h>
|
||||
|
||||
#if !defined(NULL) || (NULL!=0)
|
||||
#if !defined(NULL)
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
/* common to epics Unix and vxWorks */
|
||||
#include "dbAccess.h"
|
||||
#include "asLib.h"
|
||||
#include "sdrHeader.h"
|
||||
#include "drvSup.h"
|
||||
#include "devSup.h"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
* $Id$
|
||||
* share/src/libCom/$Id$
|
||||
*
|
||||
* A file descriptor manager for use with the UNIX system call select
|
||||
*
|
||||
@@ -62,7 +62,6 @@
|
||||
* if we are in fdmgr_pend_event()
|
||||
* .15 joh 011993 Created fdmgr header file
|
||||
* .16 joh 011993 Converted to ANSI C
|
||||
* .17 pg 050494 HPUX cpp changes (elif converted to else & if)
|
||||
*
|
||||
* NOTES:
|
||||
*
|
||||
@@ -90,12 +89,26 @@
|
||||
*
|
||||
*/
|
||||
|
||||
static char *pSccsId = "$Id$";
|
||||
static char *pSccsId = "@(#) $Id$";
|
||||
|
||||
/*
|
||||
* ANSI
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef vxWorks
|
||||
#include <vxWorks.h>
|
||||
#include <taskLib.h>
|
||||
#include <sysLib.h>
|
||||
#include <tickLib.h>
|
||||
#include <logLib.h>
|
||||
#include <selectLib.h>
|
||||
#endif
|
||||
|
||||
#include <fdmgr.h>
|
||||
#ifdef vxWorks
|
||||
#include <taskLib.h>
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
@@ -113,6 +126,10 @@ static char *pSccsId = "$Id$";
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#ifndef LOCAL
|
||||
#define LOCAL static
|
||||
#endif
|
||||
|
||||
#ifndef max
|
||||
#define max(x, y) (((x) < (y)) ? (y) : (x))
|
||||
#endif
|
||||
@@ -130,9 +147,6 @@ typedef struct{
|
||||
#if defined(vxWorks)
|
||||
# define LOCK(PFDCTX) FASTLOCK(&(PFDCTX)->lock)
|
||||
# define UNLOCK(PFDCTX) FASTUNLOCK(&(PFDCTX)->lock)
|
||||
# define LOCK_FDMGR_PEND_EVENT(PFDCTX) \
|
||||
FASTLOCK(&(PFDCTX)->fdmgr_pend_event_lock) \
|
||||
(PFDCTX)->fdmgr_pend_event_tid = taskIdCurrent
|
||||
# define UNLOCK_FDMGR_PEND_EVENT(PFDCTX) \
|
||||
FASTUNLOCK(&(PFDCTX)->fdmgr_pend_event_lock) \
|
||||
(PFDCTX)->fdmgr_pend_event_tid = NULL;
|
||||
@@ -144,109 +158,55 @@ typedef struct{
|
||||
FASTLOCK(&(PFDCTX)->fd_handler_lock)
|
||||
# define UNLOCK_FD_HANDLER(PFDCTX) \
|
||||
FASTUNLOCK(&(PFDCTX)->fd_handler_lock)
|
||||
# define printf logMsg
|
||||
# define fdmgr_gettimeval fdmgr_vxWorks_gettimeval
|
||||
# define memset(D,V,N) bfill(D,N,V)
|
||||
#else
|
||||
#if defined(UNIX)
|
||||
#elif defined(UNIX) || defined(VMS) || defined(_WIN32)
|
||||
# define LOCK(PFDCTX)
|
||||
# define UNLOCK(PFDCTX)
|
||||
# define LOCK_FDMGR_PEND_EVENT(PFDCTX) \
|
||||
{ \
|
||||
if((PFDCTX)->fdmgr_pend_event_in_use){ \
|
||||
printf("Double invocation of fdmgr_pend_event()\n"); \
|
||||
abort(); \
|
||||
} \
|
||||
(PFDCTX)->fdmgr_pend_event_in_use++; \
|
||||
}
|
||||
# define UNLOCK_FDMGR_PEND_EVENT(PFDCTX) \
|
||||
{(PFDCTX)->fdmgr_pend_event_in_use--;}
|
||||
# define fdmgr_gettimeval fdmgr_UNIX_gettimeval
|
||||
# define LOCK_EXPIRED(PFDCTX)
|
||||
# define UNLOCK_EXPIRED(PFDCTX)
|
||||
# define LOCK_FD_HANDLER(PFDCTX)
|
||||
# define UNLOCK_FD_HANDLER(PFDCTX)
|
||||
#else
|
||||
#if defined(VMS)
|
||||
# define LOCK(PFDCTX)
|
||||
# define UNLOCK(PFDCTX)
|
||||
# define LOCK_FDMGR_PEND_EVENT(PFDCTX) \
|
||||
{ \
|
||||
if((PFDCTX)->fdmgr_pend_event_in_use){ \
|
||||
printf("Double invocation of fdmgr_pend_event()\n"); \
|
||||
abort(); \
|
||||
} \
|
||||
(PFDCTX)->fdmgr_pend_event_in_use++; \
|
||||
}
|
||||
# define UNLOCK_FDMGR_PEND_EVENT(PFDCTX) \
|
||||
{(PFDCTX)->fdmgr_pend_event_in_use--;}
|
||||
# define fdmgr_gettimeval fdmgr_VMS_gettimeval
|
||||
# define LOCK_EXPIRED(PFDCTX)
|
||||
# define UNLOCK_EXPIRED(PFDCTX)
|
||||
# define LOCK_FD_HANDLER(PFDCTX)
|
||||
# define UNLOCK_FD_HANDLER(PFDCTX)
|
||||
#else
|
||||
@@@@ dont compile in this case @@@@
|
||||
#endif
|
||||
#endif
|
||||
#error Please define the host OS type
|
||||
#endif
|
||||
|
||||
|
||||
#define USEC_PER_SEC 1000000
|
||||
|
||||
#ifdef __STDC__
|
||||
#define printf @@@@ Please dont use printf in this source @@@@
|
||||
LOCAL int fdmgrPrintf(char *pformat, ...);
|
||||
|
||||
static int fdmgr_vxWorks_gettimeval(
|
||||
LOCAL int fdmgr_gettimeval(
|
||||
fdctx *pfdctx,
|
||||
struct timeval *pt
|
||||
);
|
||||
|
||||
static int fdmgr_UNIX_gettimeval(
|
||||
fdctx *pfdctx,
|
||||
struct timeval *pt
|
||||
);
|
||||
|
||||
static void select_alarm(
|
||||
LOCAL void select_alarm(
|
||||
fdctx *pfdctx
|
||||
);
|
||||
|
||||
|
||||
static int fdmgr_select(
|
||||
LOCAL int fdmgr_select(
|
||||
fdctx *pfdctx,
|
||||
struct timeval *ptimeout
|
||||
);
|
||||
|
||||
static void fdmgr_finish_off_fdentry(
|
||||
LOCAL void fdmgr_finish_off_fdentry(
|
||||
fdctx *pfdctx,
|
||||
register fdentry *pfdentry
|
||||
);
|
||||
|
||||
#else
|
||||
|
||||
static int fdmgr_vxWorks_gettimeval();
|
||||
static int fdmgr_UNIX_gettimeval();
|
||||
static void select_alarm();
|
||||
static int fdmgr_select();
|
||||
static void fdmgr_finish_off_fdentry();
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(vxWorks)
|
||||
# define abort(A) taskSuspend(taskIdSelf())
|
||||
#endif
|
||||
LOCAL void lockFDMGRPendEvent (fdctx *pfdctx);
|
||||
|
||||
/*
|
||||
* This routine is to be only called from fdmgr_pend_event()
|
||||
* If other uses are needed then locking issues must be
|
||||
* reinvestigated
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
static void process_alarm_queue(
|
||||
fdctx *pfdctx,
|
||||
struct timeval *poffset
|
||||
);
|
||||
#else
|
||||
static void process_alarm_queue();
|
||||
#endif
|
||||
LOCAL void process_alarm_queue(
|
||||
fdctx *pfdctx,
|
||||
struct timeval *poffset
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
@@ -254,11 +214,7 @@ static void fdmgr_finish_off_fdentry();
|
||||
* fdmgr_init()
|
||||
*
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
fdctx *fdmgr_init(void)
|
||||
#else
|
||||
fdctx *fdmgr_init()
|
||||
#endif
|
||||
{
|
||||
fdctx *pfdctx;
|
||||
|
||||
@@ -284,29 +240,41 @@ fdctx *fdmgr_init()
|
||||
return pfdctx;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* fdmgr_delete()
|
||||
*
|
||||
*/
|
||||
int fdmgr_delete(fdctx *pfdctx)
|
||||
{
|
||||
if(!pfdctx){
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
# if defined(vxWorks)
|
||||
FASTLOCKFREE(&pfdctx->lock);
|
||||
FASTLOCKFREE(&pfdctx->fdmgr_pend_event_lock);
|
||||
FASTLOCKFREE(&pfdctx->expired_alarm_lock);
|
||||
FASTLOCKFREE(&pfdctx->fd_handler_lock);
|
||||
# endif
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fdmgr_add_timeout()
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
alarm *fdmgr_add_timeout(
|
||||
fdmgrAlarm *fdmgr_add_timeout(
|
||||
fdctx *pfdctx,
|
||||
struct timeval *ptimeout,
|
||||
void (*func)(),
|
||||
void *param
|
||||
)
|
||||
#else
|
||||
alarm *fdmgr_add_timeout(pfdctx,ptimeout,func,param)
|
||||
fdctx *pfdctx;
|
||||
struct timeval *ptimeout;
|
||||
void (*func)();
|
||||
void *param;
|
||||
#endif
|
||||
{
|
||||
alarm *palarm=NULL;
|
||||
alarm *pa;
|
||||
fdmgrAlarm *palarm=NULL;
|
||||
fdmgrAlarm *pa;
|
||||
struct timeval t;
|
||||
int status;
|
||||
|
||||
@@ -320,10 +288,10 @@ void *param;
|
||||
return NULL;
|
||||
|
||||
LOCK(pfdctx);
|
||||
palarm = (alarm *) ellGet(&pfdctx->free_alarm_list);
|
||||
palarm = (fdmgrAlarm *) ellGet(&pfdctx->free_alarm_list);
|
||||
UNLOCK(pfdctx);
|
||||
if(!palarm){
|
||||
palarm = (alarm *) malloc(sizeof(alarm));
|
||||
palarm = (fdmgrAlarm *) malloc(sizeof(fdmgrAlarm));
|
||||
if(!palarm){
|
||||
return NULL;
|
||||
}
|
||||
@@ -332,7 +300,7 @@ void *param;
|
||||
/*
|
||||
* force all fields to a known state
|
||||
*/
|
||||
memset(palarm, 0, sizeof(*palarm));
|
||||
memset((char *)palarm, 0, sizeof(*palarm));
|
||||
|
||||
ptimeout->tv_sec += ptimeout->tv_usec/USEC_PER_SEC;
|
||||
ptimeout->tv_usec = ptimeout->tv_usec%USEC_PER_SEC;
|
||||
@@ -347,9 +315,9 @@ void *param;
|
||||
palarm->t.tv_usec = (t.tv_usec + ptimeout->tv_usec)%USEC_PER_SEC;
|
||||
|
||||
LOCK(pfdctx);
|
||||
for( pa=(alarm *)pfdctx->alarm_list.node.next;
|
||||
for( pa=(fdmgrAlarm *)pfdctx->alarm_list.node.next;
|
||||
pa;
|
||||
pa=(alarm *)pa->node.next){
|
||||
pa=(fdmgrAlarm *)pa->node.next){
|
||||
if(pa->t.tv_sec > palarm->t.tv_sec){
|
||||
break;
|
||||
}
|
||||
@@ -379,16 +347,10 @@ void *param;
|
||||
* fdmgr_clear_timeout()
|
||||
*
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
int fdmgr_clear_timeout(
|
||||
fdctx *pfdctx,
|
||||
alarm *palarm
|
||||
fdmgrAlarm *palarm
|
||||
)
|
||||
#else
|
||||
int fdmgr_clear_timeout(pfdctx, palarm)
|
||||
fdctx *pfdctx;
|
||||
alarm *palarm;
|
||||
#endif
|
||||
{
|
||||
int status;
|
||||
enum alarm_list_type alt;
|
||||
@@ -458,20 +420,12 @@ alarm *palarm;
|
||||
* this rouitine is supplied solely for compatibility
|
||||
* with earlier versions of this software
|
||||
*/
|
||||
#if __STDC__
|
||||
int fdmgr_add_fd(
|
||||
fdctx *pfdctx,
|
||||
int fd,
|
||||
void (*pfunc)(),
|
||||
void *param
|
||||
)
|
||||
#else
|
||||
int fdmgr_add_fd(pfdctx,fd,pfunc,param)
|
||||
fdctx *pfdctx;
|
||||
int fd;
|
||||
void (*pfunc)();
|
||||
void *param;
|
||||
#endif
|
||||
{
|
||||
int status;
|
||||
|
||||
@@ -491,7 +445,6 @@ void *param;
|
||||
* fdmgr_add_fd_callback()
|
||||
*
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
int fdmgr_add_callback(
|
||||
fdctx *pfdctx,
|
||||
int fd,
|
||||
@@ -499,14 +452,6 @@ enum fdi_type fdi,
|
||||
void (*pfunc)(),
|
||||
void *param
|
||||
)
|
||||
#else
|
||||
int fdmgr_add_callback(pfdctx,fd,fdi,pfunc,param)
|
||||
fdctx *pfdctx;
|
||||
int fd;
|
||||
enum fdi_type fdi;
|
||||
void (*pfunc)();
|
||||
void *param;
|
||||
#endif
|
||||
{
|
||||
fdentry *pfdentry;
|
||||
fd_set *pfds;
|
||||
@@ -540,7 +485,7 @@ void *param;
|
||||
/*
|
||||
* force all fields to a known state
|
||||
*/
|
||||
memset(pfdentry, 0, sizeof(*pfdentry));
|
||||
memset((char *)pfdentry, 0, sizeof(*pfdentry));
|
||||
|
||||
pfdentry->fd = fd;
|
||||
pfdentry->fdi = fdi;
|
||||
@@ -564,16 +509,10 @@ void *param;
|
||||
* included solely for compatibility with previous release
|
||||
*
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
int fdmgr_clear_fd(
|
||||
fdctx *pfdctx,
|
||||
int fd
|
||||
)
|
||||
#else
|
||||
int fdmgr_clear_fd(pfdctx,fd)
|
||||
fdctx *pfdctx;
|
||||
int fd;
|
||||
#endif
|
||||
{
|
||||
return fdmgr_clear_callback(pfdctx, fd, fdi_read);
|
||||
}
|
||||
@@ -584,18 +523,11 @@ int fd;
|
||||
* fdmgr_clear_callback()
|
||||
*
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
int fdmgr_clear_callback(
|
||||
fdctx *pfdctx,
|
||||
int fd,
|
||||
enum fdi_type fdi
|
||||
)
|
||||
#else
|
||||
int fdmgr_clear_callback(pfdctx,fd,fdi)
|
||||
fdctx *pfdctx;
|
||||
int fd;
|
||||
enum fdi_type fdi;
|
||||
#endif
|
||||
{
|
||||
register fdentry *pfdentry;
|
||||
int status;
|
||||
@@ -641,6 +573,7 @@ enum fdi_type fdi;
|
||||
*/
|
||||
# ifdef vxWorks
|
||||
if(delete_pending == TRUE){
|
||||
@@@@ review all of this delete pending stuff
|
||||
LOCK_FD_HANDLER(pfdctx);
|
||||
UNLOCK_FD_HANDLER(pfdctx);
|
||||
}
|
||||
@@ -650,7 +583,7 @@ enum fdi_type fdi;
|
||||
* If it is an ukn fd its a problem worth printing out
|
||||
*/
|
||||
if(status != OK){
|
||||
printf("fdmg: delete of ukn fd failed\n");
|
||||
fdmgrPrintf("fdmg: delete of ukn fd failed\n");
|
||||
}
|
||||
|
||||
return status;
|
||||
@@ -664,16 +597,10 @@ enum fdi_type fdi;
|
||||
* !! LOCK(pfdctx) must be applied !!
|
||||
*
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
static void fdmgr_finish_off_fdentry(
|
||||
LOCAL void fdmgr_finish_off_fdentry(
|
||||
fdctx *pfdctx,
|
||||
register fdentry *pfdentry
|
||||
)
|
||||
#else
|
||||
static void fdmgr_finish_off_fdentry(pfdctx,pfdentry)
|
||||
fdctx *pfdctx;
|
||||
register fdentry *pfdentry;
|
||||
#endif
|
||||
{
|
||||
FD_CLR(pfdentry->fd, pfdentry->pfds);
|
||||
ellAdd(&pfdctx->fdentry_free_list, (ELLNODE*)pfdentry);
|
||||
@@ -685,24 +612,18 @@ register fdentry *pfdentry;
|
||||
* fdmgr_pend_event()
|
||||
*
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
int fdmgr_pend_event(
|
||||
fdctx *pfdctx,
|
||||
struct timeval *ptimeout
|
||||
)
|
||||
#else
|
||||
int fdmgr_pend_event(pfdctx,ptimeout)
|
||||
fdctx *pfdctx;
|
||||
struct timeval *ptimeout;
|
||||
#endif
|
||||
{
|
||||
int status;
|
||||
extern errno;
|
||||
struct timeval t;
|
||||
alarm *palarm;
|
||||
fdmgrAlarm *palarm;
|
||||
|
||||
|
||||
LOCK_FDMGR_PEND_EVENT(pfdctx);
|
||||
lockFDMGRPendEvent(pfdctx);
|
||||
|
||||
/*
|
||||
* If its a poll dont add a timeout
|
||||
@@ -757,21 +678,14 @@ struct timeval *ptimeout;
|
||||
* returns TRUE if any labor was performed, otherwise FALSE
|
||||
*
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
static int fdmgr_select(
|
||||
LOCAL int fdmgr_select(
|
||||
fdctx *pfdctx,
|
||||
struct timeval *ptimeout
|
||||
)
|
||||
#else
|
||||
static int fdmgr_select(pfdctx,ptimeout)
|
||||
fdctx *pfdctx;
|
||||
struct timeval *ptimeout;
|
||||
#endif
|
||||
{
|
||||
register fdentry *pfdentry;
|
||||
int labor_performed;
|
||||
int status;
|
||||
int s;
|
||||
|
||||
labor_performed = FALSE;
|
||||
|
||||
@@ -790,8 +704,8 @@ struct timeval *ptimeout;
|
||||
* it is in select() so I am turning
|
||||
* on task delete disable to be safe
|
||||
*/
|
||||
# ifdef vxWorks
|
||||
TASK_SAFE();
|
||||
# ifdef vxWorks
|
||||
taskSafe();
|
||||
# endif
|
||||
status = select(
|
||||
pfdctx->maxfd,
|
||||
@@ -799,8 +713,8 @@ struct timeval *ptimeout;
|
||||
&pfdctx->writech,
|
||||
&pfdctx->excpch,
|
||||
ptimeout);
|
||||
# ifdef vxWorks
|
||||
TASK_UNSAFE();
|
||||
# ifdef vxWorks
|
||||
taskUnsafe();
|
||||
# endif
|
||||
if(status == 0){
|
||||
return labor_performed;
|
||||
@@ -809,12 +723,14 @@ struct timeval *ptimeout;
|
||||
if(errno == EINTR)
|
||||
;
|
||||
else if(errno == EINVAL)
|
||||
printf( "fdmgr: bad select args ? %d %d %d\n",
|
||||
fdmgrPrintf(
|
||||
"fdmgr: bad select args ? %d %d %d\n",
|
||||
pfdctx->maxfd,
|
||||
ptimeout->tv_sec,
|
||||
ptimeout->tv_usec);
|
||||
else
|
||||
printf( "fdmgr: error from select %d\n",
|
||||
fdmgrPrintf(
|
||||
"fdmgr: error from select %d\n",
|
||||
errno);
|
||||
|
||||
return labor_performed;
|
||||
@@ -822,7 +738,6 @@ struct timeval *ptimeout;
|
||||
|
||||
pfdentry = (fdentry *) &pfdctx->fdentry_list.node;
|
||||
while(TRUE){
|
||||
void *pfunc;
|
||||
|
||||
LOCK(pfdctx)
|
||||
pfdentry = (fdentry *) pfdentry->node.next;
|
||||
@@ -896,36 +811,28 @@ struct timeval *ptimeout;
|
||||
* only to be called by fdmgr_pend_event(). If other uses
|
||||
* come up then the locking must be revisited
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
static void process_alarm_queue(
|
||||
LOCAL void process_alarm_queue(
|
||||
fdctx *pfdctx,
|
||||
struct timeval *poffset
|
||||
)
|
||||
#else
|
||||
static void process_alarm_queue(pfdctx,poffset)
|
||||
fdctx *pfdctx;
|
||||
struct timeval *poffset;
|
||||
#endif
|
||||
{
|
||||
struct timeval t;
|
||||
int status;
|
||||
alarm *pa;
|
||||
alarm *nextpa;
|
||||
fdmgrAlarm *pa;
|
||||
fdmgrAlarm *nextpa;
|
||||
|
||||
status = fdmgr_gettimeval(pfdctx, &t);
|
||||
if(status < 0){
|
||||
abort();
|
||||
}
|
||||
assert (status >= 0);
|
||||
|
||||
LOCK(pfdctx);
|
||||
for(pa = (alarm*)pfdctx->alarm_list.node.next; pa; pa = nextpa){
|
||||
for(pa = (fdmgrAlarm*)pfdctx->alarm_list.node.next; pa; pa = nextpa){
|
||||
if(pa->t.tv_sec > t.tv_sec)
|
||||
break;
|
||||
else if(pa->t.tv_sec == t.tv_sec)
|
||||
if(pa->t.tv_usec > t.tv_usec)
|
||||
break;
|
||||
|
||||
nextpa = (alarm*)pa->node.next;
|
||||
nextpa = (fdmgrAlarm*)pa->node.next;
|
||||
ellDelete(&pfdctx->alarm_list, (ELLNODE*)pa);
|
||||
ellAdd(&pfdctx->expired_alarm_list, (ELLNODE*)pa);
|
||||
pa->alt = alt_expired;
|
||||
@@ -954,7 +861,7 @@ struct timeval *poffset;
|
||||
* on multithreaded OS
|
||||
*/
|
||||
LOCK_EXPIRED(pfdctx);
|
||||
pa = (alarm*) pfdctx->expired_alarm_list.node.next;
|
||||
pa = (fdmgrAlarm*) pfdctx->expired_alarm_list.node.next;
|
||||
while(pa){
|
||||
void (*pfunc)();
|
||||
|
||||
@@ -966,7 +873,7 @@ struct timeval *poffset;
|
||||
if(pfunc){
|
||||
(*pfunc)(pa->param);
|
||||
}
|
||||
pa = (alarm*)pa->node.next;
|
||||
pa = (fdmgrAlarm*)pa->node.next;
|
||||
}
|
||||
UNLOCK_EXPIRED(pfdctx);
|
||||
|
||||
@@ -976,14 +883,14 @@ struct timeval *poffset;
|
||||
* expired list onto the free list
|
||||
*/
|
||||
LOCK(pfdctx);
|
||||
pa = (alarm*) pfdctx->expired_alarm_list.node.next;
|
||||
pa = (fdmgrAlarm*) pfdctx->expired_alarm_list.node.next;
|
||||
while(pa){
|
||||
pa->alt = alt_free;
|
||||
pa = (alarm *) pa->node.next;
|
||||
pa = (fdmgrAlarm *) pa->node.next;
|
||||
}
|
||||
ellConcat(&pfdctx->free_alarm_list, &pfdctx->expired_alarm_list);
|
||||
|
||||
pa = (alarm *)pfdctx->alarm_list.node.next;
|
||||
pa = (fdmgrAlarm *)pfdctx->alarm_list.node.next;
|
||||
if(pa){
|
||||
if(pa->t.tv_usec >= t.tv_usec){
|
||||
poffset->tv_sec = pa->t.tv_sec - t.tv_sec;
|
||||
@@ -1007,14 +914,9 @@ struct timeval *poffset;
|
||||
* select_alarm()
|
||||
*
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
static void select_alarm(
|
||||
LOCAL void select_alarm(
|
||||
fdctx *pfdctx
|
||||
)
|
||||
#else
|
||||
static void select_alarm(pfdctx)
|
||||
fdctx *pfdctx;
|
||||
#endif
|
||||
{
|
||||
pfdctx->select_tmo = TRUE;
|
||||
}
|
||||
@@ -1024,21 +926,15 @@ fdctx *pfdctx;
|
||||
|
||||
/*
|
||||
*
|
||||
* fdmgr_UNIX_gettimeval
|
||||
*
|
||||
* UNIX & VMS
|
||||
* fdmgr_gettimeval
|
||||
*
|
||||
*/
|
||||
#ifdef UNIX
|
||||
#ifdef __STDC__
|
||||
static int fdmgr_UNIX_gettimeval(
|
||||
#if defined(UNIX) || defined(VMS)
|
||||
LOCAL int fdmgr_gettimeval(
|
||||
fdctx *pfdctx,
|
||||
struct timeval *pt
|
||||
)
|
||||
#else
|
||||
static int fdmgr_UNIX_gettimeval(pfdctx,pt)
|
||||
fdctx *pfdctx;
|
||||
struct timeval *pt;
|
||||
#endif
|
||||
{
|
||||
struct timezone tz;
|
||||
|
||||
@@ -1049,46 +945,38 @@ struct timeval *pt;
|
||||
|
||||
/*
|
||||
*
|
||||
* fdmgr_VMS_gettimeval
|
||||
* WIN32
|
||||
* fdmgr_gettimeval
|
||||
*
|
||||
*
|
||||
*/
|
||||
#ifdef VMS
|
||||
#ifdef __STDC__
|
||||
static int fdmgr_VMS_gettimeval(
|
||||
fdctx *pfdctx,
|
||||
struct timeval *pt
|
||||
#ifdef _WIN32
|
||||
LOCAL int fdmgr_gettimeval(
|
||||
fdctx *pfdctx,
|
||||
struct timeval *pt
|
||||
)
|
||||
#else
|
||||
static int fdmgr_VMS_gettimeval(pfdctx,pt)
|
||||
fdctx *pfdctx;
|
||||
struct timeval *pt;
|
||||
#endif
|
||||
{
|
||||
struct timezone tz;
|
||||
SYSTEMTIME st;
|
||||
GetSystemTime(&st);
|
||||
pt->tv_sec = (long)st.wSecond + (long)st.wMinute*60 + (long)st.wHour*360
|
||||
0;
|
||||
pt->tv_usec = st.wMilliseconds*1000;
|
||||
|
||||
return gettimeofday(pt, &tz);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* fdmgr_vxWorks_gettimeval
|
||||
*
|
||||
* vxWorks
|
||||
* fdmgr_gettimeval
|
||||
*
|
||||
*/
|
||||
#ifdef vxWorks
|
||||
#ifdef __STDC__
|
||||
static int fdmgr_vxWorks_gettimeval(
|
||||
LOCAL int fdmgr_gettimeval(
|
||||
fdctx *pfdctx,
|
||||
struct timeval *pt
|
||||
)
|
||||
#else
|
||||
static int fdmgr_vxWorks_gettimeval(pfdctx,pt)
|
||||
fdctx *pfdctx;
|
||||
struct timeval *pt;
|
||||
#endif
|
||||
{
|
||||
unsigned long current;
|
||||
|
||||
@@ -1108,3 +996,66 @@ struct timeval *pt;
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* lockFDMGRPendEvent()
|
||||
*/
|
||||
LOCAL void lockFDMGRPendEvent (fdctx *pfdctx)
|
||||
{
|
||||
# if defined(vxWorks)
|
||||
FASTLOCK(&pfdctx->fdmgr_pend_event_lock);
|
||||
pfdctx->fdmgr_pend_event_tid = taskIdCurrent;
|
||||
# else
|
||||
assert (pfdctx->fdmgr_pend_event_in_use==0);
|
||||
pfdctx->fdmgr_pend_event_in_use++;
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
* fdmgrPrintf()
|
||||
*
|
||||
* Dump error messages to the appropriate place
|
||||
*
|
||||
*/
|
||||
LOCAL int fdmgrPrintf(char *pformat, ...)
|
||||
{
|
||||
va_list args;
|
||||
int status;
|
||||
|
||||
va_start(args, pformat);
|
||||
|
||||
#ifndef vxWorks
|
||||
status = vfprintf(
|
||||
stderr,
|
||||
pformat,
|
||||
args);
|
||||
#else /*vxWorks*/
|
||||
{
|
||||
int logMsgArgs[6];
|
||||
int i;
|
||||
|
||||
for(i=0; i< NELEMENTS(logMsgArgs); i++){
|
||||
logMsgArgs[i] = va_arg(args, int);
|
||||
}
|
||||
|
||||
status = logMsg(
|
||||
pformat,
|
||||
logMsgArgs[0],
|
||||
logMsgArgs[1],
|
||||
logMsgArgs[2],
|
||||
logMsgArgs[3],
|
||||
logMsgArgs[4],
|
||||
logMsgArgs[5]);
|
||||
|
||||
}
|
||||
#endif /*vxWorks*/
|
||||
|
||||
va_end(args);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ unsigned long size;
|
||||
|
||||
if(memDebugLevel>2){
|
||||
fprintf(stderr, "%08x=malloc(%d) %s.%d\n",
|
||||
pHdr->pUser, size, pFile, line);
|
||||
(unsigned) pHdr->pUser, size, pFile, line);
|
||||
}
|
||||
|
||||
return pHdr->pUser;
|
||||
@@ -178,8 +178,10 @@ void *ptr;
|
||||
|
||||
if(status<0 || (pHdr->pUser != ptr)){
|
||||
FASTUNLOCK(&memDebugLock);
|
||||
fprintf(stderr, "%s.%d free(%08x) failed\n", pFile, line, ptr);
|
||||
fprintf(stderr, "malloc occured at %s.%d\n", pHdr->pFile, pHdr->line);
|
||||
fprintf(stderr, "%s.%d free(%08x) failed\n",
|
||||
pFile, line, (unsigned) ptr);
|
||||
fprintf(stderr, "malloc occured at %s.%d\n",
|
||||
pHdr->pFile, pHdr->line);
|
||||
assert(0);
|
||||
}
|
||||
ellDelete(&memDebugList, &pHdr->node);
|
||||
@@ -188,7 +190,8 @@ void *ptr;
|
||||
memDebugVerify(pHdr);
|
||||
|
||||
if(memDebugLevel>2){
|
||||
fprintf(stderr, "free(%08x) %s.%d\n", ptr, pFile, line);
|
||||
fprintf(stderr, "free(%08x) %s.%d\n",
|
||||
(unsigned)ptr, pFile, line);
|
||||
fprintf(stderr,
|
||||
"\tmalloc(%d) at %s.%d\n",
|
||||
pHdr->size,
|
||||
@@ -215,8 +218,10 @@ DMH *pHdr;
|
||||
}
|
||||
|
||||
if(pHdr->magic != debugMallocMagic || pHdr->pFoot->magic != debugMallocMagic){
|
||||
fprintf(stderr, "block overwritten %x\n", pHdr->pUser);
|
||||
fprintf(stderr, "malloc occured at %s.%d\n", pHdr->pFile, pHdr->line);
|
||||
fprintf(stderr, "block overwritten %x\n",
|
||||
(unsigned)pHdr->pUser);
|
||||
fprintf(stderr, "malloc occured at %s.%d\n",
|
||||
pHdr->pFile, pHdr->line);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -252,7 +257,6 @@ int memDebugPrintAll(ignoreBeforeThisTick)
|
||||
unsigned long ignoreBeforeThisTick;
|
||||
#endif /*__STDC__*/
|
||||
{
|
||||
int status;
|
||||
DMH *pHdr;
|
||||
|
||||
FASTLOCK(&memDebugLock);
|
||||
@@ -263,7 +267,7 @@ unsigned long ignoreBeforeThisTick;
|
||||
}
|
||||
fprintf(stderr,
|
||||
"%8x = malloc(%d) at %s.%d tick=%d\n",
|
||||
pHdr->pUser,
|
||||
(unsigned) pHdr->pUser,
|
||||
pHdr->size,
|
||||
pHdr->pFile,
|
||||
pHdr->line,
|
||||
|
||||
@@ -5,28 +5,96 @@ include $(EPICS)/config/CONFIG_BASE
|
||||
USR_INCLUDES = -I../../drv
|
||||
|
||||
SRCS.c = \
|
||||
../recAi.c ../recGsub.c ../recPulseDelay.c ../recAo.c \
|
||||
../recHistogram.c ../recPulseTrain.c ../recBi.c ../recLongin.c \
|
||||
../recSel.c ../recBo.c ../recLongout.c ../recSeq.c \
|
||||
../recCalc.c ../recMbbi.c ../recState.c ../recCompress.c \
|
||||
../recMbbiDirect.c ../recSteppermotor.c ../recEg.c ../recMbbo.c \
|
||||
../recStringin.c ../recEgevent.c ../recMbboDirect.c ../recStringout.c \
|
||||
../recEr.c ../recPal.c ../recSub.c ../recErevent.c \
|
||||
../recPermissive.c ../recSwitch.c ../recEvent.c ../recPid.c \
|
||||
../recTimer.c ../recFanout.c ../recPulseCounter.c ../recWaveform.c \
|
||||
../recSubArray.c ../recWait.c ../caMonitor.c ../recScan.c \
|
||||
../recAai.c ../recAao.c ../recDfanout.c ../recMbbiDirect.c ../recMbboDirect.c
|
||||
../recAi.c\
|
||||
../recAo.c\
|
||||
../recBi.c\
|
||||
../recBo.c\
|
||||
../recCalc.c\
|
||||
../recCompress.c\
|
||||
../recDfanout.c\
|
||||
../recEg.c\
|
||||
../recEgevent.c\
|
||||
../recEr.c\
|
||||
../recErevent.c\
|
||||
../recEvent.c\
|
||||
../recFanout.c\
|
||||
../recHistogram.c\
|
||||
../recLongin.c\
|
||||
../recLongout.c\
|
||||
../recMbbi.c\
|
||||
../recMbbiDirect.c\
|
||||
../recMbbo.c\
|
||||
../recMbboDirect.c\
|
||||
../recPermissive.c\
|
||||
../recPid.c\
|
||||
../recPulseCounter.c\
|
||||
../recPulseDelay.c\
|
||||
../recPulseTrain.c\
|
||||
../recScan.c\
|
||||
../recSel.c\
|
||||
../recSeq.c\
|
||||
../recState.c\
|
||||
../recSteppermotor.c\
|
||||
../recStringin.c\
|
||||
../recStringout.c\
|
||||
../recSub.c\
|
||||
../recSubArray.c\
|
||||
../recTimer.c\
|
||||
../recWaveform.c\
|
||||
../recWait.c\
|
||||
../caMonitor.c
|
||||
# ../recPal.c\
|
||||
# ../recSwitch.c\
|
||||
# ../recGsub.c\
|
||||
# ../recAai.c\
|
||||
# ../recAao.c
|
||||
|
||||
OBJS = \
|
||||
recAi.o recGsub.o recPulseDelay.o recAo.o recHistogram.o \
|
||||
recPulseTrain.o recBi.o recLongin.o recSel.o recBo.o \
|
||||
recLongout.o recSeq.o recCalc.o recMbbi.o recState.o recCompress.o \
|
||||
recMbbiDirect.o recSteppermotor.o recEg.o recMbbo.o \
|
||||
recStringin.o recEgevent.o recMbboDirect.o recStringout.o \
|
||||
recEr.o recPal.o recSub.o recErevent.o recPermissive.o recSwitch.o \
|
||||
recEvent.o recPid.o recTimer.o recFanout.o recPulseCounter.o \
|
||||
recWaveform.o recSubArray.o recWait.o caMonitor.o recScan.o \
|
||||
recAai.o recAao.o recDfanout.o recMbbiDirect.o recMbboDirect.o
|
||||
recAi.o\
|
||||
recPulseDelay.o\
|
||||
recAo.o\
|
||||
recHistogram.o\
|
||||
recPulseTrain.o\
|
||||
recBi.o\
|
||||
recLongin.o\
|
||||
recSel.o\
|
||||
recBo.o\
|
||||
recLongout.o\
|
||||
recSeq.o\
|
||||
recCalc.o\
|
||||
recMbbi.o\
|
||||
recState.o\
|
||||
recCompress.o\
|
||||
recMbbiDirect.o\
|
||||
recSteppermotor.o\
|
||||
recEg.o\
|
||||
recMbbo.o\
|
||||
recStringin.o\
|
||||
recEgevent.o\
|
||||
recMbboDirect.o\
|
||||
recStringout.o\
|
||||
recEr.o\
|
||||
recSub.o\
|
||||
recErevent.o\
|
||||
recPermissive.o\
|
||||
recEvent.o\
|
||||
recPid.o\
|
||||
recTimer.o\
|
||||
recFanout.o\
|
||||
recPulseCounter.o\
|
||||
recWaveform.o\
|
||||
recSubArray.o\
|
||||
recWait.o\
|
||||
recScan.o\
|
||||
recDfanout.o\
|
||||
recMbbiDirect.o\
|
||||
recMbboDirect.o\
|
||||
caMonitor.o
|
||||
# recPal.o\
|
||||
# recSwitch.o\
|
||||
# recGsub.o\
|
||||
# recAai.o\
|
||||
# recAao.o\
|
||||
|
||||
|
||||
PROD = recSup
|
||||
|
||||
@@ -501,6 +501,7 @@ static void convert(pao,pvalue)
|
||||
if (pao->oroc < -diff) value = pao->oval - pao->oroc;
|
||||
}else if (pao->oroc < diff) value = pao->oval + pao->oroc;
|
||||
}
|
||||
if(pao->oval==value) pao->omod = FALSE; else pao->omod = TRUE;
|
||||
pao->oval = value;
|
||||
|
||||
/* convert */
|
||||
@@ -556,8 +557,9 @@ static void monitor(pao)
|
||||
if (monitor_mask){
|
||||
db_post_events(pao,&pao->val,monitor_mask);
|
||||
}
|
||||
if(pao->oval!=pao->val) monitor_mask |= (DBE_VALUE|DBE_LOG);
|
||||
if(pao->omod) monitor_mask |= (DBE_VALUE|DBE_LOG);
|
||||
if(monitor_mask) {
|
||||
pao->omod = FALSE;
|
||||
db_post_events(pao,&pao->oval,monitor_mask);
|
||||
if(pao->oraw != pao->rval) {
|
||||
db_post_events(pao,&pao->rval,monitor_mask|DBE_VALUE);
|
||||
|
||||
@@ -235,12 +235,15 @@ static long get_enum_strs(paddr,pes)
|
||||
{
|
||||
struct biRecord *pbi=(struct biRecord *)paddr->precord;
|
||||
|
||||
pes->no_str = 2;
|
||||
pes->no_str = 0;
|
||||
memset(pes->strs,'\0',sizeof(pes->strs));
|
||||
strncpy(pes->strs[0],pbi->znam,sizeof(pbi->znam));
|
||||
if(*pbi->znam!=0) pes->no_str=1;
|
||||
strncpy(pes->strs[1],pbi->onam,sizeof(pbi->onam));
|
||||
if(*pbi->onam!=0) pes->no_str=2;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long put_enum_str(paddr,pstring)
|
||||
struct dbAddr *paddr;
|
||||
char *pstring;
|
||||
|
||||
@@ -368,10 +368,12 @@ static long get_enum_strs(paddr,pes)
|
||||
{
|
||||
struct boRecord *pbo=(struct boRecord *)paddr->precord;
|
||||
|
||||
pes->no_str = 2;
|
||||
pes->no_str = 0;
|
||||
memset(pes->strs,'\0',sizeof(pes->strs));
|
||||
strncpy(pes->strs[0],pbo->znam,sizeof(pbo->znam));
|
||||
if(*pbo->znam!=0) pes->no_str=1;
|
||||
strncpy(pes->strs[1],pbo->onam,sizeof(pbo->onam));
|
||||
if(*pbo->onam!=0) pes->no_str=2;
|
||||
return(0);
|
||||
}
|
||||
static long put_enum_str(paddr,pstring)
|
||||
|
||||
@@ -1,49 +1,14 @@
|
||||
/* recLongout.c */
|
||||
/* share/src/rec @(#)recLongout.c 1.16 6/4/93 */
|
||||
/* recDfanout.c */
|
||||
/* share/src/rec @(#)recDfanout.c 1.16 6/4/93 */
|
||||
|
||||
/* recLongout.c - Record Support Routines for Longout records */
|
||||
/* recDfanout.c - Record Support Routines for Dfanout records */
|
||||
/*
|
||||
* Author: Janet Anderson
|
||||
* Date: 9/23/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
|
||||
* Author: Matt Bickley
|
||||
* Date: Sometime in 1994
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 11-11-91 jba Moved set and reset of alarm stat and sevr to macros
|
||||
* .02 02-05-92 jba Changed function arguments from paddr to precord
|
||||
* .03 02-28-92 jba ANSI C changes
|
||||
* .04 04-10-92 jba pact now used to test for asyn processing, not status
|
||||
* .05 04-18-92 jba removed process from dev init_record parms
|
||||
* .06 06-02-92 jba changed graphic/control limits for hihi,high,low,lolo
|
||||
* .07 07-15-92 jba changed VALID_ALARM to INVALID alarm
|
||||
* .08 07-16-92 jba added invalid alarm fwd link test and chngd fwd lnk to macro
|
||||
* .09 07-21-92 jba changed alarm limits for non val related fields
|
||||
* .10 08-06-92 jba New algorithm for calculating analog alarms
|
||||
* .11 08-14-92 jba Added simulation processing
|
||||
* .12 08-19-92 jba Added code for invalid alarm output action
|
||||
* .13 09-10-92 jba modified fetch of val from dol to call recGblGetLinkValue
|
||||
* .14 09-18-92 jba pact now set in recGblGetLinkValue
|
||||
* .15 10-21-93 mhb Started with longout record to make the data fanout
|
||||
* .01 1994 mhb Started with longout record to make the data fanout
|
||||
*/
|
||||
|
||||
|
||||
@@ -105,7 +70,6 @@ struct rset dfanoutRSET={
|
||||
|
||||
static void alarm();
|
||||
static void monitor();
|
||||
static long writeValue();
|
||||
static long push_values();
|
||||
|
||||
#define OUT_ARG_MAX 8
|
||||
@@ -124,22 +88,6 @@ static long init_record(pdfanout,pass)
|
||||
|
||||
if (pass==0) return(0);
|
||||
|
||||
/* dfanout.siml must be a CONSTANT or a PV_LINK or a DB_LINK */
|
||||
switch (pdfanout->siml.type) {
|
||||
case (CONSTANT) :
|
||||
pdfanout->simm = pdfanout->siml.value.value;
|
||||
break;
|
||||
case (PV_LINK) :
|
||||
status = dbCaAddInlink(&(pdfanout->siml), (void *) pdfanout, "SIMM");
|
||||
if(status) return(status);
|
||||
break;
|
||||
case (DB_LINK) :
|
||||
break;
|
||||
default :
|
||||
recGblRecordError(S_db_badField,(void *)pdfanout,
|
||||
"dfanout: init_record Illegal SIML field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
|
||||
plink = &pdfanout->outa;
|
||||
for (i=0; i<OUT_ARG_MAX; i++, plink++) {
|
||||
@@ -149,12 +97,6 @@ static long init_record(pdfanout,pass)
|
||||
}
|
||||
}
|
||||
|
||||
/* dfanout.siol may be a PV_LINK */
|
||||
if (pdfanout->siol.type == PV_LINK){
|
||||
status = dbCaAddOutlink(&(pdfanout->siol), (void *) pdfanout, "VAL");
|
||||
if(status) return(status);
|
||||
}
|
||||
|
||||
/* get the initial value dol is a constant*/
|
||||
if (pdfanout->dol.type == CONSTANT){
|
||||
pdfanout->val = pdfanout->dol.value.value;
|
||||
@@ -184,37 +126,12 @@ static long process(pdfanout)
|
||||
if(RTN_SUCCESS(status)) pdfanout->udf=FALSE;
|
||||
}
|
||||
|
||||
/* check for alarms */
|
||||
alarm(pdfanout);
|
||||
|
||||
if (pdfanout->nsev < INVALID_ALARM )
|
||||
status=writeValue(pdfanout); /* write the new value */
|
||||
else {
|
||||
switch (pdfanout->ivoa) {
|
||||
case (IVOA_CONTINUE) :
|
||||
status=writeValue(pdfanout); /* write the new value */
|
||||
break;
|
||||
case (IVOA_NO_OUTPUT) :
|
||||
break;
|
||||
case (IVOA_OUTPUT_IVOV) :
|
||||
if(pdfanout->pact == FALSE){
|
||||
pdfanout->val=pdfanout->ivov;
|
||||
}
|
||||
status=writeValue(pdfanout); /* write the new value */
|
||||
break;
|
||||
default :
|
||||
status=-1;
|
||||
recGblRecordError(S_db_badField,(void *)pdfanout,
|
||||
"dfanout:process Illegal IVOA field");
|
||||
}
|
||||
}
|
||||
|
||||
/* check if device support set pact */
|
||||
if ( !pact && pdfanout->pact ) return(0);
|
||||
pdfanout->pact = TRUE;
|
||||
|
||||
recGblGetTimeStamp(pdfanout);
|
||||
|
||||
/* Push out the data to all the forward links */
|
||||
status = push_values(pdfanout);
|
||||
/* check for alarms */
|
||||
alarm(pdfanout);
|
||||
/* check event list */
|
||||
@@ -223,8 +140,6 @@ static long process(pdfanout)
|
||||
/* process the forward scan link record */
|
||||
recGblFwdLink(pdfanout);
|
||||
|
||||
/* Push out the data to all the forward links */
|
||||
status = push_values(pdfanout);
|
||||
|
||||
pdfanout->pact=FALSE;
|
||||
return(status);
|
||||
@@ -380,30 +295,6 @@ static void monitor(pdfanout)
|
||||
return;
|
||||
}
|
||||
|
||||
static long writeValue(pdfanout)
|
||||
struct dfanoutRecord *pdfanout;
|
||||
{
|
||||
long status;
|
||||
long nRequest=1;
|
||||
long options=0;
|
||||
|
||||
status=recGblGetLinkValue(&(pdfanout->siml),
|
||||
(void *)pdfanout,DBR_ENUM,&(pdfanout->simm),&options,&nRequest);
|
||||
if (!RTN_SUCCESS(status))
|
||||
return(status);
|
||||
|
||||
if (pdfanout->simm == YES){
|
||||
status=recGblPutLinkValue(&(pdfanout->siol),
|
||||
(void *)pdfanout,DBR_LONG,&(pdfanout->val),&nRequest);
|
||||
} else {
|
||||
status=-1;
|
||||
recGblSetSevr(pdfanout,SOFT_ALARM,INVALID_ALARM);
|
||||
return(status);
|
||||
}
|
||||
recGblSetSevr(pdfanout,SIMM_ALARM,pdfanout->sims);
|
||||
|
||||
return(status);
|
||||
}
|
||||
static long push_values(pdfanout)
|
||||
struct dfanoutRecord *pdfanout;
|
||||
{
|
||||
|
||||
@@ -182,7 +182,13 @@ LOCAL void access_rights_reply(
|
||||
struct channel_in_use *pciu
|
||||
);
|
||||
|
||||
LOCAL unsigned long bucketID;
|
||||
LOCAL struct channel_in_use *casCreateChannel (
|
||||
struct client *client,
|
||||
struct db_addr *pAddr,
|
||||
unsigned cid
|
||||
);
|
||||
|
||||
LOCAL unsigned bucketID;
|
||||
|
||||
|
||||
/*
|
||||
@@ -204,7 +210,7 @@ struct message_buffer *recv
|
||||
struct channel_in_use *pciu;
|
||||
|
||||
if(!pCaBucket){
|
||||
pCaBucket = bucketCreate(NBBY*sizeof(mp->m_cid));
|
||||
pCaBucket = bucketCreate(CAS_HASH_TABLE_SIZE);
|
||||
if(!pCaBucket){
|
||||
return ERROR;
|
||||
}
|
||||
@@ -537,53 +543,80 @@ struct client *client
|
||||
int status;
|
||||
struct channel_in_use *pciu;
|
||||
|
||||
|
||||
FASTLOCK(&prsrv_cast_client->addrqLock);
|
||||
|
||||
/*
|
||||
* clients which dont claim their
|
||||
* channel in use block prior to
|
||||
* timeout must reconnect
|
||||
* The available field is used (abused)
|
||||
* here to communicate the miner version number
|
||||
* starting with CA 4.1. The field was set to zero
|
||||
* prior to 4.1
|
||||
*/
|
||||
pciu = MPTOPCIU(mp);
|
||||
if(!pciu){
|
||||
logMsg("CAS: client timeout disconnect id=%d\n",
|
||||
mp->m_cid,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
client->minor_version_number = mp->m_available;
|
||||
|
||||
if (CA_V44(CA_PROTOCOL_VERSION,client->minor_version_number)) {
|
||||
struct db_addr tmp_addr;
|
||||
|
||||
status = db_name_to_addr(
|
||||
mp + 1,
|
||||
&tmp_addr);
|
||||
if (status < 0) {
|
||||
return;
|
||||
}
|
||||
pciu = casCreateChannel (
|
||||
client,
|
||||
&tmp_addr,
|
||||
mp->m_cid);
|
||||
if (!pciu) {
|
||||
SEND_LOCK(client);
|
||||
send_err(mp,
|
||||
ECA_ALLOCMEM,
|
||||
client,
|
||||
RECORD_NAME(&tmp_addr));
|
||||
SEND_UNLOCK(client);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
FASTLOCK(&prsrv_cast_client->addrqLock);
|
||||
/*
|
||||
* clients which dont claim their
|
||||
* channel in use block prior to
|
||||
* timeout must reconnect
|
||||
*/
|
||||
pciu = MPTOPCIU(mp);
|
||||
if(!pciu){
|
||||
logMsg("CAS: client timeout disconnect id=%d\n",
|
||||
mp->m_cid,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
FASTUNLOCK(&prsrv_cast_client->addrqLock);
|
||||
free_client(client);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* remove channel in use block from
|
||||
* the UDP client where it could time
|
||||
* out and place it on the client
|
||||
* who is claiming it
|
||||
*/
|
||||
ellDelete(
|
||||
&prsrv_cast_client->addrq,
|
||||
&pciu->node);
|
||||
FASTUNLOCK(&prsrv_cast_client->addrqLock);
|
||||
|
||||
/*
|
||||
* Any other client attachment is a severe error
|
||||
*/
|
||||
assert (pciu->client==prsrv_cast_client);
|
||||
|
||||
FASTLOCK(&prsrv_cast_client->addrqLock);
|
||||
pciu->client = client;
|
||||
ellAdd(&client->addrq, &pciu->node);
|
||||
FASTUNLOCK(&prsrv_cast_client->addrqLock);
|
||||
free_client(client);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* remove channel in use block from
|
||||
* the UDP client where it could time
|
||||
* out and place it on the client
|
||||
* who is claiming it
|
||||
*/
|
||||
ellDelete(
|
||||
&prsrv_cast_client->addrq,
|
||||
&pciu->node);
|
||||
FASTUNLOCK(&prsrv_cast_client->addrqLock);
|
||||
|
||||
/*
|
||||
* Any other client attachment is a severe error
|
||||
*/
|
||||
if(pciu->client!=prsrv_cast_client){
|
||||
logMsg("CAS: bad channel claim disconnect %d %x %x\n",
|
||||
mp->m_cid,
|
||||
(int)pciu,
|
||||
(int)pciu->client,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
free_client(client);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* set up access security for this channel
|
||||
@@ -608,19 +641,6 @@ struct client *client
|
||||
*/
|
||||
asPutClientPvt(pciu->asClientPVT, pciu);
|
||||
|
||||
FASTLOCK(&prsrv_cast_client->addrqLock);
|
||||
pciu->client = client;
|
||||
ellAdd(&client->addrq, &pciu->node);
|
||||
FASTUNLOCK(&prsrv_cast_client->addrqLock);
|
||||
|
||||
/*
|
||||
* The available field is used (abused)
|
||||
* here to communicate the miner version number
|
||||
* starting with CA 4.1. The field was set to zero
|
||||
* prior to 4.1
|
||||
*/
|
||||
pciu->client->minor_version_number = mp->m_available;
|
||||
|
||||
v42 = CA_V42(
|
||||
CA_PROTOCOL_VERSION,
|
||||
client->minor_version_number);
|
||||
@@ -631,7 +651,9 @@ struct client *client
|
||||
* the correct client, and the clients version is
|
||||
* known)
|
||||
*/
|
||||
status = asRegisterClientCallback(pciu->asClientPVT, casAccessRightsCB);
|
||||
status = asRegisterClientCallback(
|
||||
pciu->asClientPVT,
|
||||
casAccessRightsCB);
|
||||
if(status == S_asLib_asNotActive){
|
||||
/*
|
||||
* force the initial update
|
||||
@@ -654,6 +676,7 @@ struct client *client
|
||||
claim_reply->m_type = pciu->addr.field_type;
|
||||
claim_reply->m_count = pciu->addr.no_elements;
|
||||
claim_reply->m_cid = pciu->cid;
|
||||
claim_reply->m_available = pciu->sid;
|
||||
END_MSG(client);
|
||||
SEND_UNLOCK(client);
|
||||
}
|
||||
@@ -1183,7 +1206,7 @@ struct client *client
|
||||
}
|
||||
|
||||
FASTLOCK(&rsrv_free_addrq_lck);
|
||||
status = bucketRemoveItem(pCaBucket, pciu->sid, pciu);
|
||||
status = bucketRemoveItemUnsignedId (pCaBucket, &pciu->sid);
|
||||
if(status != BUCKET_SUCCESS){
|
||||
logBadId(client, mp);
|
||||
}
|
||||
@@ -1543,15 +1566,24 @@ struct extmsg *mp,
|
||||
struct client *client
|
||||
)
|
||||
{
|
||||
struct db_addr tmp_addr;
|
||||
struct extmsg *search_reply;
|
||||
struct extmsg *get_reply;
|
||||
unsigned short *pMinorVersion;
|
||||
int status;
|
||||
struct db_addr tmp_addr;
|
||||
struct channel_in_use *pchannel;
|
||||
unsigned long sid;
|
||||
|
||||
unsigned sid;
|
||||
|
||||
/*
|
||||
* set true if max memory block drops below MAX_BLOCK_THRESHOLD
|
||||
*/
|
||||
if(casDontAllowSearchReplies){
|
||||
SEND_LOCK(client);
|
||||
send_err(mp,
|
||||
ECA_ALLOCMEM,
|
||||
client,
|
||||
"Server memory exhausted");
|
||||
SEND_UNLOCK(client);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Exit quickly if channel not on this node */
|
||||
status = db_name_to_addr(
|
||||
@@ -1572,25 +1604,22 @@ struct client *client
|
||||
}
|
||||
|
||||
/*
|
||||
* set true if max memory block drops below MAX_BLOCK_THRESHOLD
|
||||
* starting with V4.4 the count field is used (abused)
|
||||
* to store the minor version number of the client.
|
||||
*
|
||||
* New versions dont alloc the channel in response
|
||||
* to a search request.
|
||||
*/
|
||||
if(casDontAllowSearchReplies){
|
||||
SEND_LOCK(client);
|
||||
send_err(mp,
|
||||
ECA_ALLOCMEM,
|
||||
client,
|
||||
"Server memory exhausted");
|
||||
SEND_UNLOCK(client);
|
||||
return;
|
||||
if (CA_V44(CA_PROTOCOL_VERSION,htons(mp->m_count))) {
|
||||
sid = ~0U;
|
||||
}
|
||||
else {
|
||||
struct channel_in_use *pchannel;
|
||||
|
||||
|
||||
/* get block off free list if possible */
|
||||
FASTLOCK(&rsrv_free_addrq_lck);
|
||||
pchannel = (struct channel_in_use *) ellGet(&rsrv_free_addrq);
|
||||
FASTUNLOCK(&rsrv_free_addrq_lck);
|
||||
if (!pchannel) {
|
||||
pchannel = (struct channel_in_use *) malloc(sizeof(*pchannel));
|
||||
pchannel = casCreateChannel (
|
||||
client,
|
||||
&tmp_addr,
|
||||
ntohs(mp->m_cid));
|
||||
if (!pchannel) {
|
||||
SEND_LOCK(client);
|
||||
send_err(mp,
|
||||
@@ -1600,39 +1629,14 @@ struct client *client
|
||||
SEND_UNLOCK(client);
|
||||
return;
|
||||
}
|
||||
}
|
||||
memset((char *)pchannel, 0, sizeof(*pchannel));
|
||||
ellInit(&pchannel->eventq);
|
||||
pchannel->ticks_at_creation = tickGet();
|
||||
pchannel->addr = tmp_addr;
|
||||
pchannel->client = client;
|
||||
pchannel->cid = mp->m_cid;
|
||||
|
||||
/*
|
||||
* allocate a server id and enter the channel pointer
|
||||
* in the table
|
||||
*/
|
||||
FASTLOCK(&rsrv_free_addrq_lck);
|
||||
sid = bucketID++;
|
||||
pchannel->sid = sid;
|
||||
status = bucketAddItem(pCaBucket, sid, pchannel);
|
||||
FASTUNLOCK(&rsrv_free_addrq_lck);
|
||||
if(status!=BUCKET_SUCCESS){
|
||||
SEND_LOCK(client);
|
||||
send_err(mp, ECA_ALLOCMEM, client, "No room for hash table");
|
||||
SEND_UNLOCK(client);
|
||||
FASTLOCK(&rsrv_free_addrq_lck);
|
||||
ellAdd(&rsrv_free_addrq, &pchannel->node);
|
||||
FASTUNLOCK(&rsrv_free_addrq_lck);
|
||||
return;
|
||||
sid = pchannel->sid;
|
||||
}
|
||||
|
||||
SEND_LOCK(client);
|
||||
|
||||
search_reply = (struct extmsg *)
|
||||
ALLOC_MSG(client, sizeof(*pMinorVersion));
|
||||
if (!search_reply)
|
||||
taskSuspend(0);
|
||||
assert (search_reply);
|
||||
|
||||
*search_reply = *mp;
|
||||
search_reply->m_postsize = sizeof(*pMinorVersion);
|
||||
@@ -1653,12 +1657,75 @@ struct client *client
|
||||
END_MSG(client);
|
||||
SEND_UNLOCK(client);
|
||||
|
||||
/* store the addr block on the cast queue until it is claimed */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* casCreateChannel ()
|
||||
*/
|
||||
LOCAL struct channel_in_use *casCreateChannel (
|
||||
struct client *client,
|
||||
struct db_addr *pAddr,
|
||||
unsigned cid
|
||||
)
|
||||
{
|
||||
unsigned *pCID;
|
||||
struct channel_in_use *pchannel;
|
||||
unsigned sid;
|
||||
int status;
|
||||
|
||||
/* get block off free list if possible */
|
||||
FASTLOCK(&rsrv_free_addrq_lck);
|
||||
pchannel = (struct channel_in_use *) ellGet(&rsrv_free_addrq);
|
||||
FASTUNLOCK(&rsrv_free_addrq_lck);
|
||||
if (!pchannel) {
|
||||
pchannel = (struct channel_in_use *)
|
||||
malloc(sizeof(*pchannel));
|
||||
if (!pchannel) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
memset((char *)pchannel, 0, sizeof(*pchannel));
|
||||
ellInit(&pchannel->eventq);
|
||||
pchannel->ticks_at_creation = tickGet();
|
||||
pchannel->addr = *pAddr;
|
||||
pchannel->client = client;
|
||||
/*
|
||||
* bypass read only warning
|
||||
*/
|
||||
pCID = (unsigned *) &pchannel->cid;
|
||||
*pCID = cid;
|
||||
|
||||
/*
|
||||
* allocate a server id and enter the channel pointer
|
||||
* in the table
|
||||
*/
|
||||
FASTLOCK(&rsrv_free_addrq_lck);
|
||||
sid = bucketID++;
|
||||
/*
|
||||
* bypass read only warning
|
||||
*/
|
||||
pCID = (unsigned *) &pchannel->sid;
|
||||
*pCID = sid;
|
||||
status = bucketAddItemUnsignedId (
|
||||
pCaBucket,
|
||||
&pchannel->sid,
|
||||
pchannel);
|
||||
FASTUNLOCK(&rsrv_free_addrq_lck);
|
||||
if(status!=BUCKET_SUCCESS){
|
||||
FASTLOCK(&rsrv_free_addrq_lck);
|
||||
ellAdd(&rsrv_free_addrq, &pchannel->node);
|
||||
FASTUNLOCK(&rsrv_free_addrq_lck);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FASTLOCK(&client->addrqLock);
|
||||
ellAdd(&client->addrq, &pchannel->node);
|
||||
FASTUNLOCK(&client->addrqLock);
|
||||
|
||||
return;
|
||||
return pchannel;
|
||||
}
|
||||
|
||||
|
||||
@@ -1905,10 +1972,11 @@ struct client *pc
|
||||
*/
|
||||
LOCAL struct channel_in_use *MPTOPCIU(struct extmsg *mp)
|
||||
{
|
||||
struct channel_in_use *pciu;
|
||||
struct channel_in_use *pciu;
|
||||
const unsigned id = mp->m_cid;
|
||||
|
||||
FASTLOCK(&rsrv_free_addrq_lck);
|
||||
pciu = bucketLookupItem(pCaBucket, mp->m_cid);
|
||||
pciu = bucketLookupItemUnsignedId (pCaBucket, &id);
|
||||
FASTUNLOCK(&rsrv_free_addrq_lck);
|
||||
|
||||
return pciu;
|
||||
@@ -1926,7 +1994,6 @@ LOCAL void casAccessRightsCB(ASCLIENTPVT ascpvt, asClientStatus type)
|
||||
struct client *pclient;
|
||||
struct channel_in_use *pciu;
|
||||
struct event_ext *pevext;
|
||||
int status;
|
||||
|
||||
pciu = asGetClientPvt(ascpvt);
|
||||
assert(pciu);
|
||||
|
||||
@@ -78,7 +78,6 @@ FAST int sock;
|
||||
int nchars;
|
||||
FAST int status;
|
||||
FAST struct client *client;
|
||||
int i;
|
||||
int true = TRUE;
|
||||
|
||||
client = NULL;
|
||||
|
||||
@@ -66,6 +66,7 @@ static char *sccsId = "@(#)caservertask.c 1.22 5/6/94";
|
||||
#include <taskwd.h>
|
||||
#include <db_access.h>
|
||||
#include <task_params.h>
|
||||
#include <envDefs.h>
|
||||
#include <server.h>
|
||||
|
||||
LOCAL int terminate_one_client(struct client *client);
|
||||
@@ -88,6 +89,11 @@ int req_server(void)
|
||||
struct sockaddr_in serverAddr; /* server's address */
|
||||
int status;
|
||||
int i;
|
||||
short port;
|
||||
|
||||
taskwdInsert((int)taskIdCurrent,NULL,NULL);
|
||||
|
||||
port = caFetchPortConfig(&EPICS_CA_SERVER_PORT, CA_SERVER_PORT);
|
||||
|
||||
if (IOC_sock != 0 && IOC_sock != ERROR)
|
||||
if ((status = close(IOC_sock)) == ERROR)
|
||||
@@ -113,13 +119,11 @@ int req_server(void)
|
||||
NULL);
|
||||
taskSuspend(0);
|
||||
}
|
||||
|
||||
taskwdInsert((int)taskIdCurrent,NULL,NULL);
|
||||
|
||||
/* Zero the sock_addr structure */
|
||||
bfill((char *)&serverAddr, sizeof(serverAddr), 0);
|
||||
serverAddr.sin_family = AF_INET;
|
||||
serverAddr.sin_port = CA_SERVER_PORT;
|
||||
serverAddr.sin_port = htons(port);
|
||||
|
||||
/* get server's Internet address */
|
||||
if (bind(IOC_sock, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == ERROR) {
|
||||
@@ -315,7 +319,9 @@ LOCAL int terminate_one_client(struct client *client)
|
||||
free(pciu->pPutNotify);
|
||||
}
|
||||
FASTLOCK(&rsrv_free_addrq_lck);
|
||||
status = bucketRemoveItem(pCaBucket, pciu->sid, pciu);
|
||||
status = bucketRemoveItemUnsignedId (
|
||||
pCaBucket,
|
||||
&pciu->sid);
|
||||
FASTUNLOCK(&rsrv_free_addrq_lck);
|
||||
if(status != BUCKET_SUCCESS){
|
||||
logMsg(
|
||||
|
||||
@@ -79,6 +79,7 @@ static char *sccsId = "@(#)cast_server.c 1.24 5/6/94";
|
||||
#include <taskwd.h>
|
||||
#include <db_access.h>
|
||||
#include <task_params.h>
|
||||
#include <envDefs.h>
|
||||
#include <server.h>
|
||||
|
||||
|
||||
@@ -100,9 +101,12 @@ int cast_server(void)
|
||||
struct sockaddr_in new_recv_addr;
|
||||
int recv_addr_size;
|
||||
unsigned nchars;
|
||||
short port;
|
||||
|
||||
taskwdInsert((int)taskIdCurrent,NULL,NULL);
|
||||
|
||||
port = caFetchPortConfig(&EPICS_CA_SERVER_PORT, CA_SERVER_PORT);
|
||||
|
||||
recv_addr_size = sizeof(new_recv_addr);
|
||||
|
||||
if( IOC_cast_sock!=0 && IOC_cast_sock!=ERROR )
|
||||
@@ -137,8 +141,7 @@ int cast_server(void)
|
||||
bfill((char *)&sin, sizeof(sin), 0);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr.s_addr = INADDR_ANY;
|
||||
sin.sin_port = CA_SERVER_PORT;
|
||||
|
||||
sin.sin_port = htons(port);
|
||||
|
||||
/* get server's Internet address */
|
||||
if( bind(IOC_cast_sock, (struct sockaddr *)&sin, sizeof (sin)) == ERROR){
|
||||
@@ -339,11 +342,12 @@ LOCAL void clean_addrq()
|
||||
}
|
||||
|
||||
if (delay > timeout) {
|
||||
int status;
|
||||
|
||||
ellDelete(&prsrv_cast_client->addrq, &pciu->node);
|
||||
FASTLOCK(&rsrv_free_addrq_lck);
|
||||
s = bucketRemoveItem(pCaBucket, pciu->sid, pciu);
|
||||
s = bucketRemoveItemUnsignedId (
|
||||
pCaBucket,
|
||||
&pciu->sid);
|
||||
if(s != BUCKET_SUCCESS){
|
||||
logMsg(
|
||||
"%s Bad id at close",
|
||||
|
||||
@@ -74,23 +74,39 @@ int rsrv_online_notify_task()
|
||||
{
|
||||
ELLLIST destAddr;
|
||||
caAddrNode *pNode;
|
||||
/*
|
||||
* 1 sec init delay
|
||||
*/
|
||||
unsigned long delay = sysClkRateGet();
|
||||
/*
|
||||
* CA_ONLINE_DELAY max delay in ticks
|
||||
*/
|
||||
unsigned long maxdelay = CA_ONLINE_DELAY;
|
||||
unsigned long delay;
|
||||
unsigned long maxdelay;
|
||||
long longStatus;
|
||||
double maxPeriod;
|
||||
struct extmsg msg;
|
||||
|
||||
struct sockaddr_in recv_addr;
|
||||
int status;
|
||||
int sock;
|
||||
int true = TRUE;
|
||||
short port;
|
||||
|
||||
taskwdInsert(taskIdSelf(),NULL,NULL);
|
||||
|
||||
longStatus = envGetDoubleConfigParam (
|
||||
&EPICS_CA_BEACON_PERIOD,
|
||||
&maxPeriod);
|
||||
if (longStatus) {
|
||||
maxPeriod = 15.0;
|
||||
ca_printf (
|
||||
"EPICS \"%s\" float fetch failed\n",
|
||||
EPICS_CA_BEACON_PERIOD.name);
|
||||
ca_printf (
|
||||
"Setting \"%s\" = %f\n",
|
||||
EPICS_CA_BEACON_PERIOD.name,
|
||||
maxPeriod);
|
||||
}
|
||||
|
||||
/*
|
||||
* 1 sec init delay between beacons
|
||||
*/
|
||||
delay = sysClkRateGet();
|
||||
maxdelay = max(maxPeriod*sysClkRateGet(),sysClkRateGet());
|
||||
|
||||
/*
|
||||
* Open the socket.
|
||||
* Use ARPA Internet address format and datagram socket.
|
||||
@@ -128,13 +144,13 @@ int rsrv_online_notify_task()
|
||||
msg.m_cmmd = htons(IOC_RSRV_IS_UP);
|
||||
|
||||
ellInit(&destAddr);
|
||||
caDiscoverInterfaces(&destAddr, sock, CA_CLIENT_PORT);
|
||||
|
||||
caAddConfiguredAddr(
|
||||
&destAddr,
|
||||
&EPICS_CA_ADDR_LIST,
|
||||
sock,
|
||||
CA_CLIENT_PORT);
|
||||
/*
|
||||
* load user and auto configured
|
||||
* broadcast address list
|
||||
*/
|
||||
port = caFetchPortConfig(&EPICS_CA_REPEATER_PORT, CA_REPEATER_PORT);
|
||||
caSetupBCastAddrList (&destAddr, sock, port);
|
||||
|
||||
# ifdef DEBUG
|
||||
caPrintAddrList(&destAddr);
|
||||
|
||||
@@ -45,6 +45,14 @@
|
||||
|
||||
static char *serverhSccsId = "@(#)server.h 1.19 5/6/94";
|
||||
|
||||
#if defined(CAS_VERSION_GLOBAL) && 0
|
||||
# define HDRVERSIONID(NAME,VERS) VERSIONID(NAME,VERS)
|
||||
#else /*CAS_VERSION_GLOBAL*/
|
||||
# define HDRVERSIONID(NAME,VERS)
|
||||
#endif /*CAS_VERSION_GLOBAL*/
|
||||
|
||||
typedef int SOCKET;
|
||||
|
||||
#include <vxLib.h>
|
||||
#include <ellLib.h>
|
||||
#include <fast_lock.h>
|
||||
@@ -54,6 +62,7 @@ static char *serverhSccsId = "@(#)server.h 1.19 5/6/94";
|
||||
#include <dbEvent.h>
|
||||
#include <iocmsg.h>
|
||||
#include <bucketLib.h>
|
||||
#include <taskwd.h>
|
||||
|
||||
#include <asLib.h>
|
||||
#include <asDbLib.h>
|
||||
@@ -112,8 +121,8 @@ struct channel_in_use{
|
||||
ELLLIST eventq;
|
||||
struct client *client;
|
||||
RSRVPUTNOTIFY *pPutNotify; /* potential active put notify */
|
||||
unsigned long cid; /* client id */
|
||||
unsigned long sid; /* server id */
|
||||
const unsigned cid; /* client id */
|
||||
const unsigned sid; /* server id */
|
||||
unsigned long ticks_at_creation; /* for UDP timeout */
|
||||
struct db_addr addr;
|
||||
ASCLIENTPVT asClientPVT;
|
||||
@@ -158,6 +167,9 @@ GLBLTYPE FAST_LOCK rsrv_free_addrq_lck;
|
||||
GLBLTYPE FAST_LOCK rsrv_free_eventq_lck;
|
||||
GLBLTYPE struct client *prsrv_cast_client;
|
||||
GLBLTYPE BUCKET *pCaBucket;
|
||||
|
||||
#define CAS_HASH_TABLE_SIZE 4096
|
||||
|
||||
/*
|
||||
* set true if max memory block drops below MAX_BLOCK_THRESHOLD
|
||||
*/
|
||||
|
||||
@@ -2,14 +2,20 @@ EPICS = ../../../..
|
||||
include Target.include
|
||||
include $(EPICS)/config/CONFIG_BASE
|
||||
|
||||
|
||||
LEX = $(ELEX)
|
||||
YACC = $(EYACC)
|
||||
#YACCOPT = -l
|
||||
#LEXOPT = -L
|
||||
|
||||
USR_LDLIBS = -ll
|
||||
YACCOPT = -d -v
|
||||
|
||||
SRCS.c = ../snc_main.c ../parse.c ../phase2.c ../gen_ss_code.c \
|
||||
../gen_tables.c sncVersion.c snc.c snc_lex.c
|
||||
SRCS.c = ../parse.c ../phase2.c ../gen_ss_code.c \
|
||||
../gen_tables.c sncVersion.c snc.c
|
||||
|
||||
OBJS = snc_main.o parse.o phase2.o gen_ss_code.o \
|
||||
gen_tables.o sncVersion.o snc.o snc_lex.o
|
||||
OBJS = parse.o phase2.o gen_ss_code.o \
|
||||
gen_tables.o sncVersion.o snc.o
|
||||
|
||||
PROD = snc
|
||||
|
||||
@@ -20,6 +26,8 @@ include $(EPICS)/config/RULES.Unix
|
||||
#
|
||||
snc_lex.c: snc.h
|
||||
|
||||
snc.o: snc_lex.c
|
||||
|
||||
sncVersion.c: ../Version
|
||||
$(RM) sncVersion.c
|
||||
sh ../makeVersion ../Version > sncVersion.c
|
||||
|
||||
@@ -321,4 +321,5 @@ global_c
|
||||
: C_STMT { global_c_stmt($1); }
|
||||
;
|
||||
%%
|
||||
|
||||
#include "snc_lex.c"
|
||||
#include "snc_main.c"
|
||||
|
||||
@@ -22,8 +22,10 @@
|
||||
* Comments are recognized as part of the syntax.
|
||||
*/
|
||||
|
||||
/*
|
||||
#include "parse.h"
|
||||
#include "snc.h" /* output from yacc */
|
||||
#include "snc.h"
|
||||
*/
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
@@ -3,18 +3,25 @@ include Target.include
|
||||
include $(EPICS)/config/CONFIG_BASE
|
||||
|
||||
CMPLR = OLD
|
||||
YACCOPT = -d
|
||||
YACC = $(EYACC)
|
||||
YACCOPT = -l -d
|
||||
|
||||
SKELETON_FILE=include/flex.skel.static
|
||||
ifeq ($(T_A),hp700)
|
||||
USR_CFLAGS = -DDEFAULT_SKELETON_FILE=\"$(SKELETON_FILE)\" -DSCO_UNIX
|
||||
else
|
||||
USR_CFLAGS = -DDEFAULT_SKELETON_FILE=\"$(SKELETON_FILE)\"
|
||||
endif
|
||||
USR_LDLIBS = -s
|
||||
|
||||
SRCS.c = ../ccl.c ../dfa.c ../ecs.c ../gen.c ../main.c \
|
||||
../misc.c ../nfa.c parse.c ../scan.c ../sym.c \
|
||||
../tblcmp.c ../yylex.c
|
||||
# main.c is included in parse.c
|
||||
SRCS.c = ../ccl.c ../dfa.c ../ecs.c ../gen.c \
|
||||
../misc.c ../nfa.c ../sym.c \
|
||||
../tblcmp.c parse.c
|
||||
|
||||
OBJS = \
|
||||
ccl.o dfa.o ecs.o gen.o main.o misc.o \
|
||||
nfa.o parse.o scan.o sym.o tblcmp.o yylex.o
|
||||
ccl.o dfa.o ecs.o gen.o misc.o \
|
||||
nfa.o sym.o tblcmp.o parse.o
|
||||
|
||||
PROD = e_flex
|
||||
|
||||
|
||||
@@ -194,16 +194,18 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE;
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
#ifndef lint
|
||||
static char rcsid[] =
|
||||
"@(#) $Header$ (LBL)";
|
||||
#endif
|
||||
|
||||
#undef yywrap
|
||||
|
||||
#include "flexdef.h"
|
||||
#include "parse.h"
|
||||
|
||||
*/
|
||||
#undef yywrap
|
||||
|
||||
|
||||
#define ACTION_ECHO fprintf( temp_action_file, "%s", yytext )
|
||||
#define MARK_END_OF_PROLOG fprintf( temp_action_file, "%%%% end of prolog\n" );
|
||||
|
||||
|
||||
@@ -32,13 +32,14 @@ char copyright[] =
|
||||
All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
#ifndef lint
|
||||
static char rcsid[] =
|
||||
"@(#) $Header$ (LBL)";
|
||||
#endif
|
||||
|
||||
|
||||
#include "flexdef.h"
|
||||
*/
|
||||
|
||||
static char flex_version[] = "2.3";
|
||||
|
||||
|
||||
@@ -700,3 +700,8 @@ char msg[];
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
#include "scan.c"
|
||||
#include "yylex.c"
|
||||
#include "main.c"
|
||||
|
||||
|
||||
@@ -194,15 +194,18 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE;
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
#ifndef lint
|
||||
static char rcsid[] =
|
||||
"@(#) $Header$ (LBL)";
|
||||
#endif
|
||||
#include "flexdef.h"
|
||||
#include <parse.h>
|
||||
|
||||
*/
|
||||
|
||||
#undef yywrap
|
||||
|
||||
#include "flexdef.h"
|
||||
#include <parse.h>
|
||||
|
||||
#define ACTION_ECHO fprintf( temp_action_file, "%s", yytext )
|
||||
#define MARK_END_OF_PROLOG fprintf( temp_action_file, "%%%% end of prolog\n" );
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
#ifndef lint
|
||||
static char rcsid[] =
|
||||
"@(#) $Header$ (LBL)";
|
||||
@@ -34,7 +35,7 @@ static char rcsid[] =
|
||||
#include <ctype.h>
|
||||
#include "flexdef.h"
|
||||
#include "parse.h"
|
||||
|
||||
*/
|
||||
|
||||
/* ANSI C does not guarantee that isascii() is defined */
|
||||
#ifndef isascii
|
||||
@@ -214,3 +215,4 @@ int yylex()
|
||||
|
||||
return ( toktype );
|
||||
}
|
||||
|
||||
|
||||
@@ -15,13 +15,13 @@ USR_INCLUDES = -I$(OPENWIN)/include
|
||||
USR_CFLAGS = -DXWINDOWS -UvxWorks
|
||||
|
||||
SRCS.c = \
|
||||
../apCreateShadow.c ../apStatusSync.c ../bfRing.c ../ca_test.c \
|
||||
../bfRing.c ../ca_test.c \
|
||||
../calcTest.c ../cmdClient.c ../extrDoc.c ../guiSubr.c \
|
||||
../iocLogServer.c ../pprPlot.c ../racPrint.c ../recListProg.c \
|
||||
../recordTest.c ../startCArepeater.c ../sydPlot.c
|
||||
|
||||
OBJS = \
|
||||
apCreateShadow.o apStatusSync.o bfRing.o ca_test.o calcTest.o \
|
||||
bfRing.o ca_test.o calcTest.o \
|
||||
cmdClient.o extrDoc.o guiSubr.o iocLogServer.o pprPlot.o racPrint.o \
|
||||
recListProg.o recordTest.o startCArepeater.o sydPlot.o
|
||||
|
||||
@@ -31,7 +31,7 @@ LIBOBJS = \
|
||||
LIBNAME = libppr.a
|
||||
|
||||
PROD = \
|
||||
apCreateShadow apStatusSync bfRing ca_test calcTest cmdClient \
|
||||
bfRing ca_test calcTest cmdClient \
|
||||
extrDoc iocLogServer racPrint recListProg recordTest startCArepeater
|
||||
|
||||
include $(EPICS)/config/RULES.Unix
|
||||
|
||||
@@ -161,7 +161,7 @@ char *pname;
|
||||
/*
|
||||
* fetch as each type
|
||||
*/
|
||||
for(i=0; i<=LAST_BUFFER_TYPE; i++){
|
||||
for(i=0; i<=DBR_CTRL_DOUBLE; i++){
|
||||
if(ca_field_type(chan_id)==0) {
|
||||
if( (i!=DBR_STRING)
|
||||
&& (i!=DBR_STS_STRING)
|
||||
|
||||
Reference in New Issue
Block a user