1/*
2Copyright (c) 2012, Broadcom Europe Ltd
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, 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
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23ON 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
25SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
28/*=============================================================================
29VideoCore OS Abstraction Layer - public header file
30=============================================================================*/
31
32#ifndef VCOS_THREAD_H
33#define VCOS_THREAD_H
34
35#ifdef __cplusplus
36extern "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 */
92VCOSPRE_ 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 */
102VCOSPRE_ 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 */
115VCOSPRE_ 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 */
123VCOSPRE_ 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 */
148VCOSPRE_ 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 */
166VCOS_INLINE_DECL
167void vcos_thread_set_priority(VCOS_THREAD_T *thread, VCOS_UNSIGNED pri);
168
169/**
170 * \brief Return the currently executing thread.
171 *
172 */
173VCOS_INLINE_DECL
174VCOS_THREAD_T *vcos_thread_current(void);
175
176/**
177 * \brief Return the thread's priority.
178 */
179VCOS_INLINE_DECL
180VCOS_UNSIGNED vcos_thread_get_priority(VCOS_THREAD_T *thread);
181
182/**
183 * \brief Return the thread's cpu affinity.
184 */
185VCOS_INLINE_DECL
186VCOS_UNSIGNED vcos_thread_get_affinity(VCOS_THREAD_T *thread);
187
188/**
189 * \brief Set the thread's cpu affinity.
190 */
191
192VCOS_INLINE_DECL
193void 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 */
200VCOS_INLINE_DECL
201int 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 */
210VCOS_INLINE_DECL
211void vcos_sleep(uint32_t ms);
212
213/**
214 * \brief Return the value of the hardware microsecond counter.
215 *
216 */
217VCOS_INLINE_DECL
218uint32_t vcos_getmicrosecs(void);
219
220VCOS_INLINE_DECL
221uint64_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 */
229VCOS_INLINE_DECL
230VCOS_UNSIGNED vcos_process_id_current(void);
231
232/** Relinquish this time slice. */
233VCOS_INLINE_DECL
234void vcos_thread_relinquish(void);
235
236/** Return the name of the given thread.
237 */
238VCOSPRE_ 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 */
250VCOS_INLINE_DECL
251VCOS_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 */
261VCOS_INLINE_DECL
262int vcos_thread_running(VCOS_THREAD_T *thread);
263
264/** Resume a thread.
265 *
266 * @param thread thread to resume
267 */
268VCOS_INLINE_DECL
269void 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
276extern void _vcos_task_timer_set(void (*pfn)(void*), void *, VCOS_UNSIGNED ms);
277extern void _vcos_task_timer_cancel(void);
278
279#ifdef __cplusplus
280}
281#endif
282#endif
283