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
1=== modified file 'tex/generalPurposeTasks.tex'
2--- tex/generalPurposeTasks.tex 2010-11-15 18:16:16 +0000
3+++ tex/generalPurposeTasks.tex 2013-05-17 16:29:29 +0000
4@@ -24,14 +24,17 @@
5
6 \subsection{Overview}
7
8-EPICS provides three general purpose IOC callback tasks. The only difference between the tasks is their scheduling
9-priority; low, medium or high. The low priority task runs at a priority just higher than Channel Access, the medium at a
10-priority about equal to the median of the periodic scan tasks, and the high at a priority higher than the event scan task. The
11+EPICS provides three sets of general purpose IOC callback tasks. The only difference between the task sets is their scheduling
12+priority: low, medium or high. The low priority tasks runs at a priority just higher than Channel Access, the medium priority tasks at a
13+priority 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
14 callback tasks are available for any software component that needs a task under which to run some job either immediately
15-or after some delay. Jobs can also be cancelled during their delay period. The three callback tasks register themselves with
16+or after some delay. Jobs can also be cancelled during their delay period. The callback tasks register themselves with
17 the task watchdog (described below). They are created with a generous amount of stack space and can thus be used for
18 invoking record processing. For example the I/O event scanner uses the general purpose callback tasks.
19
20+The number of general purpose threads per priority level is configurable.
21+On 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.
22+
23 The following steps must be taken in order to use the general purpose callback tasks:
24
25 \begin{enumerate}
26@@ -250,6 +253,23 @@
27 int callbackSetQueueSize(int size)
28 \end{verbatim}
29
30+\subsection{Parallel Callback Tasks}
31+\label{Parallel Callback Tasks}
32+
33+To enable multiple parallel callback tasks, and set the number of tasks to be started for each priority level, call
34+\verb|callbackParallelThreads| before \verb|iocInit| in the startup file. The syntax is:
35+
36+\index{callbackParallelThreads}
37+\begin{verbatim}
38+int callbackParallelThreads(int count, const char *prio)
39+\end{verbatim}
40+
41+The 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.
42+
43+The prio argument specifies the priority level, with "" (empty string), "*", or NULL indicating to apply the definition to all priority levels.
44+
45+The 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.
46+
47 \section{Task Watchdog}
48 \label{Task Watchdog}
49 \index{Task Watchdog}
50
51=== modified file 'tex/libCom.tex'
52--- tex/libCom.tex 2012-01-17 18:04:20 +0000
53+++ tex/libCom.tex 2013-05-17 16:29:29 +0000
54@@ -541,13 +541,24 @@
55 \index{ellFree2}
56 \index{ellFree}
57 \index{ellVerify}
58+
59+
60 \section{epicsRingBytes}
61
62-\verb|epicsRingBytes.h| contains
63+\index{epicsRingBytes}
64+\index{epicsRingBytes.h}
65+\verb|epicsRingBytes.h| describes a C facility for a commonly used type of ring buffer.
66+
67+\subsection{C interface}
68+
69+EpicsRingBytes provides methods for creating and using ring buffers (first in first out circular buffers) that store bytes.
70+The unlocked variant is designed so that one writer thread and one reader thread can access the ring simultaneously without requiring mutual exclusion.
71+The locked variant uses an epicsSpinLock, and works with any numbers of writer and reader threads.
72
73 \index{epicsRingBytes.h}
74 \begin{verbatim}
75 epicsRingBytesId epicsRingBytesCreate(int nbytes);
76+epicsRingBytesId epicsRingBytesLockedCreate(int nbytes);
77 void epicsRingBytesDelete(epicsRingBytesId id);
78 int epicsRingBytesGet(epicsRingBytesId id, char *value,int nbytes);
79 int epicsRingBytesPut(epicsRingBytesId id, char *value,int nbytes);
80@@ -561,6 +572,7 @@
81
82 \index{epicsRingBytesId}
83 \index{epicsRingBytesCreate}
84+\index{epicsRingBytesLockedCreate}
85 \index{epicsRingBytesDelete}
86 \index{epicsRingBytesGet}
87 \index{epicsRingBytesPut}
88@@ -575,6 +587,7 @@
89 \textbf{Method} & \textbf{Meaning}\\
90 \hline
91 epicsRingBytesCreate() & Create a new ring buffer of size nbytes. The returned epicsRingBytesId is passed to the other ring methods.\\
92+epicsRingBytesLockedCreate() & Same as epicsRingBytesCreate, but create the spin lock secured variant of the ring buffer.\\
93 epicsRingBytesDelete() & Delete the ring buffer and free any associated memory.\\
94 epicsRingBytesGet() & Move up to nbytes from the ring buffer to value. The number of bytes actually moved is returned.\\
95 epicsRingBytesPut() & 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.\\
96@@ -600,6 +613,7 @@
97
98 \end{itemize}
99
100+
101 \section{epicsRingPointer}
102
103 \index{epicsRingPointer}
104@@ -609,13 +623,14 @@
105 \subsection{C++ Interface}
106
107 EpicsRingPointer provides methods for creating and using ring buffers (first in first out circular buffers) that store pointers.
108-It is designed so that a writer thread and reader thread can access the ring simultaneously without requiring mutual exclusion.
109+The unlocked variant is designed so that one writer thread and one reader thread can access the ring simultaneously without requiring mutual exclusion.
110+The locked variant uses an epicsSpinLock, and works with any numbers of writer and reader threads.
111
112 \begin{verbatim}
113 template <class T>
114 class epicsRingPointer {
115 public:
116- epicsRingPointer(int size);
117+ epicsRingPointer(int size, bool locked);
118 ~epicsRingPointer();
119 bool push(T *p);
120 T* pop();
121@@ -654,21 +669,19 @@
122 \begin{longtable}{p{1.27778in}p{5.0in}}
123 \textbf{Method} & \textbf{Meaning}\\
124 \hline
125-epicsRingPointer() & Constructor. The size is the maximum number of elements (pointers) that can be stored in the ring.\\
126+epicsRingPointer() & 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.\\
127 \~{}epicsRingPointer() & Destructor.\\
128-push() & 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. \\
129-pop() & 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.\\
130-flush() & Remove all elements from the ring. If this operation is performed then all access to the ring should be locked.\\
131+push() & Push a new entry on the ring. It returns (false,true) is (failure, success). Failure means the ring was full.\\
132+pop() & Take a element off the ring. It returns 0 (null) if the ring was empty.\\
133+flush() & 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.\\
134 getFree() & Return the amount of empty space in the ring, i.e. how many additional elements it can hold.\\
135 getUsed() & Return the number of elements stored on the ring\\
136 getSize() & Return the size of the ring, i.e. the value of size specified when the ring was created.\\
137 isEmpty() & Returns true if the ring is empty, else false.\\
138 isFull() & Returns true if the ring is full, else false.
139 \end{longtable}
140-
141 \end{center}
142
143-
144 \subsection{C interface}
145
146 \index{ringPointerId}
147@@ -685,6 +698,7 @@
148 \begin{verbatim}
149 typedef void *epicsRingPointerId;
150 epicsRingPointerId epicsRingPointerCreate(int size);
151+ epicsRingPointerId epicsRingPointerLockedCreate(int size);
152 void epicsRingPointerDelete(epicsRingPointerId id);
153 /*epicsRingPointerPop returns 0 if the ring was empty */
154 void * epicsRingPointerPop(epicsRingPointerId id) ;
155@@ -700,6 +714,9 @@
156
157 Each C function corresponds to one of the C++ methods.
158
159+epicsRingPointerCreate() creates the unsecured variant, epicsRingPointerLockedCreate() creates the spin lock secured variant of the ring buffer.
160+
161+
162 \section{epicsTimer}
163
164 \index{epicsTimer}
165
166=== modified file 'tex/libComOsi.tex'
167--- tex/libComOsi.tex 2013-05-17 16:29:29 +0000
168+++ tex/libComOsi.tex 2013-05-17 16:29:29 +0000
169@@ -841,6 +841,49 @@
170
171 A posix version is implemented via pthreads.
172
173+
174+\section{epicsSpin}
175+
176+\index{epicsSpin}
177+\index{epicsSpin.h}
178+\verb|epicsSpin.h| contains definitions for a spin lock semaphore.
179+
180+\subsection{C Interface}
181+
182+\begin{verbatim}
183+typedef struct epicsSpin *epicsSpinId;
184+
185+epicsSpinId epicsSpinCreate();
186+void epicsSpinDestroy(epicsSpinId);
187+
188+void epicsSpinLock(epicsSpinId);
189+int epicsSpinTryLock(epicsSpinId);
190+void epicsSpinUnlock(epicsSpinId);
191+\end{verbatim}
192+
193+\index{epicsSpinId}
194+\index{epicsSpinCreate}
195+\index{epicsSpinDestroy}
196+\index{epicsSpinLock}
197+\index{epicsSpinTryLock}
198+\index{epicsSpinUnlock}
199+\begin{center}
200+\begin{longtable}{p{1.38889in}p{5.0in}}
201+\textbf{Method} & \textbf{Meaning}\\
202+\hline
203+epicsSpinCreate & Create a spin lock, allocate required resources, and initialize it to an unlocked state.\\
204+epicsSpinDestroy() & 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.\\
205+epicsSpinLock() & 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.\\
206+epicsSpinTryLock() & 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.\\
207+epicsSpinUnlock() & 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.\\
208+\end{longtable}
209+\end{center}
210+
211+\subsection{Implementation Notes}
212+
213+The default implementation uses POSIX spin locks on POSIX compliant systems, and epicsMutex for non-POSIX environments.
214+
215+
216 \section{epicsStdlib}
217
218 \index{epicsStdlib}
219@@ -864,7 +907,6 @@
220 They are provided because some architectures have implementations of scanf which do not accept NAN or INFINITY.
221
222
223-
224 \section{epicsStdio}
225
226 \index{epicsStdio}

Subscribers

People subscribed via source and target branches

to all changes: