EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  <20032004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  <20032004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: RE: CA questions
From: "Jeff Hill" <[email protected]>
To: "'Liyu, Andrei'" <[email protected]>, <[email protected]>
Date: Tue, 4 Nov 2003 15:12:24 -0700
Hello,

I have also provided individual responses to your questions below.

I did update some CA reference manual sections in response to some of your
questions and these sections are attached at the end for your review. 

> 1. So, first question about
> ca_current_context () and ca_attach_context().
> 
> My program srars and I created thread ONE and use
> 	ca_context_create (ca_enable_preemptive_callback);
> 
> Then I create thread TWO. I believe that I should use
> 
> 	struct ca_client_context * pSThreadCAContext;
> 	pSThreadCAContext = ca_current_context ();
> // pSThreadCAContext should not equal NULL!!!
> 	int iStatus = ca_attach_context( pSThreadCAContext);
> // iStatus should equal ECA_ISATTACHED
> 
> What is next step? For example,
> 	pSThreadCAContext->ca_function( ...);
> or
> 	ca_function( ...)?

The CA API was written long before C++ was popular and also did not
originally support multiple CA client contexts in the same process. It is
necessary to remain backward compatible. Therefore, the original CA client
API does not have calls of the form "pSThreadCAContext->ca_function", but a
future C++ based API will. It is not necessary to specify the context
identifier when invoking the library because the context identifier is
stored in a thread private variable by ca_attach_context().

> 
> 
> If I am not mistaken when I would like to finish work with CA I should
> - close all channel in all threads
> - use ca_context_destroy(); once in any thread.
> Am I right?

Yes. That should work fine. The most common situation is for the thread that
called ca_context_create() to call ca_context_destroy(), but I don't know of
any reason why an auxiliary thread should not call ca_context_destroy().

> 
> Also what I will have if I init CA library some times?

I am confused by this question but I am guessing that you are just
emphasizing that in your situation you would like to call
ca_context_destroy() from a different thread than the one that called
ca_context_create() and, to the best of my knowledge, that should work fine.

> And last not question - suggestion. Maybe CA library can be exist
> without this init level. When channel will be open CA library 
> will init in first time, attach in other thread and so on.

What you are asking for is already partly true. That is, if you call a
ca_xxx() function without calling ca_create_context() then the library will
do an implicit ca_create_context(ca_disable_preemptive_callback). A
non-preemptive callback context is created by default for backwards
compatibility and also because novice programs expect that type of execution
environment.

The second part of your request, which I interpret to be asking that the
ca_attach_context() step also be implicit, is not done by design so we can
make the default be to allow multiple implicit non-preemptive CA client
contexts in the same process. My inclination is to make the non-preemptive
execution environment the default because preemptive execution is typically
used by experts that have experience using mutex locks to make a reliable
multithreaded program. Also, to allow user created threads to join into a CA
context the application programmer must somehow specify which threads will
be allowed to participate in which CA contexts (assuming that there will be
more than one of them in a single process).

> 
> 2. ca_pend_io and ca_pend_event.
> I have asked this question. But I continue misunderstanding ...
> When I use ca_enable_preemptive_callback that CA library open its
> thread.
> So CA library has its CPU time. What background activities should CA
> library do in CPU time of other threads?
> 
> 3. Some time ago I understood that I open channel to PV's field. 

CA channels form a virtual circuit between a process variable (PV) and a
client side application program. It is possible to connect a wide variety of
data sources into EPICS using the CA server library. When a CA channel
communicates with an EPICS Input Output Controller (IOC) then a field is a
specialization of a PV, and an EPICS record is a plug compatible function
block that contains fields, and the meta data below frequently are mapped
onto specific fields within the EPICS records by the EPICS record support
(see the EPICS Application Developer Guide).

> PV's field has type, count, reading/writing access, host name 
> (why not IOC name?).

In the past there was only one IOC per host and so the host name and the IOC
name were always the same. With R3.14 it's possible to have multiple IOCs on
the same host so this is more complicated. The short answer is that the CA
client currently knows only the IP address and the port number of the server
(IOC). The IP address can be converted to a host name. I suppose that, when
configuring an IOC, the EPICS application developer might use a new facility
which specifies the IOC name, and this could be passed up to the CA client
library interface, but that has not been considered as of yet. We are
interested in your thoughts on this matter (why it is needed - how it would
be used etc).

> But what about timestamp? Is it only to VAL field?

You can ask for the time stamp, alarm status, limits, units, and other meta
data associated with a field by requesting different DBR_XXX types. The
range of data types supported is documented in the R3.14.4 CA reference
manual and also in db_access.h. Typically, in an EPICS IOC context the time
stamp is obtained from the timestamp field in the record which is updated
when the record is processed. The time stamp is usually the time that the
record was processed or the time that the value field was acquired by the
hardware.

> 2. ca_pend_io and ca_pend_event.
> When I use ca_enable_preemptive_callback that CA library open 
> its thread. 

Actually, the library employs threads in both modes (in preemptive-callback
mode and also in non-preemptive-callback mode). The difference is that the
callbacks are controlled to occur only when the initializing (main) thread
is executing inside of the CA library in non-preemptive-callback mode.
Otherwise in preemptive-callback-mode the callbacks may occur at any time,
and you must protect your program with mutex locks.

> So CA library has its CPU time. What background 
> activities should CA library do in CPU time of other threads?

With respect to ca_pend_io:
The ca_pend_io() function flushes the output queue and then it blocks until
non-completion-callback get requests have completed. This function also
blocks until non-connection-callback channel create requests have connected
for the first time. Otherwise ca_pend_io() does nothing and returns. 

With respect to ca_pend_event:
The ca_pend_event() function flushes the output queue and then blocks for
the specified number of seconds. During that time the library will take care
of whatever it needs to take care of. In preemptive-callback mode the
function merely sleeps for the requested number of seconds and the library
does what it needs to do, on its own schedule, calling callbacks at any time
without any synchronization with your program. In contrast, in
non-preeemptive-callback mode, callbacks may only occur when you are in a
library function, and ca_pend_event() has been a convenient place for single
threaded applications to wait while CA client library background activities
are allowed to occur.

> 
> 4. And last question. What do client and server do when 
> connection lost?
> 
> I believe that they are waiting up to EPICS_CA_CONN_TWO time 
> and server is sending beacons. 

This is an oversimplification, but almost correct. The details are in the
R3.14.4 CA reference manual.

> But what is later? Does server clean resource of
> disconnection channel? 

Mostly no. 

Once you create a channel the client library will try to keep it connected
for you until you delete the channel. The client library will *not* delete
the channel for you. That is your responsibility and the timing of this is
your choice with ca_clear_channel().

The client library will also remember any monitor subscriptions entered
against the channel and make a subscription with the server whenever the
channel connects. The subscriptions are *not* destroyed when the channel
disconnects. The subscriptions *are* destroyed when you destroy the channel.

Any outstanding get callback, put callback, or sync group requests *are*
cleaned up (destroyed) when the channel disconnects.

> Why client can connect again if server was rebooted?

This is a necessary feature for client side applications in a distributed
process control system. Long lifespan programs like the sequencer, the
database links, the operator interface, the archiver, and many others need
this capability. The CA client library knows when the server has rebooted
and therefore when it is possible to reattach to it. 

It is possible to receive a callback from the CA client library when the
circuit reconnects.

The following are extracts from some revised sections of the manual.

----------------snip---------snip---------------

Thread Safety and Preemptive Callback to User Code

Starting with EPICS R3.14 the CA client libraries are fully thread safe on
all OS (in past releases the library was thread safe only on vxWorks). When
the client library is initialized the programmer may specify if preemptive
call back is enabled. Preemptive call back is disabled by default. If
preemptive call back is enabled then the user's call back functions might be
called by CA's auxiliary threads when the main initiating channel access
thread is not inside of a function in the channel access client library.
Otherwise, the user's call back functions will be called only when the main
initiating channel access thread is executing inside of the CA client
library. When the CA client library invokes a user's call back function it
will always wait for the current callback to complete prior to executing
another call back function. Programmers enabling preemptive callback should
be familiar with using mutex locks to create a reliable multi-threaded
program.
To set up a traditional single threaded client you will need code like this
(see ca_context_create and CA Client Contexts and Application Specific
Auxiliary Threads).
SEVCHK ( ca_context_create(ca_disable_preemptive_callback ), "application
pdq calling ca_context_create" );
To set up a preemptive callback enabled CA client context you will need code
like this (see ca_context_create and CA Client Contexts and Application
Specific Auxiliary Threads).
SEVCHK ( ca_context_create(ca_enable_preemptive_callback ), "application pdq
calling ca_context_create" );

CA Client Contexts and Application Specific Auxiliary Threads

It is often necessary for several CA client side tools running in the same
address space (process) to be independent of each other. For example, the
database CA links and the sequencer are designed to not use the same CA
client library threads, network circuits, and data structures. Each thread
that calls ca_context_create() for the first time either directly, or
implicitly when calling any CA library function for the first time, creates
a CA client library context. A CA client library context contains all of the
threads, network circuits, and data structures required to connect and
communicate with the channels that a CA client application has created. The
priority of auxiliary threads spawned by the CA client library are at fixed
offsets from the priority of the thread that called ca_context_create(). An
application specific auxiliary thread can join a CA context by calling
ca_attach_context() using the CA context identifier that was returned from
ca_current_context() when it is called by the thread that created the
context which needs to be joined. A context which is to be joined must be
created using ca_context_create(ca_enable_preemptive_callback). It is not
possible to attach a thread to a CA context created explicitly or implicitly
with ca_create_context(ca_disable_preemptive_callback). Once a thread has
joined with a CA context it need only make ordinary ca_xxxx() library calls
to use the context. There is no need to specify the context identifier when
invoking the CA library calls because the context identifier is stored in a
thread private variable by ca_attach_context().
A CA client library context can be shut down and cleaned up, after
destroying any channels or application specific threads that are attached to
it, by calling ca_context_destroy(). The context may be created and
destroyed by different threads as long as they are both part of the same
context.

Jeff



References:
CA questions Liyu, Andrei

Navigate by Date:
Prev: Question on newer MVME-177 Chestnut, Ronald P.
Next: RE: CA questions Liyu, Andrei
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  <20032004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: CA questions Liyu, Andrei
Next: RE: CA questions Liyu, Andrei
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  <20032004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 10 Aug 2010 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·