1 | /* |
2 | Copyright (c) 2012, Broadcom Europe Ltd |
3 | All rights reserved. |
4 | |
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the following conditions are met: |
7 | * Redistributions of source code must retain the above copyright |
8 | notice, this list of conditions and the following disclaimer. |
9 | * Redistributions in binary form must reproduce the above copyright |
10 | notice, this list of conditions and the following disclaimer in the |
11 | documentation and/or other materials provided with the distribution. |
12 | * Neither the name of the copyright holder nor the |
13 | names of its contributors may be used to endorse or promote products |
14 | derived from this software without specific prior written permission. |
15 | |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY |
20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ |
27 | |
28 | /*============================================================================= |
29 | VideoCore OS Abstraction Layer - public header file |
30 | =============================================================================*/ |
31 | |
32 | #ifndef VCOS_THREAD_H |
33 | #define VCOS_THREAD_H |
34 | |
35 | #ifdef __cplusplus |
36 | extern "C" { |
37 | #endif |
38 | |
39 | #include "interface/vcos/vcos_types.h" |
40 | #include "vcos.h" |
41 | |
42 | /** |
43 | * \file vcos_thread.h |
44 | * |
45 | * \section thread Threads |
46 | * |
47 | * Under Nucleus, a thread is created by NU_Create_Task, passing in the stack |
48 | * and various other parameters. To stop the thread, NU_Terminate_Thread() and |
49 | * NU_Delete_Thread() are called. |
50 | * |
51 | * Unfortunately it's not possible to emulate this API under some fairly common |
52 | * operating systems. Under Windows you can't pass in the stack, and you can't |
53 | * safely terminate a thread. |
54 | * |
55 | * Therefore, an API which is similar to the pthreads API is used instead. This |
56 | * API can (mostly) be emulated under all interesting operating systems. |
57 | * |
58 | * Obviously this makes the code somewhat more complicated on VideoCore than it |
59 | * would otherwise be - we end up with an extra mutex per thread, and some code |
60 | * that waits for it. The benefit is that we have a single way of creating |
61 | * threads that works consistently on all platforms (apart from stack supplying). |
62 | * |
63 | * \subsection stack Stack |
64 | * |
65 | * It's still not possible to pass in the stack address, but this can be made |
66 | * much more obvious in the API: the relevant function is missing and the |
67 | * CPP symbol VCOS_CAN_SET_STACK_ADDR is zero rather than one. |
68 | * |
69 | * \subsection thr_create Creating a thread |
70 | * |
71 | * The simplest way to create a thread is with vcos_thread_create() passing in a |
72 | * NULL thread parameter argument. To wait for the thread to exit, call |
73 | * vcos_thread_join(). |
74 | * |
75 | * \subsection back Backward compatibility |
76 | * |
77 | * To ease migration, a "classic" thread creation API is provided for code |
78 | * that used to make use of Nucleus, vcos_thread_create_classic(). The |
79 | * arguments are not exactly the same, as the PREEMPT parameter is dropped. |
80 | * |
81 | */ |
82 | |
83 | #define VCOS_AFFINITY_CPU0 _VCOS_AFFINITY_CPU0 |
84 | #define VCOS_AFFINITY_CPU1 _VCOS_AFFINITY_CPU1 |
85 | #define VCOS_AFFINITY_MASK _VCOS_AFFINITY_MASK |
86 | #define VCOS_AFFINITY_DEFAULT _VCOS_AFFINITY_DEFAULT |
87 | #define VCOS_AFFINITY_THISCPU _VCOS_AFFINITY_THISCPU |
88 | |
89 | /** Report whether or not we have an RTOS at all, and hence the ability to |
90 | * create threads. |
91 | */ |
92 | VCOSPRE_ int VCOSPOST_ vcos_have_rtos(void); |
93 | |
94 | /** Create a thread. It must be cleaned up by calling vcos_thread_join(). |
95 | * |
96 | * @param thread Filled in on return with thread |
97 | * @param name A name for the thread. May be the empty string. |
98 | * @param attrs Attributes; default attributes will be used if this is NULL. |
99 | * @param entry Entry point. |
100 | * @param arg Argument passed to the entry point. |
101 | */ |
102 | VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_thread_create(VCOS_THREAD_T *thread, |
103 | const char *name, |
104 | VCOS_THREAD_ATTR_T *attrs, |
105 | VCOS_THREAD_ENTRY_FN_T entry, |
106 | void *arg); |
107 | |
108 | /** Exit the thread from within the thread function itself. |
109 | * Resources must still be cleaned up via a call to thread_join(). |
110 | * |
111 | * The thread can also be terminated by simply exiting the thread function. |
112 | * |
113 | * @param data Data passed to thread_join. May be NULL. |
114 | */ |
115 | VCOSPRE_ void VCOSPOST_ vcos_thread_exit(void *data); |
116 | |
117 | /** Wait for a thread to terminate and then clean up its resources. |
118 | * |
119 | * @param thread Thread to wait for |
120 | * @param pData Updated to point at data provided in vcos_thread_exit or exit |
121 | * code of thread function. |
122 | */ |
123 | VCOSPRE_ void VCOSPOST_ vcos_thread_join(VCOS_THREAD_T *thread, |
124 | void **pData); |
125 | |
126 | |
127 | /** |
128 | * \brief Create a thread using an API similar to the one "traditionally" |
129 | * used under Nucleus. |
130 | * |
131 | * This creates a thread which must be cleaned up by calling vcos_thread_join(). |
132 | * The thread cannot be simply terminated (as in Nucleus and ThreadX) as thread |
133 | * termination is not universally supported. |
134 | * |
135 | * @param thread Filled in with thread instance |
136 | * @param name An optional name for the thread. NULL or "" may be used (but |
137 | * a name will aid in debugging). |
138 | * @param entry Entry point |
139 | * @param arg A single argument passed to the entry point function |
140 | * @param stack Pointer to stack address |
141 | * @param stacksz Size of stack in bytes |
142 | * @param priaff Priority of task, between VCOS_PRI_LOW and VCOS_PRI_HIGH, ORed with the CPU affinity |
143 | * @param autostart If non-zero the thread will start immediately. |
144 | * @param timeslice Timeslice (system ticks) for this thread. |
145 | * |
146 | * @sa vcos_thread_terminate vcos_thread_delete |
147 | */ |
148 | VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_thread_create_classic(VCOS_THREAD_T *thread, |
149 | const char *name, |
150 | void *(*entry)(void *arg), |
151 | void *arg, |
152 | void *stack, |
153 | VCOS_UNSIGNED stacksz, |
154 | VCOS_UNSIGNED priaff, |
155 | VCOS_UNSIGNED timeslice, |
156 | VCOS_UNSIGNED autostart); |
157 | |
158 | /** |
159 | * \brief Set a thread's priority |
160 | * |
161 | * Set the priority for a thread. |
162 | * |
163 | * @param thread The thread |
164 | * @param pri Thread priority in VCOS_PRI_MASK bits; affinity in VCOS_AFFINITY_MASK bits. |
165 | */ |
166 | VCOS_INLINE_DECL |
167 | void vcos_thread_set_priority(VCOS_THREAD_T *thread, VCOS_UNSIGNED pri); |
168 | |
169 | /** |
170 | * \brief Return the currently executing thread. |
171 | * |
172 | */ |
173 | VCOS_INLINE_DECL |
174 | VCOS_THREAD_T *vcos_thread_current(void); |
175 | |
176 | /** |
177 | * \brief Return the thread's priority. |
178 | */ |
179 | VCOS_INLINE_DECL |
180 | VCOS_UNSIGNED vcos_thread_get_priority(VCOS_THREAD_T *thread); |
181 | |
182 | /** |
183 | * \brief Return the thread's cpu affinity. |
184 | */ |
185 | VCOS_INLINE_DECL |
186 | VCOS_UNSIGNED vcos_thread_get_affinity(VCOS_THREAD_T *thread); |
187 | |
188 | /** |
189 | * \brief Set the thread's cpu affinity. |
190 | */ |
191 | |
192 | VCOS_INLINE_DECL |
193 | void vcos_thread_set_affinity(VCOS_THREAD_T *thread, VCOS_UNSIGNED affinity); |
194 | |
195 | /** |
196 | * \brief Query whether we are in an interrupt. |
197 | * |
198 | * @return 1 if in interrupt context. |
199 | */ |
200 | VCOS_INLINE_DECL |
201 | int vcos_in_interrupt(void); |
202 | |
203 | /** |
204 | * \brief Sleep a while. |
205 | * |
206 | * @param ms Number of milliseconds to sleep for |
207 | * |
208 | * This may actually sleep a whole number of ticks. |
209 | */ |
210 | VCOS_INLINE_DECL |
211 | void vcos_sleep(uint32_t ms); |
212 | |
213 | /** |
214 | * \brief Return the value of the hardware microsecond counter. |
215 | * |
216 | */ |
217 | VCOS_INLINE_DECL |
218 | uint32_t vcos_getmicrosecs(void); |
219 | |
220 | VCOS_INLINE_DECL |
221 | uint64_t vcos_getmicrosecs64(void); |
222 | |
223 | #define vcos_get_ms() (vcos_getmicrosecs()/1000) |
224 | |
225 | /** |
226 | * \brief Return a unique identifier for the current process |
227 | * |
228 | */ |
229 | VCOS_INLINE_DECL |
230 | VCOS_UNSIGNED vcos_process_id_current(void); |
231 | |
232 | /** Relinquish this time slice. */ |
233 | VCOS_INLINE_DECL |
234 | void vcos_thread_relinquish(void); |
235 | |
236 | /** Return the name of the given thread. |
237 | */ |
238 | VCOSPRE_ const char * VCOSPOST_ vcos_thread_get_name(const VCOS_THREAD_T *thread); |
239 | |
240 | /** Change preemption. This is almost certainly not what you want, as it won't |
241 | * work reliably in a multicore system: although you can affect the preemption |
242 | * on *this* core, you won't affect what's happening on the other core(s). |
243 | * |
244 | * It's mainly here to ease migration. If you're using it in new code, you |
245 | * probably need to think again. |
246 | * |
247 | * @param pe New preemption, VCOS_PREEMPT or VCOS_NO_PREEMPT |
248 | * @return Old value of preemption. |
249 | */ |
250 | VCOS_INLINE_DECL |
251 | VCOS_UNSIGNED vcos_change_preemption(VCOS_UNSIGNED pe); |
252 | |
253 | /** Is a thread still running, or has it exited? |
254 | * |
255 | * Note: this exists for some fairly scary code in the video codec tests. Don't |
256 | * try to use it for anything else, as it may well not do what you expect. |
257 | * |
258 | * @param thread thread to query |
259 | * @return non-zero if thread is running, or zero if it has exited. |
260 | */ |
261 | VCOS_INLINE_DECL |
262 | int vcos_thread_running(VCOS_THREAD_T *thread); |
263 | |
264 | /** Resume a thread. |
265 | * |
266 | * @param thread thread to resume |
267 | */ |
268 | VCOS_INLINE_DECL |
269 | void vcos_thread_resume(VCOS_THREAD_T *thread); |
270 | |
271 | /* |
272 | * Internal APIs - may not always be present and should not be used in |
273 | * client code. |
274 | */ |
275 | |
276 | extern void _vcos_task_timer_set(void (*pfn)(void*), void *, VCOS_UNSIGNED ms); |
277 | extern void _vcos_task_timer_cancel(void); |
278 | |
279 | #ifdef __cplusplus |
280 | } |
281 | #endif |
282 | #endif |
283 | |