Merge lp:~epics-documenters/epics-appdev/parallel-cbthreads into lp:~epics-documenters/epics-appdev/3.16
- parallel-cbthreads
- Merge into 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 |
| Related bugs: | |
| Related blueprints: |
Parallel Callback Threads
(High)
|
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| EPICS Documentation Team | Pending | ||
|
Review via email:
|
|||
Commit message
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 | 24 | 24 | ||
| 6 | 25 | \subsection{Overview} | 25 | \subsection{Overview} |
| 7 | 26 | 26 | ||
| 11 | 27 | EPICS provides three general purpose IOC callback tasks. The only difference between the tasks is their scheduling | 27 | EPICS provides three sets of general purpose IOC callback tasks. The only difference between the task sets is their scheduling |
| 12 | 28 | priority; low, medium or high. The low priority task runs at a priority just higher than Channel Access, the medium at a | 28 | 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 | 29 | priority about equal to the median of the periodic scan tasks, and the high at a priority higher than the event scan task. The | 29 | 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 | 30 | callback tasks are available for any software component that needs a task under which to run some job either immediately | 30 | callback tasks are available for any software component that needs a task under which to run some job either immediately |
| 16 | 31 | or after some delay. Jobs can also be cancelled during their delay period. The three callback tasks register themselves with | 31 | or after some delay. Jobs can also be cancelled during their delay period. The callback tasks register themselves with |
| 17 | 32 | the task watchdog (described below). They are created with a generous amount of stack space and can thus be used for | 32 | the task watchdog (described below). They are created with a generous amount of stack space and can thus be used for |
| 18 | 33 | invoking record processing. For example the I/O event scanner uses the general purpose callback tasks. | 33 | invoking record processing. For example the I/O event scanner uses the general purpose callback tasks. |
| 19 | 34 | 34 | ||
| 20 | 35 | The number of general purpose threads per priority level is configurable. | ||
| 21 | 36 | 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 | 37 | |||
| 23 | 35 | The following steps must be taken in order to use the general purpose callback tasks: | 38 | The following steps must be taken in order to use the general purpose callback tasks: |
| 24 | 36 | 39 | ||
| 25 | 37 | \begin{enumerate} | 40 | \begin{enumerate} |
| 26 | @@ -250,6 +253,23 @@ | |||
| 27 | 250 | int callbackSetQueueSize(int size) | 253 | int callbackSetQueueSize(int size) |
| 28 | 251 | \end{verbatim} | 254 | \end{verbatim} |
| 29 | 252 | 255 | ||
| 30 | 256 | \subsection{Parallel Callback Tasks} | ||
| 31 | 257 | \label{Parallel Callback Tasks} | ||
| 32 | 258 | |||
| 33 | 259 | To enable multiple parallel callback tasks, and set the number of tasks to be started for each priority level, call | ||
| 34 | 260 | \verb|callbackParallelThreads| before \verb|iocInit| in the startup file. The syntax is: | ||
| 35 | 261 | |||
| 36 | 262 | \index{callbackParallelThreads} | ||
| 37 | 263 | \begin{verbatim} | ||
| 38 | 264 | int callbackParallelThreads(int count, const char *prio) | ||
| 39 | 265 | \end{verbatim} | ||
| 40 | 266 | |||
| 41 | 267 | 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 | 268 | |||
| 43 | 269 | The prio argument specifies the priority level, with "" (empty string), "*", or NULL indicating to apply the definition to all priority levels. | ||
| 44 | 270 | |||
| 45 | 271 | 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 | 272 | |||
| 47 | 253 | \section{Task Watchdog} | 273 | \section{Task Watchdog} |
| 48 | 254 | \label{Task Watchdog} | 274 | \label{Task Watchdog} |
| 49 | 255 | \index{Task Watchdog} | 275 | \index{Task Watchdog} |
| 50 | 256 | 276 | ||
| 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 | 541 | \index{ellFree2} | 541 | \index{ellFree2} |
| 56 | 542 | \index{ellFree} | 542 | \index{ellFree} |
| 57 | 543 | \index{ellVerify} | 543 | \index{ellVerify} |
| 58 | 544 | |||
| 59 | 545 | |||
| 60 | 544 | \section{epicsRingBytes} | 546 | \section{epicsRingBytes} |
| 61 | 545 | 547 | ||
| 63 | 546 | \verb|epicsRingBytes.h| contains | 548 | \index{epicsRingBytes} |
| 64 | 549 | \index{epicsRingBytes.h} | ||
| 65 | 550 | \verb|epicsRingBytes.h| describes a C facility for a commonly used type of ring buffer. | ||
| 66 | 551 | |||
| 67 | 552 | \subsection{C interface} | ||
| 68 | 553 | |||
| 69 | 554 | EpicsRingBytes provides methods for creating and using ring buffers (first in first out circular buffers) that store bytes. | ||
| 70 | 555 | The unlocked variant is designed so that one writer thread and one reader thread can access the ring simultaneously without requiring mutual exclusion. | ||
| 71 | 556 | The locked variant uses an epicsSpinLock, and works with any numbers of writer and reader threads. | ||
| 72 | 547 | 557 | ||
| 73 | 548 | \index{epicsRingBytes.h} | 558 | \index{epicsRingBytes.h} |
| 74 | 549 | \begin{verbatim} | 559 | \begin{verbatim} |
| 75 | 550 | epicsRingBytesId epicsRingBytesCreate(int nbytes); | 560 | epicsRingBytesId epicsRingBytesCreate(int nbytes); |
| 76 | 561 | epicsRingBytesId epicsRingBytesLockedCreate(int nbytes); | ||
| 77 | 551 | void epicsRingBytesDelete(epicsRingBytesId id); | 562 | void epicsRingBytesDelete(epicsRingBytesId id); |
| 78 | 552 | int epicsRingBytesGet(epicsRingBytesId id, char *value,int nbytes); | 563 | int epicsRingBytesGet(epicsRingBytesId id, char *value,int nbytes); |
| 79 | 553 | int epicsRingBytesPut(epicsRingBytesId id, char *value,int nbytes); | 564 | int epicsRingBytesPut(epicsRingBytesId id, char *value,int nbytes); |
| 80 | @@ -561,6 +572,7 @@ | |||
| 81 | 561 | 572 | ||
| 82 | 562 | \index{epicsRingBytesId} | 573 | \index{epicsRingBytesId} |
| 83 | 563 | \index{epicsRingBytesCreate} | 574 | \index{epicsRingBytesCreate} |
| 84 | 575 | \index{epicsRingBytesLockedCreate} | ||
| 85 | 564 | \index{epicsRingBytesDelete} | 576 | \index{epicsRingBytesDelete} |
| 86 | 565 | \index{epicsRingBytesGet} | 577 | \index{epicsRingBytesGet} |
| 87 | 566 | \index{epicsRingBytesPut} | 578 | \index{epicsRingBytesPut} |
| 88 | @@ -575,6 +587,7 @@ | |||
| 89 | 575 | \textbf{Method} & \textbf{Meaning}\\ | 587 | \textbf{Method} & \textbf{Meaning}\\ |
| 90 | 576 | \hline | 588 | \hline |
| 91 | 577 | epicsRingBytesCreate() & Create a new ring buffer of size nbytes. The returned epicsRingBytesId is passed to the other ring methods.\\ | 589 | epicsRingBytesCreate() & Create a new ring buffer of size nbytes. The returned epicsRingBytesId is passed to the other ring methods.\\ |
| 92 | 590 | epicsRingBytesLockedCreate() & Same as epicsRingBytesCreate, but create the spin lock secured variant of the ring buffer.\\ | ||
| 93 | 578 | epicsRingBytesDelete() & Delete the ring buffer and free any associated memory.\\ | 591 | epicsRingBytesDelete() & Delete the ring buffer and free any associated memory.\\ |
| 94 | 579 | epicsRingBytesGet() & Move up to nbytes from the ring buffer to value. The number of bytes actually moved is returned.\\ | 592 | epicsRingBytesGet() & Move up to nbytes from the ring buffer to value. The number of bytes actually moved is returned.\\ |
| 95 | 580 | 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.\\ | 593 | 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 | 600 | 613 | ||
| 98 | 601 | \end{itemize} | 614 | \end{itemize} |
| 99 | 602 | 615 | ||
| 100 | 616 | |||
| 101 | 603 | \section{epicsRingPointer} | 617 | \section{epicsRingPointer} |
| 102 | 604 | 618 | ||
| 103 | 605 | \index{epicsRingPointer} | 619 | \index{epicsRingPointer} |
| 104 | @@ -609,13 +623,14 @@ | |||
| 105 | 609 | \subsection{C++ Interface} | 623 | \subsection{C++ Interface} |
| 106 | 610 | 624 | ||
| 107 | 611 | EpicsRingPointer provides methods for creating and using ring buffers (first in first out circular buffers) that store pointers. | 625 | EpicsRingPointer provides methods for creating and using ring buffers (first in first out circular buffers) that store pointers. |
| 109 | 612 | It is designed so that a writer thread and reader thread can access the ring simultaneously without requiring mutual exclusion. | 626 | The unlocked variant is designed so that one writer thread and one reader thread can access the ring simultaneously without requiring mutual exclusion. |
| 110 | 627 | The locked variant uses an epicsSpinLock, and works with any numbers of writer and reader threads. | ||
| 111 | 613 | 628 | ||
| 112 | 614 | \begin{verbatim} | 629 | \begin{verbatim} |
| 113 | 615 | template <class T> | 630 | template <class T> |
| 114 | 616 | class epicsRingPointer { | 631 | class epicsRingPointer { |
| 115 | 617 | public: | 632 | public: |
| 117 | 618 | epicsRingPointer(int size); | 633 | epicsRingPointer(int size, bool locked); |
| 118 | 619 | ~epicsRingPointer(); | 634 | ~epicsRingPointer(); |
| 119 | 620 | bool push(T *p); | 635 | bool push(T *p); |
| 120 | 621 | T* pop(); | 636 | T* pop(); |
| 121 | @@ -654,21 +669,19 @@ | |||
| 122 | 654 | \begin{longtable}{p{1.27778in}p{5.0in}} | 669 | \begin{longtable}{p{1.27778in}p{5.0in}} |
| 123 | 655 | \textbf{Method} & \textbf{Meaning}\\ | 670 | \textbf{Method} & \textbf{Meaning}\\ |
| 124 | 656 | \hline | 671 | \hline |
| 126 | 657 | epicsRingPointer() & Constructor. The size is the maximum number of elements (pointers) that can be stored in the ring.\\ | 672 | 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 | 658 | \~{}epicsRingPointer() & Destructor.\\ | 673 | \~{}epicsRingPointer() & Destructor.\\ |
| 131 | 659 | 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. \\ | 674 | push() & Push a new entry on the ring. It returns (false,true) is (failure, success). Failure means the ring was full.\\ |
| 132 | 660 | 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.\\ | 675 | pop() & Take a element off the ring. It returns 0 (null) if the ring was empty.\\ |
| 133 | 661 | flush() & Remove all elements from the ring. If this operation is performed then all access to the ring should be locked.\\ | 676 | 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 | 662 | getFree() & Return the amount of empty space in the ring, i.e. how many additional elements it can hold.\\ | 677 | getFree() & Return the amount of empty space in the ring, i.e. how many additional elements it can hold.\\ |
| 135 | 663 | getUsed() & Return the number of elements stored on the ring\\ | 678 | getUsed() & Return the number of elements stored on the ring\\ |
| 136 | 664 | getSize() & Return the size of the ring, i.e. the value of size specified when the ring was created.\\ | 679 | getSize() & Return the size of the ring, i.e. the value of size specified when the ring was created.\\ |
| 137 | 665 | isEmpty() & Returns true if the ring is empty, else false.\\ | 680 | isEmpty() & Returns true if the ring is empty, else false.\\ |
| 138 | 666 | isFull() & Returns true if the ring is full, else false. | 681 | isFull() & Returns true if the ring is full, else false. |
| 139 | 667 | \end{longtable} | 682 | \end{longtable} |
| 140 | 668 | |||
| 141 | 669 | \end{center} | 683 | \end{center} |
| 142 | 670 | 684 | ||
| 143 | 671 | |||
| 144 | 672 | \subsection{C interface} | 685 | \subsection{C interface} |
| 145 | 673 | 686 | ||
| 146 | 674 | \index{ringPointerId} | 687 | \index{ringPointerId} |
| 147 | @@ -685,6 +698,7 @@ | |||
| 148 | 685 | \begin{verbatim} | 698 | \begin{verbatim} |
| 149 | 686 | typedef void *epicsRingPointerId; | 699 | typedef void *epicsRingPointerId; |
| 150 | 687 | epicsRingPointerId epicsRingPointerCreate(int size); | 700 | epicsRingPointerId epicsRingPointerCreate(int size); |
| 151 | 701 | epicsRingPointerId epicsRingPointerLockedCreate(int size); | ||
| 152 | 688 | void epicsRingPointerDelete(epicsRingPointerId id); | 702 | void epicsRingPointerDelete(epicsRingPointerId id); |
| 153 | 689 | /*epicsRingPointerPop returns 0 if the ring was empty */ | 703 | /*epicsRingPointerPop returns 0 if the ring was empty */ |
| 154 | 690 | void * epicsRingPointerPop(epicsRingPointerId id) ; | 704 | void * epicsRingPointerPop(epicsRingPointerId id) ; |
| 155 | @@ -700,6 +714,9 @@ | |||
| 156 | 700 | 714 | ||
| 157 | 701 | Each C function corresponds to one of the C++ methods. | 715 | Each C function corresponds to one of the C++ methods. |
| 158 | 702 | 716 | ||
| 159 | 717 | epicsRingPointerCreate() creates the unsecured variant, epicsRingPointerLockedCreate() creates the spin lock secured variant of the ring buffer. | ||
| 160 | 718 | |||
| 161 | 719 | |||
| 162 | 703 | \section{epicsTimer} | 720 | \section{epicsTimer} |
| 163 | 704 | 721 | ||
| 164 | 705 | \index{epicsTimer} | 722 | \index{epicsTimer} |
| 165 | 706 | 723 | ||
| 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 | 841 | 841 | ||
| 171 | 842 | A posix version is implemented via pthreads. | 842 | A posix version is implemented via pthreads. |
| 172 | 843 | 843 | ||
| 173 | 844 | |||
| 174 | 845 | \section{epicsSpin} | ||
| 175 | 846 | |||
| 176 | 847 | \index{epicsSpin} | ||
| 177 | 848 | \index{epicsSpin.h} | ||
| 178 | 849 | \verb|epicsSpin.h| contains definitions for a spin lock semaphore. | ||
| 179 | 850 | |||
| 180 | 851 | \subsection{C Interface} | ||
| 181 | 852 | |||
| 182 | 853 | \begin{verbatim} | ||
| 183 | 854 | typedef struct epicsSpin *epicsSpinId; | ||
| 184 | 855 | |||
| 185 | 856 | epicsSpinId epicsSpinCreate(); | ||
| 186 | 857 | void epicsSpinDestroy(epicsSpinId); | ||
| 187 | 858 | |||
| 188 | 859 | void epicsSpinLock(epicsSpinId); | ||
| 189 | 860 | int epicsSpinTryLock(epicsSpinId); | ||
| 190 | 861 | void epicsSpinUnlock(epicsSpinId); | ||
| 191 | 862 | \end{verbatim} | ||
| 192 | 863 | |||
| 193 | 864 | \index{epicsSpinId} | ||
| 194 | 865 | \index{epicsSpinCreate} | ||
| 195 | 866 | \index{epicsSpinDestroy} | ||
| 196 | 867 | \index{epicsSpinLock} | ||
| 197 | 868 | \index{epicsSpinTryLock} | ||
| 198 | 869 | \index{epicsSpinUnlock} | ||
| 199 | 870 | \begin{center} | ||
| 200 | 871 | \begin{longtable}{p{1.38889in}p{5.0in}} | ||
| 201 | 872 | \textbf{Method} & \textbf{Meaning}\\ | ||
| 202 | 873 | \hline | ||
| 203 | 874 | epicsSpinCreate & Create a spin lock, allocate required resources, and initialize it to an unlocked state.\\ | ||
| 204 | 875 | 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 | 876 | 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 | 877 | 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 | 878 | 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 | 879 | \end{longtable} | ||
| 209 | 880 | \end{center} | ||
| 210 | 881 | |||
| 211 | 882 | \subsection{Implementation Notes} | ||
| 212 | 883 | |||
| 213 | 884 | The default implementation uses POSIX spin locks on POSIX compliant systems, and epicsMutex for non-POSIX environments. | ||
| 214 | 885 | |||
| 215 | 886 | |||
| 216 | 844 | \section{epicsStdlib} | 887 | \section{epicsStdlib} |
| 217 | 845 | 888 | ||
| 218 | 846 | \index{epicsStdlib} | 889 | \index{epicsStdlib} |
| 219 | @@ -864,7 +907,6 @@ | |||
| 220 | 864 | They are provided because some architectures have implementations of scanf which do not accept NAN or INFINITY. | 907 | They are provided because some architectures have implementations of scanf which do not accept NAN or INFINITY. |
| 221 | 865 | 908 | ||
| 222 | 866 | 909 | ||
| 223 | 867 | |||
| 224 | 868 | \section{epicsStdio} | 910 | \section{epicsStdio} |
| 225 | 869 | 911 | ||
| 226 | 870 | \index{epicsStdio} | 912 | \index{epicsStdio} |
