Compare commits

...

46 Commits

Author SHA1 Message Date
Janet B. Anderson
d0d1a39c57 Removed unbundled products apCreateShadow and apStatusSync 1994-11-30 15:17:07 +00:00
John Winans
622c4f8382 Added IRQ mode stuff 1994-11-30 15:10:23 +00:00
Jeff Hill
da47b297d2 new env var 1994-11-29 22:41:46 +00:00
Jeff Hill
53b2a77378 no tiny buckets 1994-11-29 22:41:12 +00:00
Jeff Hill
81de80789c added new EPICS env var
fixed delete of cast iiu when all disconn chan deleted
1994-11-29 22:40:22 +00:00
Marty Kraimer
d32a6bb770 Fix for ctl/L 1994-11-29 22:37:17 +00:00
Johnny Tang
5d341aed37 atdb.c is included in atdb_yacc.c 1994-11-29 21:37:18 +00:00
Jeff Hill
3fee3eceff fixed vx exit handler problems 1994-11-23 21:03:41 +00:00
Johnny Tang
ded5d21444 Use elex and antelope instead of lex and yacc. 1994-11-23 20:17:11 +00:00
Janet B. Anderson
02310d0bd4 Converted from flex and yacc to e_flex and antelope. 1994-11-23 19:48:14 +00:00
Johnny Tang
2fb0212252 Included main.c scan.c and yylex.c into parse.y 1994-11-23 19:33:09 +00:00
Johnny Tang
2e16f3a6d7 Comment out flexdef.h 1994-11-23 19:31:39 +00:00
Johnny Tang
47fa7a4fa4 include scan.c yylex.c and main.c 1994-11-23 19:30:54 +00:00
Marty Kraimer
0a1c03c8d4 Added omod field sp that monitors to oval properly posted 1994-11-23 15:33:36 +00:00
Marty Kraimer
8815ca1008 emoved simulation fields 1994-11-23 15:30:55 +00:00
Marty Kraimer
c1b65bad02 Dont build pal and switch 1994-11-23 15:30:20 +00:00
Jeff Hill
a8c8dc89d9 fixed use of bogus broadcast var pointer in conn.c prior to first search 1994-11-18 00:34:06 +00:00
John Winans
3ce0670ba8 Turned off the debugging system (it consumed an additional 30% of CPU) 1994-11-17 21:15:26 +00:00
Jeff Hill
bc89526dff more fixes for use of defunct task var under vxWorks 1994-11-17 21:12:23 +00:00
John Winans
1c7a4ef3db Major restructuring of init code. 1994-11-17 21:11:58 +00:00
Marty Kraimer
a7333f554d add asLib.h 1994-11-17 20:27:35 +00:00
Jeff Hill
c2484d675b sccs %W%W => CVS $Id$ 1994-11-17 19:11:06 +00:00
Jeff Hill
589ccacc3d Fixed vxWorks exit handler used wrong task variable 1994-11-17 19:09:55 +00:00
Jeff Hill
9d3ce3aedd dont alloc chan in response to search message 1994-11-16 03:42:07 +00:00
Jeff Hill
a88293bbbb dont alloc channel in response to search request changes 1994-11-16 03:41:25 +00:00
Marty Kraimer
46e1cdf441 In non-syc mode return 2 for no convert 1994-11-15 21:46:35 +00:00
Marty Kraimer
1a826583e7 On ca_puts changed check for illegal type (needed for alarm ack) 1994-11-15 20:25:48 +00:00
Janet B. Anderson
99434dfe06 Added gsd_sync_subr.c and USR_LDFLAGS 1994-11-15 16:24:27 +00:00
Johnny Tang
5db7f418d4 Update README.hp700_alpha 1994-11-14 23:32:52 +00:00
Janet B. Anderson
70e2716ff0 One file per line again, commented out drvCaenV265.c 1994-11-14 23:22:15 +00:00
Johnny Tang
51eb05d411 replace install with cp and chmod. 1994-11-14 23:21:51 +00:00
Johnny Tang
754dd841eb Replace ARCH_TYPE with . 1994-11-14 23:12:17 +00:00
Marty Kraimer
f2d167920c Fixed get so it doesnt try ACK request types 1994-11-14 21:01:53 +00:00
Johnny Tang
4ae4145b9e Replace ARCH_TYPE with . 1994-11-14 19:26:16 +00:00
Jeff Hill
d453191f25 added windows_depen.c 1994-11-14 19:04:57 +00:00
Jeff Hill
0c2699c85b added drvCaenV265.c 1994-11-14 18:59:31 +00:00
Jeff Hill
ea9d141a54 dded caenV265 1994-11-14 18:48:45 +00:00
Jeff Hill
7bb451bb74 updated for changes in bucketLib.c 1994-11-14 18:47:18 +00:00
Jeff Hill
0ba3898e81 Improved bucketLib.c & portability changes 1994-11-14 18:45:25 +00:00
Jeff Hill
547ca9d02d Changes for NT, ALPHA/OSF, and VAX/VMS port 1994-11-14 18:43:05 +00:00
Marty Kraimer
348f4c0e8d One line per module 1994-11-14 16:20:22 +00:00
Marty Kraimer
2fddb398b2 Allow white space in parm field 1994-11-14 16:18:53 +00:00
Janet B. Anderson
688f766622 Bug fix for pes->no_str calculation 1994-11-14 15:59:10 +00:00
Janet B. Anderson
c0892857eb Changed ARCH to T_A 1994-11-03 21:08:44 +00:00
Janet B. Anderson
a1458c0c58 Added conditional for hp700 -- lie about being SCO_UNIX 1994-11-03 21:00:35 +00:00
cvs2svn
15d6708cec This commit was manufactured by cvs2svn to create tag 'R3.12.0-beta0'. 1994-11-01 14:55:16 +00:00
74 changed files with 5759 additions and 2916 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,4 @@
/*
* $Id$
* caRepeater.c
* share/src/ca/caRepeater.c
*

View File

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

View File

@@ -10,11 +10,8 @@
*/
# ifdef VMS
lib$init_timer();
# endif
# ifdef VMS
lib$show_timer();
#ifdef VMS
#include <LIB$ROUTINES.H>
#endif

View File

@@ -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(&current);
/*
* 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 (
&current,
&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 (
&current,
&piiu->timeAtEchoRequest);
stmo = delay > CA_RETRY_PERIOD;
delay = cac_time_diff (
&current,
&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 (
&current,
&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 (
&current,
&piiu->timeAtLastRecv);
if (delay>ca_static->ca_connectTMO) {
echo_request(piiu, &current);
}
}
}
UNLOCK;
if(!piiuCast){
/*
* try to attach to the repeater if we havent yet
*/
if (!ca_static->ca_repeater_contacted) {
delay = cac_time_diff (
&current,
&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,
&current);
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 (
&current,
&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(&currentTime);
delay = cac_time_diff(
&ca_static->ca_conn_next_retry,
&currentTime);
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(&currentTime);
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 (
&currentTime,
&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(&currentTime, &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);
}

View File

@@ -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 *)&copyin;
@@ -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*/

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -34,7 +34,7 @@
#include <ellLib.h>
#if !defined(NULL) || (NULL!=0)
#if !defined(NULL)
#define NULL 0
#endif

View File

@@ -34,7 +34,7 @@
#include <ellLib.h>
#if !defined(NULL) || (NULL!=0)
#if !defined(NULL)
#define NULL 0
#endif

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -78,7 +78,6 @@ FAST int sock;
int nchars;
FAST int status;
FAST struct client *client;
int i;
int true = TRUE;
client = NULL;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -321,4 +321,5 @@ global_c
: C_STMT { global_c_stmt($1); }
;
%%
#include "snc_lex.c"
#include "snc_main.c"

View File

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

View File

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

View File

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

View File

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

View File

@@ -700,3 +700,8 @@ char msg[];
{
}
#include "scan.c"
#include "yylex.c"
#include "main.c"

View File

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

View File

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

View File

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

View File

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