Merge lp:~epics-documenters/epics-appdev/parallel-cbthreads into lp:~epics-documenters/epics-appdev/3.16

Proposed by Ralph Lange
Status: Merged
Merged at revision: 60
Proposed branch: lp:~epics-documenters/epics-appdev/parallel-cbthreads
Merge into: lp:~epics-documenters/epics-appdev/3.16
Prerequisite: lp:~epics-documenters/epics-appdev/get-cpus
Diff against target: 226 lines (+93/-14)
3 files modified
tex/generalPurposeTasks.tex (+24/-4)
tex/libCom.tex (+26/-9)
tex/libComOsi.tex (+43/-1)
To merge this branch: bzr merge lp:~epics-documenters/epics-appdev/parallel-cbthreads
Reviewer Review Type Date Requested Status
EPICS Documentation Team Pending
Review via email: mp+164449@code.launchpad.net

Description of the change

Documentation for parallel callback threads on multi-core (SMP) systems.
Includes spin locks and spin lock secured ring buffers.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'tex/generalPurposeTasks.tex'
--- tex/generalPurposeTasks.tex 2010-11-15 18:16:16 +0000
+++ tex/generalPurposeTasks.tex 2013-05-17 16:29:29 +0000
@@ -24,14 +24,17 @@
2424
25\subsection{Overview}25\subsection{Overview}
2626
27EPICS provides three general purpose IOC callback tasks. The only difference between the tasks is their scheduling 27EPICS provides three sets of general purpose IOC callback tasks. The only difference between the task sets is their scheduling
28priority; low, medium or high. The low priority task runs at a priority just higher than Channel Access, the medium at a 28priority: low, medium or high. The low priority tasks runs at a priority just higher than Channel Access, the medium priority tasks at a
29priority about equal to the median of the periodic scan tasks, and the high at a priority higher than the event scan task. The 29priority about equal to the median of the periodic scan tasks, and the high priority tasks at a priority higher than the event scan task. The
30callback tasks are available for any software component that needs a task under which to run some job either immediately 30callback tasks are available for any software component that needs a task under which to run some job either immediately
31or after some delay. Jobs can also be cancelled during their delay period. The three callback tasks register themselves with 31or after some delay. Jobs can also be cancelled during their delay period. The callback tasks register themselves with
32the task watchdog (described below). They are created with a generous amount of stack space and can thus be used for 32the task watchdog (described below). They are created with a generous amount of stack space and can thus be used for
33invoking record processing. For example the I/O event scanner uses the general purpose callback tasks.33invoking record processing. For example the I/O event scanner uses the general purpose callback tasks.
3434
35The number of general purpose threads per priority level is configurable.
36On SMP systems with multi-core CPUs, the throughput can be improved and the latency (time between job scheduling and processing) can be lowered by running multiple parallel callback tasks, which the OS scheduler may assign to different CPU cores. Parallel callback tasks must be explicitly enabled (see \ref{Parallel Callback Tasks} below), as this feature is disabled by default for compatibility reasons.
37
35The following steps must be taken in order to use the general purpose callback tasks: 38The following steps must be taken in order to use the general purpose callback tasks:
3639
37\begin{enumerate}40\begin{enumerate}
@@ -250,6 +253,23 @@
250int callbackSetQueueSize(int size)253int callbackSetQueueSize(int size)
251\end{verbatim}254\end{verbatim}
252255
256\subsection{Parallel Callback Tasks}
257\label{Parallel Callback Tasks}
258
259To enable multiple parallel callback tasks, and set the number of tasks to be started for each priority level, call
260\verb|callbackParallelThreads| before \verb|iocInit| in the startup file. The syntax is:
261
262\index{callbackParallelThreads}
263\begin{verbatim}
264int callbackParallelThreads(int count, const char *prio)
265\end{verbatim}
266
267The count argument is the number of tasks to start, with 0 indicating to use the default (number of CPUs), and negative numbers indicating to use the number of CPUs minus the specified amount.
268
269The prio argument specifies the priority level, with "" (empty string), "*", or NULL indicating to apply the definition to all priority levels.
270
271The default value is stored in the variable \verb|callbackParallelThreadsDefault| (initialized to the number of CPUs), which can be changed using the iocShell's \verb|var| command.
272
253\section{Task Watchdog}273\section{Task Watchdog}
254\label{Task Watchdog}274\label{Task Watchdog}
255\index{Task Watchdog}275\index{Task Watchdog}
256276
=== modified file 'tex/libCom.tex'
--- tex/libCom.tex 2012-01-17 18:04:20 +0000
+++ tex/libCom.tex 2013-05-17 16:29:29 +0000
@@ -541,13 +541,24 @@
541\index{ellFree2}541\index{ellFree2}
542\index{ellFree}542\index{ellFree}
543\index{ellVerify}543\index{ellVerify}
544
545
544\section{epicsRingBytes}546\section{epicsRingBytes}
545547
546\verb|epicsRingBytes.h| contains548\index{epicsRingBytes}
549\index{epicsRingBytes.h}
550\verb|epicsRingBytes.h| describes a C facility for a commonly used type of ring buffer.
551
552\subsection{C interface}
553
554EpicsRingBytes provides methods for creating and using ring buffers (first in first out circular buffers) that store bytes.
555The unlocked variant is designed so that one writer thread and one reader thread can access the ring simultaneously without requiring mutual exclusion.
556The locked variant uses an epicsSpinLock, and works with any numbers of writer and reader threads.
547557
548\index{epicsRingBytes.h}558\index{epicsRingBytes.h}
549\begin{verbatim}559\begin{verbatim}
550epicsRingBytesId epicsRingBytesCreate(int nbytes);560epicsRingBytesId epicsRingBytesCreate(int nbytes);
561epicsRingBytesId epicsRingBytesLockedCreate(int nbytes);
551void epicsRingBytesDelete(epicsRingBytesId id);562void epicsRingBytesDelete(epicsRingBytesId id);
552int epicsRingBytesGet(epicsRingBytesId id, char *value,int nbytes);563int epicsRingBytesGet(epicsRingBytesId id, char *value,int nbytes);
553int epicsRingBytesPut(epicsRingBytesId id, char *value,int nbytes);564int epicsRingBytesPut(epicsRingBytesId id, char *value,int nbytes);
@@ -561,6 +572,7 @@
561572
562\index{epicsRingBytesId}573\index{epicsRingBytesId}
563\index{epicsRingBytesCreate}574\index{epicsRingBytesCreate}
575\index{epicsRingBytesLockedCreate}
564\index{epicsRingBytesDelete}576\index{epicsRingBytesDelete}
565\index{epicsRingBytesGet}577\index{epicsRingBytesGet}
566\index{epicsRingBytesPut}578\index{epicsRingBytesPut}
@@ -575,6 +587,7 @@
575\textbf{Method} & \textbf{Meaning}\\587\textbf{Method} & \textbf{Meaning}\\
576\hline588\hline
577epicsRingBytesCreate() & Create a new ring buffer of size nbytes. The returned epicsRingBytesId is passed to the other ring methods.\\589epicsRingBytesCreate() & Create a new ring buffer of size nbytes. The returned epicsRingBytesId is passed to the other ring methods.\\
590epicsRingBytesLockedCreate() & Same as epicsRingBytesCreate, but create the spin lock secured variant of the ring buffer.\\
578epicsRingBytesDelete() & Delete the ring buffer and free any associated memory.\\591epicsRingBytesDelete() & Delete the ring buffer and free any associated memory.\\
579epicsRingBytesGet() & Move up to nbytes from the ring buffer to value. The number of bytes actually moved is returned.\\592epicsRingBytesGet() & Move up to nbytes from the ring buffer to value. The number of bytes actually moved is returned.\\
580epicsRingBytesPut() & Move nbytes from value to the ring buffer if there is enough free space available to hold them. The number of bytes actually moved is returned, which will be zero if insufficient space exists.\\593epicsRingBytesPut() & Move nbytes from value to the ring buffer if there is enough free space available to hold them. The number of bytes actually moved is returned, which will be zero if insufficient space exists.\\
@@ -600,6 +613,7 @@
600613
601\end{itemize}614\end{itemize}
602615
616
603\section{epicsRingPointer}617\section{epicsRingPointer}
604618
605\index{epicsRingPointer}619\index{epicsRingPointer}
@@ -609,13 +623,14 @@
609\subsection{C++ Interface}623\subsection{C++ Interface}
610624
611EpicsRingPointer provides methods for creating and using ring buffers (first in first out circular buffers) that store pointers.625EpicsRingPointer provides methods for creating and using ring buffers (first in first out circular buffers) that store pointers.
612It is designed so that a writer thread and reader thread can access the ring simultaneously without requiring mutual exclusion.626The unlocked variant is designed so that one writer thread and one reader thread can access the ring simultaneously without requiring mutual exclusion.
627The locked variant uses an epicsSpinLock, and works with any numbers of writer and reader threads.
613628
614\begin{verbatim}629\begin{verbatim}
615template <class T>630template <class T>
616class epicsRingPointer {631class epicsRingPointer {
617public:632public:
618 epicsRingPointer(int size);633 epicsRingPointer(int size, bool locked);
619 ~epicsRingPointer();634 ~epicsRingPointer();
620 bool push(T *p);635 bool push(T *p);
621 T* pop();636 T* pop();
@@ -654,21 +669,19 @@
654\begin{longtable}{p{1.27778in}p{5.0in}}669\begin{longtable}{p{1.27778in}p{5.0in}}
655\textbf{Method} & \textbf{Meaning}\\670\textbf{Method} & \textbf{Meaning}\\
656\hline671\hline
657epicsRingPointer() & Constructor. The size is the maximum number of elements (pointers) that can be stored in the ring.\\672epicsRingPointer() & Constructor. The size is the maximum number of elements (pointers) that can be stored in the ring. If locked is true, the spin lock secured variant is created.\\
658\~{}epicsRingPointer() & Destructor.\\673\~{}epicsRingPointer() & Destructor.\\
659push() & Push a new entry on the ring. It returns (false,true) is (failure, success). Failure means the ring was full. If a single writer is present it does not have to use a lock while performing the push. If multiple writers are present they must use a common lock while issuing the push. \\674push() & Push a new entry on the ring. It returns (false,true) is (failure, success). Failure means the ring was full.\\
660pop() & Take a element off the ring. It returns 0 (null) if the ring was empty. If a single reader is present it does not have to lock while issuing the pop. If multiple readers are present they must use a common lock while issuing the pop.\\675pop() & Take a element off the ring. It returns 0 (null) if the ring was empty.\\
661flush() & Remove all elements from the ring. If this operation is performed then all access to the ring should be locked.\\676flush() & Remove all elements from the ring. If this operation is performed on a ring buffer of the unsecured variant, all access to the ring should be locked.\\
662getFree() & Return the amount of empty space in the ring, i.e. how many additional elements it can hold.\\677getFree() & Return the amount of empty space in the ring, i.e. how many additional elements it can hold.\\
663getUsed() & Return the number of elements stored on the ring\\678getUsed() & Return the number of elements stored on the ring\\
664getSize() & Return the size of the ring, i.e. the value of size specified when the ring was created.\\679getSize() & Return the size of the ring, i.e. the value of size specified when the ring was created.\\
665isEmpty() & Returns true if the ring is empty, else false.\\680isEmpty() & Returns true if the ring is empty, else false.\\
666isFull() & Returns true if the ring is full, else false.681isFull() & Returns true if the ring is full, else false.
667\end{longtable}682\end{longtable}
668
669\end{center}683\end{center}
670684
671
672\subsection{C interface}685\subsection{C interface}
673686
674\index{ringPointerId}687\index{ringPointerId}
@@ -685,6 +698,7 @@
685\begin{verbatim}698\begin{verbatim}
686typedef void *epicsRingPointerId;699typedef void *epicsRingPointerId;
687 epicsRingPointerId epicsRingPointerCreate(int size);700 epicsRingPointerId epicsRingPointerCreate(int size);
701 epicsRingPointerId epicsRingPointerLockedCreate(int size);
688 void epicsRingPointerDelete(epicsRingPointerId id);702 void epicsRingPointerDelete(epicsRingPointerId id);
689 /*epicsRingPointerPop returns 0 if the ring was empty */703 /*epicsRingPointerPop returns 0 if the ring was empty */
690 void * epicsRingPointerPop(epicsRingPointerId id) ;704 void * epicsRingPointerPop(epicsRingPointerId id) ;
@@ -700,6 +714,9 @@
700714
701Each C function corresponds to one of the C++ methods.715Each C function corresponds to one of the C++ methods.
702716
717epicsRingPointerCreate() creates the unsecured variant, epicsRingPointerLockedCreate() creates the spin lock secured variant of the ring buffer.
718
719
703\section{epicsTimer}720\section{epicsTimer}
704721
705\index{epicsTimer}722\index{epicsTimer}
706723
=== modified file 'tex/libComOsi.tex'
--- tex/libComOsi.tex 2013-05-17 16:29:29 +0000
+++ tex/libComOsi.tex 2013-05-17 16:29:29 +0000
@@ -841,6 +841,49 @@
841841
842A posix version is implemented via pthreads.842A posix version is implemented via pthreads.
843843
844
845\section{epicsSpin}
846
847\index{epicsSpin}
848\index{epicsSpin.h}
849\verb|epicsSpin.h| contains definitions for a spin lock semaphore.
850
851\subsection{C Interface}
852
853\begin{verbatim}
854typedef struct epicsSpin *epicsSpinId;
855
856epicsSpinId epicsSpinCreate();
857void epicsSpinDestroy(epicsSpinId);
858
859void epicsSpinLock(epicsSpinId);
860int epicsSpinTryLock(epicsSpinId);
861void epicsSpinUnlock(epicsSpinId);
862\end{verbatim}
863
864\index{epicsSpinId}
865\index{epicsSpinCreate}
866\index{epicsSpinDestroy}
867\index{epicsSpinLock}
868\index{epicsSpinTryLock}
869\index{epicsSpinUnlock}
870\begin{center}
871\begin{longtable}{p{1.38889in}p{5.0in}}
872\textbf{Method} & \textbf{Meaning}\\
873\hline
874epicsSpinCreate & Create a spin lock, allocate required resources, and initialize it to an unlocked state.\\
875epicsSpinDestroy() & Remove the spin lock and any resources it uses. Any further use of the spin lock may result in unknown (most certainly bad) behavior. The results are also undefined if epicsSpinDestroy is used when a thread holds the lock.\\
876epicsSpinLock() & Wait (by spinning, i.e. busy waiting) until the resource is free. After a successful lock, no additional, i.e. recursive, locking attempts may be issued.\\
877epicsSpinTryLock() & Similar to lock except that, if the resource is owned by another thread, the call completes immediately. The return value is 0 if the resource is owned by the caller.\\
878epicsSpinUnlock() & Release the spin lock resource which was locked by epicsSpinLock or epicsSpinTryLock. The results are undefined if the lock is not held by the calling thread, or if epicsSpinUnlock is used on an uninitialized spin lock.\\
879\end{longtable}
880\end{center}
881
882\subsection{Implementation Notes}
883
884The default implementation uses POSIX spin locks on POSIX compliant systems, and epicsMutex for non-POSIX environments.
885
886
844\section{epicsStdlib}887\section{epicsStdlib}
845888
846\index{epicsStdlib}889\index{epicsStdlib}
@@ -864,7 +907,6 @@
864They are provided because some architectures have implementations of scanf which do not accept NAN or INFINITY.907They are provided because some architectures have implementations of scanf which do not accept NAN or INFINITY.
865908
866909
867
868\section{epicsStdio}910\section{epicsStdio}
869911
870\index{epicsStdio}912\index{epicsStdio}

Subscribers

People subscribed via source and target branches

to all changes: