|
0
|
1 #ifndef CYGONCE_KERNEL_THREAD_INL |
|
|
2 #define CYGONCE_KERNEL_THREAD_INL |
|
|
3 |
|
|
4 //========================================================================== |
|
|
5 // |
|
|
6 // thread.inl |
|
|
7 // |
|
|
8 // Thread class inlines |
|
|
9 // |
|
|
10 //========================================================================== |
|
|
11 //####COPYRIGHTBEGIN#### |
|
|
12 // |
|
|
13 // ------------------------------------------- |
|
|
14 // The contents of this file are subject to the Cygnus eCos Public License |
|
|
15 // Version 1.0 (the "License"); you may not use this file except in |
|
|
16 // compliance with the License. You may obtain a copy of the License at |
|
|
17 // http://sourceware.cygnus.com/ecos |
|
|
18 // |
|
|
19 // Software distributed under the License is distributed on an "AS IS" |
|
|
20 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the |
|
|
21 // License for the specific language governing rights and limitations under |
|
|
22 // the License. |
|
|
23 // |
|
|
24 // The Original Code is eCos - Embedded Cygnus Operating System, released |
|
|
25 // September 30, 1998. |
|
|
26 // |
|
|
27 // The Initial Developer of the Original Code is Cygnus. Portions created |
|
|
28 // by Cygnus are Copyright (C) 1998 Cygnus Solutions. All Rights Reserved. |
|
|
29 // ------------------------------------------- |
|
|
30 // |
|
|
31 //####COPYRIGHTEND#### |
|
|
32 //========================================================================== |
|
|
33 //#####DESCRIPTIONBEGIN#### |
|
|
34 // |
|
|
35 // Author(s): nickg |
|
|
36 // Contributors: nickg |
|
|
37 // Date: 1997-09-09 |
|
|
38 // Purpose: Define inlines for thread classes |
|
|
39 // Description: Inline implementations of various member functions defined |
|
|
40 // in various Thread classes. |
|
|
41 // Usage: |
|
|
42 // #include <cyg/kernel/thread.hxx> |
|
|
43 // ... |
|
|
44 // #include <cyg/kernel/thread.inl> |
|
|
45 // ... |
|
|
46 |
|
|
47 // |
|
|
48 //####DESCRIPTIONEND#### |
|
|
49 // |
|
|
50 //========================================================================== |
|
|
51 |
|
|
52 #include <cyg/kernel/thread.hxx> |
|
|
53 #include <cyg/hal/hal_arch.h> |
|
|
54 |
|
|
55 #include <cyg/kernel/clock.inl> |
|
|
56 |
|
|
57 //========================================================================== |
|
|
58 // Inlines for Cyg_HardwareThread |
|
|
59 |
|
|
60 // ------------------------------------------------------------------------- |
|
|
61 // Attach a stack to this thread. If there is a HAL defined macro to |
|
|
62 // do this, then we use that, otherwise assume a falling stack. |
|
|
63 inline void Cyg_HardwareThread::attach_stack(CYG_ADDRESS s_base, cyg_uint32 s_size) |
|
|
64 { |
|
|
65 stack_base = s_base; |
|
|
66 stack_size = s_size; |
|
|
67 #ifdef CYGFUN_KERNEL_THREADS_STACK_LIMIT |
|
|
68 stack_limit = s_base; |
|
|
69 #endif |
|
|
70 |
|
|
71 #ifdef HAL_THREAD_ATTACH_STACK |
|
|
72 |
|
|
73 HAL_THREAD_ATTACH_STACK(stack_ptr, stack_base, stack_size); |
|
|
74 |
|
|
75 #else |
|
|
76 |
|
|
77 stack_ptr = stack_base + stack_size; |
|
|
78 |
|
|
79 #endif |
|
|
80 } |
|
|
81 |
|
|
82 // ------------------------------------------------------------------------- |
|
|
83 |
|
|
84 inline Cyg_HardwareThread::Cyg_HardwareThread( |
|
|
85 cyg_thread_entry *e_point, // entry point function |
|
|
86 CYG_ADDRWORD e_data, // entry data |
|
|
87 cyg_ucount32 s_size, // stack size, 0 = use default |
|
|
88 CYG_ADDRESS s_base // stack base, NULL = allocate |
|
|
89 ) |
|
|
90 { |
|
|
91 entry_point = e_point; |
|
|
92 entry_data = e_data; |
|
|
93 #ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT |
|
|
94 saved_context = 0; |
|
|
95 #endif |
|
|
96 |
|
|
97 attach_stack( s_base, s_size ); |
|
|
98 }; |
|
|
99 |
|
|
100 // ------------------------------------------------------------------------- |
|
|
101 // get the size/base of this thread's stack |
|
|
102 |
|
|
103 inline CYG_ADDRESS |
|
|
104 Cyg_HardwareThread::get_stack_base() |
|
|
105 { |
|
|
106 return stack_base; |
|
|
107 } |
|
|
108 |
|
|
109 inline cyg_uint32 |
|
|
110 Cyg_HardwareThread::get_stack_size() |
|
|
111 { |
|
|
112 return stack_size; |
|
|
113 } |
|
|
114 |
|
|
115 // ------------------------------------------------------------------------- |
|
|
116 |
|
|
117 #ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT |
|
|
118 |
|
|
119 // Return the current saved state for this thread. |
|
|
120 inline HAL_SavedRegisters *Cyg_HardwareThread::get_saved_context() |
|
|
121 { |
|
|
122 HAL_SavedRegisters *regs; |
|
|
123 if( saved_context != 0 ) regs = saved_context; |
|
|
124 else HAL_THREAD_GET_SAVED_REGISTERS( stack_ptr, regs ); |
|
|
125 return regs; |
|
|
126 } |
|
|
127 |
|
|
128 inline void Cyg_HardwareThread::set_saved_context(HAL_SavedRegisters *ctx) |
|
|
129 { |
|
|
130 saved_context = ctx; |
|
|
131 } |
|
|
132 |
|
|
133 #endif |
|
|
134 |
|
|
135 // ------------------------------------------------------------------------- |
|
|
136 // (declare this inline before its first use) |
|
|
137 |
|
|
138 inline cyg_uint16 Cyg_Thread::get_unique_id() |
|
|
139 { |
|
|
140 return unique_id; |
|
|
141 } |
|
|
142 |
|
|
143 // ------------------------------------------------------------------------- |
|
|
144 // Initialize the context of this thread. |
|
|
145 |
|
|
146 inline void Cyg_HardwareThread::init_context(Cyg_Thread *thread) |
|
|
147 { |
|
|
148 #ifdef CYGPKG_INFRA_DEBUG |
|
|
149 cyg_uint32 threadid = thread->get_unique_id()*0x01010000; |
|
|
150 #else |
|
|
151 cyg_uint32 threadid = 0x11110000; |
|
|
152 #endif |
|
|
153 HAL_THREAD_INIT_CONTEXT( stack_ptr, thread, thread_entry, threadid ); |
|
|
154 } |
|
|
155 |
|
|
156 |
|
|
157 |
|
|
158 // ------------------------------------------------------------------------- |
|
|
159 // Load thread context without saving current context. |
|
|
160 // This function is only really here for completeness, the |
|
|
161 // kernel generally calls the HAL macros directly. |
|
|
162 |
|
|
163 inline void Cyg_HardwareThread::load_context() |
|
|
164 { |
|
|
165 CYG_ADDRESS dummy_stack_ptr; |
|
|
166 |
|
|
167 HAL_THREAD_SWITCH_CONTEXT( &dummy_stack_ptr, &stack_ptr ); |
|
|
168 } |
|
|
169 |
|
|
170 // ------------------------------------------------------------------------- |
|
|
171 // Save current thread's context and load that of the given next thread. |
|
|
172 // This function is only really here for completeness, the |
|
|
173 // kernel generally calls the HAL macros directly. |
|
|
174 |
|
|
175 inline void Cyg_HardwareThread::switch_context(Cyg_HardwareThread *next) |
|
|
176 { |
|
|
177 HAL_THREAD_SWITCH_CONTEXT( &stack_ptr, &next->stack_ptr ); |
|
|
178 } |
|
|
179 |
|
|
180 // ------------------------------------------------------------------------- |
|
|
181 // Get and set entry_data. |
|
|
182 |
|
|
183 inline void Cyg_HardwareThread::set_entry_data( CYG_ADDRWORD data ) |
|
|
184 { |
|
|
185 entry_data = data; |
|
|
186 } |
|
|
187 |
|
|
188 inline CYG_ADDRWORD Cyg_HardwareThread::get_entry_data() |
|
|
189 { |
|
|
190 return entry_data; |
|
|
191 } |
|
|
192 |
|
|
193 // ------------------------------------------------------------------------- |
|
|
194 // Allocate some memory at the lower end of the stack |
|
|
195 // by moving the stack limit pointer. |
|
|
196 |
|
|
197 #ifdef CYGFUN_KERNEL_THREADS_STACK_LIMIT |
|
|
198 |
|
|
199 inline void *Cyg_HardwareThread::increment_stack_limit( cyg_ucount32 size) |
|
|
200 { |
|
|
201 stack_limit += size; |
|
|
202 return (void *)(stack_limit - size); |
|
|
203 } |
|
|
204 |
|
|
205 |
|
|
206 inline CYG_ADDRESS |
|
|
207 Cyg_HardwareThread::get_stack_limit() |
|
|
208 { |
|
|
209 return stack_limit; |
|
|
210 } |
|
|
211 |
|
|
212 #endif |
|
|
213 |
|
|
214 //========================================================================== |
|
|
215 // Inlines for Cyg_Thread class |
|
|
216 |
|
|
217 inline Cyg_Thread *Cyg_Thread::self() |
|
|
218 { |
|
|
219 return Cyg_Scheduler::get_current_thread(); |
|
|
220 } |
|
|
221 |
|
|
222 // ------------------------------------------------------------------------- |
|
|
223 |
|
|
224 inline void Cyg_Thread::yield() |
|
|
225 { |
|
|
226 self()->Cyg_SchedThread::yield(); |
|
|
227 } |
|
|
228 |
|
|
229 // ------------------------------------------------------------------------- |
|
|
230 |
|
|
231 #ifdef CYGSEM_KERNEL_SCHED_MLQUEUE |
|
|
232 inline void |
|
|
233 Cyg_Thread::rotate_queue( cyg_priority pri ) |
|
|
234 { |
|
|
235 self()->Cyg_SchedThread::rotate_queue( pri ); |
|
|
236 } |
|
|
237 #endif |
|
|
238 |
|
|
239 // ------------------------------------------------------------------------- |
|
|
240 |
|
|
241 #ifdef CYGIMP_THREAD_PRIORITY |
|
|
242 |
|
|
243 inline cyg_priority Cyg_Thread::get_priority() |
|
|
244 { |
|
|
245 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE |
|
|
246 |
|
|
247 // If we have an inherited priority, return our original |
|
|
248 // priority rather than the current one. |
|
|
249 |
|
|
250 if( priority_inherited ) return original_priority; |
|
|
251 |
|
|
252 #endif |
|
|
253 |
|
|
254 return priority; |
|
|
255 } |
|
|
256 |
|
|
257 // Return the actual dispatching priority of the thread |
|
|
258 // regardless of inheritance or scheduling concerns. |
|
|
259 inline cyg_priority Cyg_Thread::get_current_priority() |
|
|
260 { |
|
|
261 return priority; |
|
|
262 } |
|
|
263 |
|
|
264 #endif |
|
|
265 |
|
|
266 // ------------------------------------------------------------------------- |
|
|
267 |
|
|
268 inline void Cyg_Thread::set_sleep_reason( cyg_reason reason) |
|
|
269 { |
|
|
270 self()->sleep_reason = reason; |
|
|
271 self()->wake_reason = NONE; |
|
|
272 } |
|
|
273 |
|
|
274 // ------------------------------------------------------------------------- |
|
|
275 |
|
|
276 inline Cyg_Thread::cyg_reason Cyg_Thread::get_sleep_reason() |
|
|
277 { |
|
|
278 return sleep_reason; |
|
|
279 } |
|
|
280 |
|
|
281 // ------------------------------------------------------------------------- |
|
|
282 |
|
|
283 inline void Cyg_Thread::set_wake_reason( cyg_reason reason ) |
|
|
284 { |
|
|
285 sleep_reason = NONE; |
|
|
286 wake_reason = reason; |
|
|
287 } |
|
|
288 |
|
|
289 // ------------------------------------------------------------------------- |
|
|
290 |
|
|
291 inline Cyg_Thread::cyg_reason Cyg_Thread::get_wake_reason() |
|
|
292 { |
|
|
293 return wake_reason; |
|
|
294 } |
|
|
295 |
|
|
296 // ------------------------------------------------------------------------- |
|
|
297 |
|
|
298 inline void Cyg_Thread::set_timer( |
|
|
299 cyg_tick_count trigger, |
|
|
300 cyg_reason reason |
|
|
301 ) |
|
|
302 { |
|
|
303 #ifdef CYGFUN_KERNEL_THREADS_TIMER |
|
|
304 self()->sleep_reason = reason; |
|
|
305 self()->wake_reason = NONE; |
|
|
306 self()->timer.initialize( trigger); |
|
|
307 #endif |
|
|
308 } |
|
|
309 |
|
|
310 // ------------------------------------------------------------------------- |
|
|
311 |
|
|
312 inline void Cyg_Thread::clear_timer() |
|
|
313 { |
|
|
314 #ifdef CYGFUN_KERNEL_THREADS_TIMER |
|
|
315 self()->timer.disable(); |
|
|
316 #endif |
|
|
317 } |
|
|
318 |
|
|
319 // ------------------------------------------------------------------------- |
|
|
320 |
|
|
321 #ifdef CYGVAR_KERNEL_THREADS_DATA |
|
|
322 |
|
|
323 inline CYG_ADDRWORD Cyg_Thread::get_data( cyg_ucount32 index ) |
|
|
324 { |
|
|
325 CYG_ASSERT( index < CYGNUM_KERNEL_THREADS_DATA_MAX, |
|
|
326 "Per thread data index out of bounds"); |
|
|
327 CYG_ASSERT( (thread_data_map & (1<<index)) == 0, |
|
|
328 "Unallocated index used"); |
|
|
329 |
|
|
330 return self()->thread_data[index]; |
|
|
331 } |
|
|
332 |
|
|
333 inline CYG_ADDRWORD *Cyg_Thread::get_data_ptr( cyg_ucount32 index ) |
|
|
334 { |
|
|
335 CYG_ASSERT( index < CYGNUM_KERNEL_THREADS_DATA_MAX, |
|
|
336 "Per thread data index out of bounds"); |
|
|
337 CYG_ASSERT( (thread_data_map & (1<<index)) == 0, |
|
|
338 "Unallocated index used"); |
|
|
339 |
|
|
340 return &(self()->thread_data[index]); |
|
|
341 } |
|
|
342 |
|
|
343 inline void Cyg_Thread::set_data( cyg_ucount32 index, CYG_ADDRWORD data ) |
|
|
344 { |
|
|
345 CYG_ASSERT( index < CYGNUM_KERNEL_THREADS_DATA_MAX, |
|
|
346 "Per thread data index out of bounds"); |
|
|
347 CYG_ASSERT( (thread_data_map & (1<<index)) == 0, |
|
|
348 "Unallocated index used"); |
|
|
349 |
|
|
350 thread_data[index] = data; |
|
|
351 } |
|
|
352 |
|
|
353 #endif |
|
|
354 |
|
|
355 // ------------------------------------------------------------------------- |
|
|
356 |
|
|
357 #ifdef CYGVAR_KERNEL_THREADS_NAME |
|
|
358 |
|
|
359 inline char *Cyg_Thread::get_name() |
|
|
360 { |
|
|
361 return name; |
|
|
362 } |
|
|
363 |
|
|
364 #endif |
|
|
365 |
|
|
366 // ------------------------------------------------------------------------- |
|
|
367 |
|
|
368 #ifdef CYGVAR_KERNEL_THREADS_LIST |
|
|
369 |
|
|
370 inline Cyg_Thread *Cyg_Thread::get_list_head() |
|
|
371 { |
|
|
372 return thread_list?thread_list->list_next:0; |
|
|
373 } |
|
|
374 |
|
|
375 inline Cyg_Thread *Cyg_Thread::get_list_next() |
|
|
376 { |
|
|
377 return (this==thread_list)?0:list_next; |
|
|
378 } |
|
|
379 |
|
|
380 #endif |
|
|
381 |
|
|
382 |
|
|
383 // ------------------------------------------------------------------------- |
|
|
384 |
|
|
385 #ifdef CYGPKG_KERNEL_EXCEPTIONS |
|
|
386 |
|
|
387 inline void Cyg_Thread::register_exception( |
|
|
388 cyg_code exception_number, // exception number |
|
|
389 cyg_exception_handler handler, // handler function |
|
|
390 CYG_ADDRWORD data, // data argument |
|
|
391 cyg_exception_handler **old_handler, // handler function |
|
|
392 CYG_ADDRWORD *old_data // data argument |
|
|
393 ) |
|
|
394 { |
|
|
395 self()->exception_control.register_exception( |
|
|
396 exception_number, |
|
|
397 handler, |
|
|
398 data, |
|
|
399 old_handler, |
|
|
400 old_data |
|
|
401 ); |
|
|
402 } |
|
|
403 |
|
|
404 inline void Cyg_Thread::deregister_exception( |
|
|
405 cyg_code exception_number // exception number |
|
|
406 ) |
|
|
407 { |
|
|
408 self()->exception_control.deregister_exception( |
|
|
409 exception_number |
|
|
410 ); |
|
|
411 } |
|
|
412 |
|
|
413 #endif |
|
|
414 |
|
|
415 //========================================================================== |
|
|
416 // Inlines for Cyg_ThreadTimer class |
|
|
417 |
|
|
418 // ------------------------------------------------------------------------- |
|
|
419 #if defined(CYGFUN_KERNEL_THREADS_TIMER) && defined(CYGVAR_KERNEL_COUNTERS_CLOCK) |
|
|
420 |
|
|
421 inline Cyg_ThreadTimer::Cyg_ThreadTimer( |
|
|
422 Cyg_Thread *th |
|
|
423 ) |
|
|
424 : Cyg_Alarm(Cyg_Clock::real_time_clock, |
|
|
425 &alarm, |
|
|
426 CYG_ADDRWORD(this) |
|
|
427 ) |
|
|
428 { |
|
|
429 thread = th; |
|
|
430 } |
|
|
431 |
|
|
432 #endif |
|
|
433 |
|
|
434 //========================================================================== |
|
|
435 // Inlines for Cyg_ThreadQueue class |
|
|
436 |
|
|
437 |
|
|
438 inline void Cyg_ThreadQueue::enqueue(Cyg_Thread *thread) |
|
|
439 { |
|
|
440 Cyg_ThreadQueue_Implementation::enqueue(thread); |
|
|
441 } |
|
|
442 |
|
|
443 // ------------------------------------------------------------------------- |
|
|
444 |
|
|
445 inline Cyg_Thread *Cyg_ThreadQueue::highpri() |
|
|
446 { |
|
|
447 return Cyg_ThreadQueue_Implementation::highpri(); |
|
|
448 } |
|
|
449 |
|
|
450 // ------------------------------------------------------------------------- |
|
|
451 |
|
|
452 inline Cyg_Thread *Cyg_ThreadQueue::dequeue() |
|
|
453 { |
|
|
454 return Cyg_ThreadQueue_Implementation::dequeue(); |
|
|
455 } |
|
|
456 |
|
|
457 // ------------------------------------------------------------------------- |
|
|
458 |
|
|
459 inline void Cyg_ThreadQueue::remove(Cyg_Thread *thread) |
|
|
460 { |
|
|
461 Cyg_ThreadQueue_Implementation::remove(thread); |
|
|
462 } |
|
|
463 |
|
|
464 // ------------------------------------------------------------------------- |
|
|
465 |
|
|
466 inline cyg_bool Cyg_ThreadQueue::empty() |
|
|
467 { |
|
|
468 return Cyg_ThreadQueue_Implementation::empty(); |
|
|
469 } |
|
|
470 |
|
|
471 // ------------------------------------------------------------------------- |
|
|
472 #endif // ifndef CYGONCE_KERNEL_THREAD_INL |
|
|
473 // EOF thread.inl |