mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-20 15:37:42 +08:00
2011-04-21 Jennifer Averett <Jennifer.Averett@OARcorp.com
PR 1777/cpukit * libcsupport/src/malloc_deferred.c, libcsupport/src/realloc.c, score/Makefile.am, score/cpu/lm32/irq.c, score/cpu/nios2/irq.c, score/include/rtems/score/coremutex.h, score/include/rtems/score/thread.h, score/inline/rtems/score/thread.inl, score/src/heapfree.c, score/src/pheapwalk.c, score/src/smp.c, score/src/threaddispatch.c: Consolidated access to _Thread_Dispatch_disable_level. * score/src/threaddisabledispatch.c, score/src/threadenabledispatch.c: New files.
This commit is contained in:
@@ -1,3 +1,16 @@
|
||||
2011-04-21 Jennifer Averett <Jennifer.Averett@OARcorp.com
|
||||
|
||||
PR 1777/cpukit
|
||||
* libcsupport/src/malloc_deferred.c, libcsupport/src/realloc.c,
|
||||
score/Makefile.am, score/cpu/lm32/irq.c, score/cpu/nios2/irq.c,
|
||||
score/include/rtems/score/coremutex.h,
|
||||
score/include/rtems/score/thread.h,
|
||||
score/inline/rtems/score/thread.inl, score/src/heapfree.c,
|
||||
score/src/pheapwalk.c, score/src/smp.c, score/src/threaddispatch.c:
|
||||
Consolidated access to _Thread_Dispatch_disable_level.
|
||||
* score/src/threaddisabledispatch.c, score/src/threadenabledispatch.c:
|
||||
New files.
|
||||
|
||||
2011-04-18 Joel Sherrill <joel.sherrilL@OARcorp.com>
|
||||
|
||||
* posix/src/mqueuegetattr.c,
|
||||
|
||||
@@ -26,7 +26,7 @@ rtems_chain_control RTEMS_Malloc_GC_list;
|
||||
|
||||
bool malloc_is_system_state_OK(void)
|
||||
{
|
||||
if ( _Thread_Dispatch_disable_level > 0 )
|
||||
if ( _Thread_Dispatch_in_critical_section() )
|
||||
return false;
|
||||
|
||||
if ( _ISR_Nest_level > 0 )
|
||||
|
||||
@@ -35,7 +35,7 @@ void *realloc(
|
||||
*/
|
||||
|
||||
if (_System_state_Is_up(_System_state_Get())) {
|
||||
if (_Thread_Dispatch_disable_level > 0)
|
||||
if (_Thread_Dispatch_in_critical_section())
|
||||
return (void *) 0;
|
||||
|
||||
if (_ISR_Nest_level > 0)
|
||||
|
||||
@@ -189,6 +189,7 @@ libscore_a_SOURCES += src/rbtree.c \
|
||||
libscore_a_SOURCES += src/thread.c src/threadchangepriority.c \
|
||||
src/threadclearstate.c src/threadclose.c src/threadcreateidle.c \
|
||||
src/threaddelayended.c src/threaddispatch.c \
|
||||
src/threadenabledispatch.c src/threaddisabledispatch.c \
|
||||
src/threadget.c src/threadhandler.c src/threadinitialize.c \
|
||||
src/threadloadenv.c src/threadready.c src/threadreset.c \
|
||||
src/threadrestart.c src/threadsetpriority.c \
|
||||
|
||||
@@ -44,7 +44,7 @@ void __ISR_Handler(uint32_t vector, CPU_Interrupt_frame *ifr)
|
||||
|
||||
/* Interrupts are disabled upon entry to this Handler */
|
||||
|
||||
_Thread_Dispatch_disable_level++;
|
||||
_Thread_Dispatch_increment_disable_level();
|
||||
|
||||
#if( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE)
|
||||
if ( _ISR_Nest_level == 0 ) {
|
||||
@@ -71,7 +71,7 @@ void __ISR_Handler(uint32_t vector, CPU_Interrupt_frame *ifr)
|
||||
stack_ptr = _old_stack_ptr;
|
||||
#endif
|
||||
|
||||
_Thread_Dispatch_disable_level--;
|
||||
_Thread_Dispatch_decrement_disable_level();
|
||||
|
||||
_CPU_ISR_Enable( level );
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ void __ISR_Handler(uint32_t vector, CPU_Interrupt_frame *ifr)
|
||||
|
||||
_ISR_Nest_level++;
|
||||
|
||||
_Thread_Dispatch_disable_level++;
|
||||
_Thread_Dispatch_increment_disable_level();
|
||||
|
||||
if ( _ISR_Vector_table[ vector] )
|
||||
{
|
||||
@@ -60,7 +60,7 @@ void __ISR_Handler(uint32_t vector, CPU_Interrupt_frame *ifr)
|
||||
/* Make sure that interrupts are disabled again */
|
||||
_CPU_ISR_Disable( level );
|
||||
|
||||
_Thread_Dispatch_disable_level--;
|
||||
_Thread_Dispatch_decrement_disable_level();
|
||||
|
||||
_ISR_Nest_level--;
|
||||
|
||||
@@ -69,7 +69,7 @@ void __ISR_Handler(uint32_t vector, CPU_Interrupt_frame *ifr)
|
||||
stack_ptr = _old_stack_ptr;
|
||||
#endif
|
||||
|
||||
if( _Thread_Dispatch_disable_level == 0 )
|
||||
if( !_Thread_Dispatch_in_critical_section() )
|
||||
{
|
||||
if ( _Thread_Dispatch_necessary ) {
|
||||
_CPU_ISR_Enable( level );
|
||||
|
||||
@@ -368,7 +368,7 @@ void _CORE_mutex_Seize_interrupt_blocking(
|
||||
#define _CORE_mutex_Seize_body( \
|
||||
_the_mutex, _id, _wait, _timeout, _level ) \
|
||||
do { \
|
||||
if ( _Thread_Dispatch_disable_level \
|
||||
if ( _Thread_Dispatch_in_critical_section() \
|
||||
&& (_wait) \
|
||||
&& (_System_state_Get() >= SYSTEM_STATE_BEGIN_MULTITASKING ) \
|
||||
) { \
|
||||
|
||||
@@ -46,6 +46,18 @@
|
||||
#define RTEMS_SCORE_THREAD_ENABLE_USER_PROVIDED_STACK_VIA_API
|
||||
#endif
|
||||
|
||||
#if defined(RTEMS_SMP) || \
|
||||
defined(RTEMS_HEAVY_STACK_DEBUG) || \
|
||||
defined(RTEMS_HEAVY_MALLOC_DEBUG)
|
||||
#define __THREAD_DO_NOT_INLINE_DISABLE_DISPATCH__
|
||||
#endif
|
||||
|
||||
#if defined(RTEMS_SMP) || \
|
||||
(CPU_INLINE_ENABLE_DISPATCH == FALSE) || \
|
||||
(__RTEMS_DO_NOT_INLINE_THREAD_ENABLE_DISPATCH__ == 1)
|
||||
#define __THREAD_DO_NOT_INLINE_ENABLE_DISPATCH__
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@@ -31,6 +31,64 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* This routine returns true if thread dispatch indicates
|
||||
* that we are in a critical section.
|
||||
*/
|
||||
RTEMS_INLINE_ROUTINE bool _Thread_Dispatch_in_critical_section(void)
|
||||
{
|
||||
if ( _Thread_Dispatch_disable_level == 0 )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine returns value of the the thread dispatch level.
|
||||
*/
|
||||
RTEMS_INLINE_ROUTINE uint32_t _Thread_Dispatch_get_disable_level(void)
|
||||
{
|
||||
return _Thread_Dispatch_disable_level;
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine sets thread dispatch level to the
|
||||
* value passed in.
|
||||
*/
|
||||
RTEMS_INLINE_ROUTINE uint32_t _Thread_Dispatch_set_disable_level(uint32_t value)
|
||||
{
|
||||
_Thread_Dispatch_disable_level = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* This rountine increments the thread dispatch level
|
||||
*/
|
||||
RTEMS_INLINE_ROUTINE uint32_t _Thread_Dispatch_increment_disable_level(void)
|
||||
{
|
||||
_Thread_Dispatch_disable_level++;
|
||||
return _Thread_Dispatch_disable_level;
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine decrements the thread dispatch level.
|
||||
*/
|
||||
RTEMS_INLINE_ROUTINE uint32_t _Thread_Dispatch_decrement_disable_level(void)
|
||||
{
|
||||
_Thread_Dispatch_disable_level--;
|
||||
return _Thread_Dispatch_disable_level;
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine initializes the thread dispatching subsystem.
|
||||
*/
|
||||
|
||||
RTEMS_INLINE_ROUTINE void _Thread_Dispatch_initialization( void )
|
||||
{
|
||||
_Thread_Dispatch_set_disable_level( 1 );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This routine halts multitasking and returns control to
|
||||
* the "thread" (i.e. the BSP) which initially invoked the
|
||||
@@ -150,51 +208,15 @@ RTEMS_INLINE_ROUTINE void _Thread_Deallocate_fp( void )
|
||||
* This routine prevents dispatching.
|
||||
*/
|
||||
|
||||
#if defined(RTEMS_HEAVY_STACK_DEBUG) || defined(RTEMS_HEAVY_MALLOC_DEBUG)
|
||||
#include <rtems/bspIo.h>
|
||||
#include <rtems/fatal.h>
|
||||
#include <rtems/stackchk.h>
|
||||
#include <rtems/score/sysstate.h>
|
||||
#include <rtems/score/heap.h>
|
||||
|
||||
/*
|
||||
* This is currently not defined in any .h file, so we have to
|
||||
* extern it here.
|
||||
*/
|
||||
extern Heap_Control *RTEMS_Malloc_Heap;
|
||||
#endif
|
||||
|
||||
#if defined ( __THREAD_DO_NOT_INLINE_DISABLE_DISPATCH__ )
|
||||
void _Thread_Disable_dispatch( void );
|
||||
#else
|
||||
RTEMS_INLINE_ROUTINE void _Thread_Disable_dispatch( void )
|
||||
{
|
||||
/*
|
||||
* This check is very brutal to system performance but is very helpful
|
||||
* at finding blown stack problems. If you have a stack problem and
|
||||
* need help finding it, then uncomment this code. Every system
|
||||
* call will check the stack and since mutexes are used frequently
|
||||
* in most systems, you might get lucky.
|
||||
*/
|
||||
#if defined(RTEMS_HEAVY_STACK_DEBUG)
|
||||
if (_System_state_Is_up(_System_state_Get()) && (_ISR_Nest_level == 0)) {
|
||||
if ( rtems_stack_checker_is_blown() ) {
|
||||
printk( "Stack blown!!\n" );
|
||||
rtems_fatal_error_occurred( 99 );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
_Thread_Dispatch_disable_level += 1;
|
||||
_Thread_Dispatch_increment_disable_level();
|
||||
RTEMS_COMPILER_MEMORY_BARRIER();
|
||||
|
||||
/*
|
||||
* This check is even more brutal than the other one. This enables
|
||||
* malloc heap integrity checking upon entry to every system call.
|
||||
*/
|
||||
#if defined(RTEMS_HEAVY_MALLOC_DEBUG)
|
||||
if ( _Thread_Dispatch_disable_level == 1 ) {
|
||||
_Heap_Walk( RTEMS_Malloc_Heap,99, false );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This routine allows dispatching to occur again. If this is
|
||||
@@ -203,21 +225,18 @@ RTEMS_INLINE_ROUTINE void _Thread_Disable_dispatch( void )
|
||||
* processor will be transferred to the heir thread.
|
||||
*/
|
||||
|
||||
#if ( (defined(CPU_INLINE_ENABLE_DISPATCH) && \
|
||||
(CPU_INLINE_ENABLE_DISPATCH == FALSE)) || \
|
||||
(__RTEMS_DO_NOT_INLINE_THREAD_ENABLE_DISPATCH__ == 1) )
|
||||
void _Thread_Enable_dispatch( void );
|
||||
#if defined ( __THREAD_DO_NOT_INLINE_ENABLE_DISPATCH__ )
|
||||
void _Thread_Enable_dispatch( void );
|
||||
#else
|
||||
/* inlining of enable dispatching must be true */
|
||||
RTEMS_INLINE_ROUTINE void _Thread_Enable_dispatch( void )
|
||||
{
|
||||
RTEMS_COMPILER_MEMORY_BARRIER();
|
||||
if ( (--_Thread_Dispatch_disable_level) == 0 )
|
||||
_Thread_Dispatch();
|
||||
}
|
||||
/* inlining of enable dispatching must be true */
|
||||
RTEMS_INLINE_ROUTINE void _Thread_Enable_dispatch( void )
|
||||
{
|
||||
RTEMS_COMPILER_MEMORY_BARRIER();
|
||||
if ( _Thread_Dispatch_decrement_disable_level() == 0 )
|
||||
_Thread_Dispatch();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* This routine allows dispatching to occur again. However,
|
||||
* no dispatching operation is performed even if this is the outer
|
||||
@@ -227,7 +246,7 @@ RTEMS_INLINE_ROUTINE void _Thread_Enable_dispatch( void )
|
||||
RTEMS_INLINE_ROUTINE void _Thread_Unnest_dispatch( void )
|
||||
{
|
||||
RTEMS_COMPILER_MEMORY_BARRIER();
|
||||
_Thread_Dispatch_disable_level -= 1;
|
||||
_Thread_Dispatch_decrement_disable_level();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -237,7 +256,7 @@ RTEMS_INLINE_ROUTINE void _Thread_Unnest_dispatch( void )
|
||||
|
||||
RTEMS_INLINE_ROUTINE bool _Thread_Is_dispatching_enabled( void )
|
||||
{
|
||||
return ( _Thread_Dispatch_disable_level == 0 );
|
||||
return ( _Thread_Dispatch_in_critical_section() == false );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -250,15 +269,6 @@ RTEMS_INLINE_ROUTINE bool _Thread_Is_context_switch_necessary( void )
|
||||
return ( _Thread_Dispatch_necessary );
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine initializes the thread dispatching subsystem.
|
||||
*/
|
||||
|
||||
RTEMS_INLINE_ROUTINE void _Thread_Dispatch_initialization( void )
|
||||
{
|
||||
_Thread_Dispatch_disable_level = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns true if the_thread is NULL and false otherwise.
|
||||
*/
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
* is the task stack of a thread that deletes itself. The thread dispatch
|
||||
* disable level is a way to detect this use case.
|
||||
*/
|
||||
if ( _Thread_Dispatch_disable_level == 0 ) {
|
||||
if ( !_Thread_Dispatch_in_critical_section() ) {
|
||||
Heap_Block *const next = block->Protection_begin.next_delayed_free_block;
|
||||
if ( next == NULL ) {
|
||||
_Heap_Protection_delay_block_free( heap, block );
|
||||
|
||||
@@ -39,7 +39,7 @@ bool _Protected_heap_Walk(
|
||||
*
|
||||
* NOTE: Dispatching is also disabled during initialization.
|
||||
*/
|
||||
if ( !_Thread_Dispatch_disable_level ) {
|
||||
if ( _Thread_Dispatch_in_critical_section() == false ) {
|
||||
_RTEMS_Lock_allocator();
|
||||
status = _Heap_Walk( the_heap, source, do_dump );
|
||||
_RTEMS_Unlock_allocator();
|
||||
|
||||
@@ -37,7 +37,7 @@ void rtems_smp_run_first_task(int cpu)
|
||||
* This is definitely a hack until we have SMP scheduling. Since there
|
||||
* is only one executing and heir right now, we have to fake this out.
|
||||
*/
|
||||
_Thread_Dispatch_disable_level = 1;
|
||||
_Thread_Dispatch_set_disable_level(1);
|
||||
_Thread_Executing = heir;
|
||||
_CPU_Context_switch_to_first_task_smp( &heir->Registers );
|
||||
}
|
||||
@@ -103,7 +103,7 @@ void rtems_smp_process_interrupt(void)
|
||||
|
||||
if ( message & RTEMS_BSP_SMP_SHUTDOWN ) {
|
||||
ISR_Level level;
|
||||
_Thread_Dispatch_disable_level = 0;
|
||||
_Thread_Dispatch_set_disable_level(0);
|
||||
_Per_CPU_Information[cpu].isr_nest_level = 0;
|
||||
_Per_CPU_Information[cpu].state = RTEMS_BSP_SMP_CPU_SHUTDOWN;
|
||||
_ISR_Disable( level );
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* _Thread_Disable_dispatch
|
||||
*
|
||||
*
|
||||
* COPYRIGHT (c) 1989-2011.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/thread.h>
|
||||
|
||||
#if defined ( __THREAD_DO_NOT_INLINE_DISABLE_DISPATCH__ )
|
||||
void _Thread_Disable_dispatch( void )
|
||||
{
|
||||
/*
|
||||
* This check is very brutal to system performance but is very helpful
|
||||
* at finding blown stack problems. If you have a stack problem and
|
||||
* need help finding it, then uncomment this code. Every system
|
||||
* call will check the stack and since mutexes are used frequently
|
||||
* in most systems, you might get lucky.
|
||||
*/
|
||||
#if defined(RTEMS_HEAVY_STACK_DEBUG)
|
||||
if (_System_state_Is_up(_System_state_Get()) && (_ISR_Nest_level == 0)) {
|
||||
if ( rtems_stack_checker_is_blown() ) {
|
||||
printk( "Stack blown!!\n" );
|
||||
rtems_fatal_error_occurred( 99 );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
_Thread_Dispatch_increment_disable_level();
|
||||
RTEMS_COMPILER_MEMORY_BARRIER();
|
||||
|
||||
/*
|
||||
* This check is even more brutal than the other one. This enables
|
||||
* malloc heap integrity checking upon entry to every system call.
|
||||
*/
|
||||
#if defined(RTEMS_HEAVY_MALLOC_DEBUG)
|
||||
if ( _Thread_Dispatch_get_disable_level() == 1 ) {
|
||||
_Heap_Walk( RTEMS_Malloc_Heap,99, false );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
* Thread Handler
|
||||
*
|
||||
*
|
||||
* COPYRIGHT (c) 1989-2009.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
@@ -34,35 +33,7 @@
|
||||
#include <rtems/score/timestamp.h>
|
||||
#endif
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_Enable_dispatch
|
||||
*
|
||||
* This kernel routine exits a context switch disable critical section.
|
||||
* This is the NOT INLINED version.
|
||||
*
|
||||
* Input parameters: NONE
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*
|
||||
* INTERRUPT LATENCY:
|
||||
* dispatch thread
|
||||
* no dispatch thread
|
||||
*/
|
||||
|
||||
#if ( (defined(CPU_INLINE_ENABLE_DISPATCH) && \
|
||||
(CPU_INLINE_ENABLE_DISPATCH == FALSE)) || \
|
||||
(__RTEMS_DO_NOT_INLINE_THREAD_ENABLE_DISPATCH__ == 1) )
|
||||
void _Thread_Enable_dispatch( void )
|
||||
{
|
||||
if ( --_Thread_Dispatch_disable_level )
|
||||
return;
|
||||
_Thread_Dispatch();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
/**
|
||||
* _Thread_Dispatch
|
||||
*
|
||||
* This kernel routine determines if a dispatch is needed, and if so
|
||||
@@ -72,10 +43,6 @@ void _Thread_Enable_dispatch( void )
|
||||
* ALTERNATE ENTRY POINTS:
|
||||
* void _Thread_Enable_dispatch();
|
||||
*
|
||||
* Input parameters: NONE
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*
|
||||
* INTERRUPT LATENCY:
|
||||
* dispatch thread
|
||||
* no dispatch thread
|
||||
@@ -91,7 +58,7 @@ void _Thread_Dispatch( void )
|
||||
_ISR_Disable( level );
|
||||
while ( _Thread_Dispatch_necessary == true ) {
|
||||
heir = _Thread_Heir;
|
||||
_Thread_Dispatch_disable_level = 1;
|
||||
_Thread_Dispatch_set_disable_level( 1 );
|
||||
_Thread_Dispatch_necessary = false;
|
||||
_Thread_Executing = heir;
|
||||
|
||||
@@ -185,7 +152,7 @@ void _Thread_Dispatch( void )
|
||||
}
|
||||
|
||||
post_switch:
|
||||
_Thread_Dispatch_disable_level = 0;
|
||||
_Thread_Dispatch_set_disable_level( 0 );
|
||||
|
||||
_ISR_Enable( level );
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* _Thread_Enable_dispatch
|
||||
*
|
||||
*
|
||||
* COPYRIGHT (c) 1989-2011.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/score/thread.h>
|
||||
|
||||
#ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
|
||||
#include <rtems/score/timestamp.h>
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* The following declares the dispatch critical section nesting
|
||||
* counter which is used to prevent context switches at inopportune
|
||||
* moments.
|
||||
*/
|
||||
|
||||
/**
|
||||
* _Thread_Enable_dispatch
|
||||
*
|
||||
* This kernel routine exits a context switch disable critical section.
|
||||
* This is the NOT INLINED version.
|
||||
*
|
||||
* INTERRUPT LATENCY:
|
||||
* dispatch thread
|
||||
* no dispatch thread
|
||||
*/
|
||||
#if defined (__THREAD_DO_NOT_INLINE_ENABLE_DISPATCH__ )
|
||||
void _Thread_Enable_dispatch( void )
|
||||
{
|
||||
if ( --_Thread_Dispatch_disable_level )
|
||||
return;
|
||||
_Thread_Dispatch();
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user