LCLS Controls

SLC-Aware IOC Design


 

Async Utilities Design

 

Quick links:

1.   Scope

This document describes the software design for the SLC-aware IOC Async Utilities. These utilities are for use by cstrAsync, cstrHdlr, and mgntHdlr.

2.   Introduction

2.1 Background

Job Global data (including slcJobFunc_as) in file scoped within the .c file containing these utilities. That data is protected by being accessible only by calling these utilities. Again, access to the global area by async handler threads is always through an Async utility.

 

Much of the functionality here is implemented for the SLC Micros in utilities whose source lives in REF_RMX_ASYNC.

The following table shows the names of Functions on the SLC RMX micros and the Functions on the SLC IOC which accomplish roughly the same functionality.

 

 

SLC Micro Function(s)

SLC IOC Function

ASYNCDBINIT
INIT_CYC_GLBCOM
CYCLE_INIT

slcAsyncInit

INIT_MICR_STS

cstHdlrInitMicrSts

GET_CYCLE_TIME

None

GET_CYCLE_FCN

slcAsyncGetCycleFcn

METER_DBSEND

slcAsyncMeterDbsend

PROC_MICR_STS

cstrHdlrProcMicrSts

LOCK_STATS

slcAsyncLockStats

UNLOCK_STATS

slcAsyncUnlockStats

SET_FCN_STATS

slcAsyncSetFcnStats

2.2 References

1.      SLC Asynch Database Update Design Spec by T Lahey, N Spencer 1989

2.      Improving Control of Auto-Checking Functions by T Lahey,N Spencer, R Hall 1990

2.3 Requirements

See the SLC-Aware IOC Functional Requirements by Stephanie Alison.

3.   Async Utilities Design

General sketch for all Async Handler Threads that perform cycling

This is the general pattern followed by All Async Handler Threads including (but not limited to) cstrHdlr and mgntHdlr.

Prior to an Async Handler thread running, slcAsyncInit() is called by cstrHdlr at it’s initialization time to set up the Async Global area once for all async Job/functions.

These are the calls that Async Handlers should make for handling cycling functions (Handlers may do other things like receiving VMS messages. Those things are not listed):

LOOP:

        If slcThreads_as[thisHdlr].stop ==epicsTrue, clean up and return.

        Receive an IOC_ASYNC message from cstrAsync which indicates the cycling function to perform. The function index and name is part of the message. The time of receipts is received as part of that call too.

        Call a local cycling function based on the name from the message. The cycling function returns dblputDone=epicsTrue if any dbupdates were done. It returns dblputDone=epicsFalse otherwise.

        Call slcAsyncMeterDbSend(funcIx, requestType=slcAsync, dblputDone). This is called whether or not the cycling function did any dblputs. It does dbupdate() if needed.

        Call slcAsyncSetFcnStats(funcIx, epicsTime, requestType=slcAsync) to update CSTR related statistics in job global.

Exists Flag and Mutex Used by Async Tasks

1.      Boolean flags.

 

        asyncExists is a flag in file scope. It is set to False by the executive before cstrAsync is run using an slcAsync utility function.

 

At the end of it’s processing, slcAsyncInit() sets the asyncExists flag to True to indicate that the slcJobFunc global table creation is complete. If slcAsyncInit fails, it sets the asyncExists flag to “false.

 

Public slcAsync utilities check if the async global area has been set up successfully by calling slcAsyncReady() which checks the asyncExists.

 

slcAsyncExit() sets the asyncExists flag to “false”.

 

        The other flags of interest are the active and stopped flags in slcThread_as.

 

 

2.      Mutex

 

There is a single mutex (asyncRWMutex) which is used to protect access to the Global Data by utility functions which write to that area. The mutex insures that the utilites are thread-safe. slcAsyncLockStats() and slcAsyncUnlockStats() are utilities for use obtaining and releasing the mutex.

Message Logging

Messages to be logged are stated below under the individual utility descriptions.

Function Return Status

Most utilities return int unix-style status set to 0 (for success) or non-zero (for failure).

Resource Management

Writes to the SLC database will be metered in a manner similar to the SLC Micro Test Job by calling the utility function slcAsyncMeterDbsend().

Global Data

 

slcJobFunc_as is an array of structures in file scope, with one structure (array element) per cycling function across the entire IOC. Each Job may have zero or more cycling functions. The array is calloc'ed by slcAsyncInit() to have one entry per cycling function across the current slc ioc. The pointer to this array is static and file scoped.

 

slcJobFunc_as and the associated set of dblist pointers are often referred to as “Global Data” within this document. It is called “Job Global” to correspond with the SLC Micro code.


There is a file scoped Boolean flag called asyncExists and a mutex that both provide protected access to Job Global (see descriptions above).

 

It is important to note that in the CSTR database, all functions for a given Job must be grouped together (example: CSTR:micr:1,CNAM may NOT indicate a mixed grouping like this: KLYS-TRMP CRAT-WATC KLYS-FCHK...)
slcAsyncInit issues an error message and returns bad status if the functions are not all grouped together for all jobs.


Two new entries will be added to slcJob_ts.

        The first is "first cycling function index". This is an integer index into the array slcJobFunc_as. This integer is passed to async functions as an input argument.

        The second is "number of cycling functions". This is also an integer.

 

The following table describes the association between slcJob_as and slcJobFunc_as.



 

 

Async Utilities below look at all cycling functions for a given job.
That is done by looking in slcJobs_as[jobEnum] for the current job, and picking up the first cycle function index and number_of_functions. Those two values are used to inspect the slcJobFunc_as and associated arrays of secondary values.

The following structure is slcJobFunc_ts. To the right is the initial value for each element as set by slcAsyncInit.

INITIAL VALUE

--------------

/* Async cycling function information */

typedef struct {

slcJob_te slcJobId_e; /* enum into slcJob_as for this job */ COMPUTED based on CNAM

char funcName_c[5]; /* null terminated 4-character func name */ READ FROM CSTR:CNAM

unsigned long cyclTimeSec; /* cycle time from CSTR:CYCL */ READ FROM CSTR:CYCL

unsigned long mtrlSec; /* dpupdate meter length in seconds */ READ FROM CSTR:MTRL

unsigned long mtrcSec; /* dbupdate meter max # dbupdates in mrtl */ READ FROM CSTR:MTRC

unsigned long mtrtSec; /* dbupdate meter max time between dbupdates */ READ FROM CSTR:MTRT

epicsTimeStamp meterStartTime_s; /* time metering started */ current time

unsigned long meterCount; /* metering counter */ 0

vmsStat_t lastDbupdateStatus; /* last database update status */ DB_OKOK

epicsTimeStamp updateTimeStamp_s; /* timestamp of last dbupdate */ current time

epicsTimeStamp cycleTimeStamp_s; /* last time this cycl function was executed */ current time

float betweenCycle; /* time between last 2 cycles */ 0.0

unsigned long numFuncExe; /* total # function executions in calc interval */ 0

unsigned long numVmsMsg; /* # of function executions from vms msg interv */ 0

unsigned long numDbUpdates; /* # of dbupdates (for metering and %) interval */ 0

unsigned long numDbUpdateFail; /* # of dbupdates that failed in calc interval */ 0

epicsTimeStamp sendTimeStamp_s; /* NEW time when last msg sent attempt by cstr to hdlr */ current time

unsigned long sendErrCount; /* NEW number of failures in sending to hdlr. Not zeroed except at init. */ 0

} slcJobFunc_ts;

Diagnostics

Write Async job/function table for an input job name (can be ALL*) to the console.

Provide a way for the user to change a subset of cycling parameters for a job/function pair. Use utilities slcAsyncSetXXXX described below to set them. They must lock the global area before writing it.

        One utility will zero the sendErrCount in job global so the user can track send failures.

 

Async Utility Function descriptions

The Async utilities all exist in a single file called libsrc/util/slcAsync.c. Prototypes are in slcAsync.h

Utilities are thread-safe. This is accomplished by using a single mutex to protect access to the global data.

It is necessary to restart the SLC IOC in order to add a new cycling function. But, all other cycling parameters (besides CNAM) from the database like CYCL and MTRx are kept in job global and used by Async utilities. Every time those parameters are used, they are read from Job Global. Thus, for an existing cycling function, those items are changeable from the ioc console.

 

        int slcAsyncInit(void)


Called by cstrAsync at initialization time to set up the Async Global area before any Handler threads are run. If slcAsyncInit returns bad status, cstrAsync exits. The global area is actually a job/function called slcJobFunc_as in file scope (see above for more on this table). slcAsyncInit is not called from anywhere else.

slcAsyncInit corresponds to several functions on the slc micros as shown in the table above.

slcAsyncInit returns 0 if successful. It returns -1 (error) if there are errors returned by memory allocation, database calls, or the CSTR data fetched from the SLC database.

Call slcAsyncInitVerify() to get cycling parameters from the database, check them, and allocate/initialize slcJobFunc_as. If it returns bad status, goto egresss and do the flag processing at the end of this function which will cause us to return bad status and cause the thread to exit..

Allocate the mutex (asyncRWMutex_ps) for use in accessing the Global Area by calling epicsMutexCreate

 

If everything above went OK,

Set asyncExists local flag to “true” using slcAsyncSetAsyncExists(epicsTrue);.

 

 

        int slcAsyncInitVerify(void)

Get cycling parameters from the database, check them, and allocate/initialize slcJobFunc_as for all job/functions.

Return 0 for success, -1 for failure.

A failure is considered fatal and the caller should cause cleanup and exit to occur. Any of the following cases (and probably more) are considered fatal.

        Invalid job name in CNAM

        Invalid ordering in CNAM

        Any error from any db utility.

        Any error from getting the mutex. Or memory allocation error.

        Sizes of dblists and dbdatas are not as expected.

        Problem initializing a timestamp

This is a static function (called only by another function within this .c file).

The following secondaries values are read (one time only) from the CSTR SLC database primary.

Call dblistalloc(), dblist() and then dblget(CSTR,[this_micro],1,SECN) which, in one call (per secondary) returns lists (arrays) of each value of size SLC_MAX_N_ASYN. Calloc slcJobFunc_as based on how many functions are in the CNAM list. These are the secondaries obtained from the database:

                     CNAM - contains Job Name and Cycle Function.

                     CYCL - is the cycle length in seconds.

                     MTRL, MTRC, and MAXT - database write metering parameters.

If any of the DB calls fail, then return bad status.

Loop through the dblists and do the following steps

1.      As explained above, the slcJobFunc_as array is calloc'ed by this function to have one entry per cycling function across the current slc ioc.. Cycling functions for a given Job are grouped together in slcJobFunc_as Check that the job name in CNAM is valid and matches a job name in the slcJob_ts array. Log a fatal error if there's no match and break out of loop.

2.      Store CNAM (job and function) into slcJobFunc_as. Compute the index to slcJob_as for each functions job and store it in slcJobFunc_as[].slcJobEnum.

3.      Check CYCL, MTRC, MTRL, MAXT (dblist/dblget was already done ),
against reasonable limits. Any value which is outside reasonable limits is reset to an appropriate default (see the supertype I table in the requirements doc for defaults). Store values in slcJobFunc_as using the slcAsyncSetXXX() functions below (for example call slcAsyncSetCYCL()). Log a message if the values are set to defaults stating DB value and default it was set to. Return good status in that case.

4.      Increment function counter in slcJob_as for this job. Set function index in slcJob_as if first function for job.

Call dbListFree() to free the one-time use lists obtained above for all the DB lists.

Call dblistalloc() and dblist() to get MMSK, CMSK, HSTA, FMSK, and SCAN Supertype II lists. Don’t do dblget() yet. That will be done by slcAsyncUpdSt2() which is called by the main thread right after slcAsyncInit().

 

        int slcAsyncGetCycleFcn (int 1stCycleFuncIx, int numCycleFunc, int* cycl2Exe, char * cycl2ExeName_c, epicsTimeStamp currentTime_s);

This is a public function called by cstrAsync. It returns (in cycl2Exe and cycl2ExeName_c) the slcJobFuncIx (index and name) of the cycling function which is “most ready to run” for the current job. It does this by going through all entries in Job Global for the current job as indicated by 1stCycleFuncIx and numCycleFunc. If one is not found, then -1 is returned in cycl2Exe.

Call slcAsyncReady() and return 0 if it returns 0.

Get current time by calling eicsTimeGetCurrent() and set into output parameter currentTime_s. Return if error.

Call slcAsyncLockStats() to get a mutex on the Global Area. Return if it returns an error.

Go through entries in slcJobFunc_as (using the input arguments to index it) and see if there an async function for this job that is ready to run based on current time, CSTR: CTIM, CYCL, SCAN, HSTA, CMSK, and MMSK. Return an indication as to which of these async functions is “most ready to run” to the caller in cycl2Exe and cycl2ExeName_c.

For a cycling function to be ready to run, the following conditions must be true.

         Cycling time (slcJobFunc_as[].cyclTimeSec) must be > 0

         Current_time last_execution_time > cycling_period

         Current_time time_of_last_msg_send > cycling_period (don’t keep trying if q full)

         The cycling_period is either CYCL or SCAN, if the bit for the function is set in MMSK and SCAN is less than CYCL.

         The function must be enabled as determined by checking the appropriate bit in CMSK.

         HSTA is only checked for the magnet job. The TEST job is not HSTA’able. The magnet job must be enabled as determined by checking the appropriate bit in HSTA. Note: because there is no direct correspondence between CycleFuncIx (input parameters) and HSTA, it will be necessary to use a hard codeed mask to know which Bit to check in HSTA.

Egress: Call slcAsyncUnlockStats() to release the mutex on the Global Area.

 

        void slcAsyncSetCYCL (jobFuncIx, value)

set CYCL in slcJobFunc_as[jobFuncIx] to the value passed in.

Check for valid values. And use default if needed. Defaults listed in requirements document.

        void slcAsyncSetMTRC (jobFuncIx, value)

set MTRC in slcJobFunc_as[jobFuncIx] to the value passed in.

Check for valid values. And use default if needed. Defaults listed in requirements document.

        void slcAsyncSetMTRL (jobFuncIx, value)

set MTRL in slcJobFunc_as[jobFuncIx] to the value passed in.

Check for valid values. And use default if needed. Defaults listed in requirements document.

        void slcAsyncSetMAXT (jobFuncIx, value)

    1. set MAXT in slcJobFunc_as[jobFuncIx] to the value passed in.
    2. Check for valid values. And use default if needed. Defaults listed in requirements document.

 

        int slcAsyncProcChk1(CTIMdblist_ps, CTIMdbdata_ps, UTIMdblist_ps, UTIMdbdata_ps, ELPSdblist_ps, ELPSdbdata_ps )

This is a public function called by cstrHdlr only. It processes UTIM, CTIM, and ELPS.

These secondaries are always sent (updated) without checking if they changed because UTIM and CTIM change when this function runs.

Call slcAsyncReady() and return if it returns an error.

Call slcAsyncLockStats() to get a mutex on the Global Area. Return if it returns an error.
For each cycling function in the Global Area do the following and dblput the data:

Put the last database update time from Global into the UTIM dblist.
Put the last cycling function update time from Global into the CTIM dblist.
Put elapsed time from Global in the ELPS dblist.

Timestamps are converted to VMS format using timeEpicsToVms() before putting them into the slc database.

cstrHdlr will do the dbupdate.
Call slcAsyncUnlockStats() to release the mutex on the Global Area.

Any failures in the calls above logic cause a -1 (error) return status. Otherwise 0 is returned (success).

        int slcAsyncProcChk2(NRUNdblist_ps, NRUNdbdata_ps, FAILdblist_ps, FAILdbdata_ps, PUPDdblist_ps, PUPDbdata_ps, PVAXdblist_ps, PVAXdbdata_ps, epicsBoolean * dbUpdateNeeded_ps)

This is a public function called by cstrHdlr only. It processes NRUN, FAIL, PVAX, and PUPD.

dbUpdateNeeded is an output parameter.

Call slcAsyncReady() and return if it returns an error.

Call slcAsyncLockStats() to get a mutex on the Global Area.


For each cycling function in the Global Area:

If Number of Executions (NRUN) has changed in Global vs what’s in the previous used dblist, put the new value from Global into the NRUN dblist and set dbUpdateNeeded flag that something changed

 

If number of failures (FAIL) has changed in Global vs what’s in the previous used dblist, put the new value from Global into the FAIL dblist and set dbUpdateNeeded flag that something changed.


Calculate Percent executions triggered by Vax Messages (PVAX). If it has changed, store it in the PVAX dblist and set flag.

 Calculate Percent executions triggering successful database updates (PUPD). If it has changed, store it in the PUPD dblist and set flag.

Do dblputs as needed for data listed above.

Zero the counters for NRUN, FAIL, DBUPDATES, and VAXFUNCS in global.
Call slcAsyncUnlockStats() to release the mutex on the Global Area.

Any failures in the calls above logic cause a -1 (error) return status. Otherwise 0 is returned (success).

        int slcAsyncUpdSt2(void )

This is a static function (called only by another function within this .c file).

Call slcAsyncReady() and return error if not ready.

Call slcAsyncLockStats() to get a mutex on the Global Area. Return and error if it returns an error.

Get MMSK, CMSK, HSTA, FMSK and SCAN from database using dblget()

Pointers to the dblget lists are already set up in file scope.

Return -1 if a dblget fails. Return 0 for success.

Call slcAsyncUnlockStats() to release the mutex on the Global Area. Return an error if it returns an error.

 

        epicsBoolean slcAsyncReady(void )

This is a static function. It returns epicsTrue for success. epicsFalse for an error.

slcAsync utilities check if the async global area has been set up successfully and is available by calling this function.

 

This function Simply returns the value of asyncExists flag by using the public accessor function slcAsyncGetAsyncExists.

 

 

        int slcAsyncSetSendStats(int asyncFuncIx, vmsStat Status, epicsTimeStamp currentTime_s);

         asyncFuncIx is an input parameter indicating the index in slcJobFunc_as for the check function.

         status is an input parameter indicating the message send status.

         currentTime_s is an input parameter indicating current time of day.

 

This is a public function called by cstrAsyncSendFuncMsg.

It updates message send statistics in async job global.

It returns -1 for success and 0 for failure.

 

For the given check function, increment send failed counter for msgs sent from cstrAsync to the handler.

Set last send timestamp in job global.

 

1.       Lock Job Global

2.       If status indicates failure

a.              Increment send error counter (sendErrCount ) in job global. This is not zeroed on success.

3.       Update send timestamp (sendErrCount) in job global. This is set for both success and failure.

4.       Unlock Job Global.

 

 



        int slcAsyncMeterDbsend (funcIx, requestType, epicsBoolean dblputDone).

         asyncFuncIx is an input parameter indicating the index in slcJobFunc_as for the check function which needs to be checked to see if a dbupdate needs to be done. NOTE: It is not necessary for the caller to pass jobId, since that can be obtained here from slcJobFunc_as[asyncFuncIx].slcJobIx.

         requestType is an input parameter indicating if the call is as a result of an async update or message from vms

         dblputDone is an input parameter indicating if prevous processing (like a check function) did a dlbput and therefore this function needs to do a dbupdate().

 

This is a public function for use by all async threads. It does a dbupdate for a given async function if it’s time to do so. Dbupdate() actually updates the whole job, not just one async function’s data..

 

There are entries in slcJobFunc_ts (listed above) for keeping track of metering. They include:

                           epicsTimeStamp meterStartTime; /* time metering started*/

                           int meterCount; /* metering counter*/

                           vmsstat_t lastDbupdateStatus; /* last database update status */

 

The first thing it does is to call slcAsyncReady() to verify that the global area to be ready to be accessed. If it returns an error, return with error from here.

Get current time for use in time calculations below (and for passing to slcAsyncSetDbStats) using epicsTimeGetCurrent(). Return from here is there is an error.

Call slcAsyncLockStats(). Return from here is if there is an error.

Check the following items (many of them in async job global) to see if a dbupdate() needs to be done. But, don’t do the dbupdate() until after calling slcAsyncUnlockStat() below.

                     Do an update if the last Alpha update request for this job/function failed.

                     Do an update if no update has happened in the last MAXT seconds.

                     Do an update if the requestType is not ASYNC.

                     Do an update if dblputDone is true and the number of successful database updates is less than the allowed number (MTRC) in the last MTRL seconds.

                     Do an update if the bit for the function is set in FMSK.

Note: in the case the dbupate() fails, we will be passing an indication of that to slcAsyncSetDbStat() below which will take appropriate action.

Call slcAsyncUnlockStats(). Return from here is if there is an error.

Call dbupdate now if required

Note: It is not necessary to process OMSK as is done on the slc micros. That functionality was never implemented.

Call local function slcAsyncSetDbStats(asyncFuncIx…) to update database related statistics (like database update counters) in the slcJobFunc_as array for the input function only if dbupdate() was attempted above or dblputDone is true. Return from here is there is an error. TBD*** What is passed to slcAsyncSetDbStats() if metering is in effect **TBD

 

        int slcAsyncSetDbStats(int asyncFucnIx, epicsBoolean metered, epicsBoolean MeterJustStarted, vmsStat_t dbUpdateStatus, epicsTime currentTime)

                asyncFuncIx is an input parameter indicating the index in slcJobFunc_as for the check function for which Stats are being set.

                Metered is an input parameter indicating if the last call was metered.

                MeterJustStarted is an input parameter indicating if metering just started (0 if dbupdate failed).

                dbUpdateStatus is an input parameter status code indicating the status of the last dbupdate() call. **TBD** What is this set to if metering is in effect?? I don’t think it matters because we don’t store it below if metered.

                currentTime is an input parameter of current time of day.

 

This function is only called by slcAsyncMeterDbsend. It is a static function and returns 0 for success -1 for failure.

Call slcAsyncLockStats() to lock the global area. Return from here if there is an error.

 

Update the following items in the slcJobFunc_as array for the input job and function:

 

                Metering-started timestamp is set to current time input parameter if metering has just started.

                Increment the metering counter if metering is in effect.

                Increment either the database-update-failed counter or database-update-success counter for this job/function depending on dbUpdateStatus if metering is not in effect.

                Set the last-database-update timestamp to current time input parameter if the dbUpdateStatus is good. **TBD** Do this if metered?

                Set the last-database-update status to dbUpdateStatus input parameter. Don’t do this if metering is in effect.

 

Call slcAsyncUnlockStats() to unlock the global area. Return from here is there is an error.

 

 

        int slcAsyncLockStats(void).

First, call slcAsyncReady() to make sure global is available. If not, log a cmlog message and return bad status from here.

This public function calls epicsMutexLock(id) to take out mutex on Global Area.

This function returns 0 for success. -1 for failure.

Note: That call blocks until the lock is available or an error occurs. If the call fails, an error message is logged and bad status is returned.

 

        int slcAsyncUnlockStats(void).

First, call slcAsyncReady() to make sure global is available. If not, log a cmlog message and return bad status from here.

This function returns 0 for success. -1 for failure. The only possible failure is global not ready.

This public function calls epicsMutexUnlock(id) to release mutex on Global Area. That call returns void.

 

        int slcAsyncSetFcnStats(int asyncFuncIx, epicsTimeStamp *startTime_ps, requestType).

1.      asyncFuncIx is an input parameter that is an index to slcJobFunc_as indicating which async function this request is for.

2.      start_time is an input parameter
Passed by the caller so that the ELPS (elapsed) time can be calculated (current time - start_time (which is the time right before the function was executed)).

3.      requestType is an input argument slcReqType_te enum indicating slcAsync or slcMsg.
It indicates if this is as a result of a vms message request or an async request.
It's an enum with two possible values: slcAsync or slcMsg.

This is a public function for use by all async threads.

It sets statistics in the Global Area for the specified cycling function.

Input startTime is the time right before function began and is set by caller (used as start time in calculating func execution elapsed time (ELPS)).

The first thing it does is to call slcAsyncReady() to verify that the global area is ready to be accessed. If it returns an error, return with error from here.

Call epicsTimeGetCurrent() to get current time to be end time for ELPS calculation. Return if error.

Call slcAsyncLockStats() to take out mutex on Global Area. If it returns an error, return with error from here.

Calculate elapsed time (ELPS) and store in Global Area

Store current time into in Global Area for this function (set last execution time to current time).

Increment NRUNS (execution counter) in Global Area for this function.

If slcRequestType indicates the call is from a Handler as a result of VMS message (slcMsg), then, increment number of hdlr functions in last calculation interval (and calculate PVAX).

If slcRequestType indicates the call is from a Handler as a result of Async call (slcAsync), then, increment number of async functions in last calculation interval.

Call slcAsyncUnlockStats() to release the mutex on the Global Area. Return if error.

 

        int slcAsyncDumpGlob(void)

This is a public function

Call slcAsyncReady(). Return if error.

Call slcAsyncLockStats(). Return if error.

Print all function tables for debugging if jobName_a is ALL*. Othewise, print the function table for the input job name (call slcGetJobIndexByName).

This function does not log messages to cmlog.

Call slcAsyncUnlockStats()

        void slcAsyncExit(void)

This is a public function called by cstrAsync at it’s cleanup time.

Call slcAsyncLockStats()

 

Set asyncExists global flag to false.

 

Zero the number of async functions and the first function index in the slcJob_as array for all jobs.

 

All resources allocated by Async Utilites are deallocated here. This includes memory (eg slcJobFunc_as) and dblists (call dbfree).

Call dblistfree() to free MMSK, CMSK, HSTA, FMSK, and SCAN Supertype II lists.

 

 

Get rid of mutex like this:

1.        Save the mutex ID locally.

2.        Null the mutex by setting file scope pointer to null

3.        Call slcAsyncUnlockStats(). Ignore any return status

4.        Call epicsMutexDestroy(localCopyOfMutex). Ignore any return status.

 

 


SLC-Aware IOC Home Page | LCLS Controls | EPICS at SLAC | SLAC Computing | SLAC Networking | SLAC Home

Contact: Ron MacKenzie,
Last Modified: May 11, 2005. by RONM.