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