📄 kapi.cxx
字号:
//==========================================================================
//
// common/kapi.cxx
//
// C API Implementation
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
// Copyright (C) 2002 Nick Garnett
// Copyright (C) 2003 Jonathan Larmour
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): nickg, dsm
// Contributors: nickg
// Date: 1998-03-02
// Purpose: C API Implementation
// Description: C++ implementation of the C API
//
//
//####DESCRIPTIONEND####
//
//==========================================================================
#include <pkgconf/kernel.h>
#ifdef CYGFUN_KERNEL_API_C
#include <cyg/kernel/ktypes.h> // base kernel types
#include <cyg/infra/cyg_trac.h> // tracing macros
#include <cyg/infra/cyg_ass.h> // assertion macros
#include <cyg/kernel/instrmnt.h> // instrumentation
#include <cyg/kernel/diag.h>
#include <cyg/kernel/thread.hxx>
#include <cyg/kernel/thread.inl> // thread inlines
#include <cyg/kernel/sched.hxx>
#include <cyg/kernel/intr.hxx>
#include <cyg/kernel/clock.hxx>
#include <cyg/kernel/sema.hxx>
#include <cyg/kernel/flag.hxx>
#include <cyg/kernel/mutex.hxx>
#include <cyg/kernel/mbox.hxx>
#include <cyg/kernel/sched.inl> // scheduler inlines
#include <cyg/kernel/clock.inl> // clock inlines
#include <cyg/kernel/kapi.h> // C API
// -------------------------------------------------------------------------
// Magic new function
inline void *operator new(size_t size, void *ptr)
{
CYG_CHECK_DATA_PTR( ptr, "Bad pointer" );
return ptr;
}
// -------------------------------------------------------------------------
#ifdef CYGDBG_USE_ASSERTS
#define CYG_ASSERT_SIZES(cstruct, cxxstruct) \CYG_MACRO_START \ char *msg = "Size of C struct " #cstruct \ " != size of C++ struct " #cxxstruct ; \ CYG_ASSERT( sizeof(cstruct) == sizeof(cxxstruct) , msg ); \CYG_MACRO_END
#else
#define CYG_ASSERT_SIZES(cstruct, cxxstruct)
#endif
/*---------------------------------------------------------------------------*/
/* Scheduler operations */
/* Starts scheduler with created threads. Never returns. */
externC void cyg_scheduler_start(void) __THROW
{
Cyg_Scheduler::start();
}
/* Lock the scheduler. */
externC void cyg_scheduler_lock(void) __THROW
{
Cyg_Scheduler::lock();
// get_sched_lock() is unsigned, see below "cyg_ucount32 lock"
CYG_ASSERT( (0xff000000 & (Cyg_Scheduler::get_sched_lock())) == 0,
"Scheduler overlocked" );
}
/* Lock the scheduler, but never more than level=1. */
externC void cyg_scheduler_safe_lock(void) __THROW
{
Cyg_Scheduler::lock();
cyg_ucount32 slock = Cyg_Scheduler::get_sched_lock();
if (slock > 1)
Cyg_Scheduler::unlock();
// get_sched_lock() is unsigned, see below "cyg_ucount32 lock"
CYG_ASSERT( (0xff000000 & (Cyg_Scheduler::get_sched_lock())) == 0,
"Scheduler overlocked" );
}
/* Unlock the scheduler. */
externC void cyg_scheduler_unlock(void) __THROW
{
cyg_ucount32 slock = Cyg_Scheduler::get_sched_lock();
CYG_ASSERT( 0 < slock, "Scheduler not locked" );
// And program defensively too:
if ( 0 < slock )
Cyg_Scheduler::unlock();
}
/* Read the scheduler lock value. */
externC cyg_ucount32 cyg_scheduler_read_lock(void) __THROW
{
cyg_ucount32 slock = Cyg_Scheduler::get_sched_lock();
return slock;
}
/*---------------------------------------------------------------------------*/
/* Thread operations */
externC void cyg_thread_create(
cyg_addrword_t sched_info, /* scheduling info (eg pri) */
cyg_thread_entry_t *entry, /* entry point function */
cyg_addrword_t entry_data, /* entry data */
char *name, /* optional thread name */
void *stack_base, /* stack base, NULL = alloc */
cyg_ucount32 stack_size, /* stack size, 0 = default */
cyg_handle_t *handle, /* returned thread handle */
cyg_thread *thread /* put thread here */
) __THROW
{
CYG_ASSERT_SIZES( cyg_thread, Cyg_Thread );
Cyg_Thread *t = new((void *)thread) Cyg_Thread (
(CYG_ADDRWORD) sched_info,
(cyg_thread_entry *)entry,
(CYG_ADDRWORD) entry_data,
name,
(CYG_ADDRWORD) stack_base,
stack_size
);
t=t;
CYG_CHECK_DATA_PTR( handle, "Bad handle pointer" );
*handle = (cyg_handle_t)thread;
}
externC void cyg_thread_exit() __THROW
{
Cyg_Thread::exit();
}
externC cyg_bool_t cyg_thread_delete( cyg_handle_t thread ) __THROW
{
Cyg_Thread *th = (Cyg_Thread *)thread;
if( th->get_state() != Cyg_Thread::EXITED )
th->kill(); // encourage it to terminate
if( th->get_state() != Cyg_Thread::EXITED )
return false; // it didn't run yet, leave it up to the app to fix
th->~Cyg_Thread();
return true;
}
externC void cyg_thread_suspend(cyg_handle_t thread) __THROW
{
((Cyg_Thread *)thread)->suspend();
}
externC void cyg_thread_resume(cyg_handle_t thread) __THROW
{
Cyg_Thread *th = (Cyg_Thread *)thread;
// If we are resuming an exited thread then
// reinitialize it.
if( th->get_state() == Cyg_Thread::EXITED )
th->reinitialize();
th->resume();
}
externC void cyg_thread_kill( cyg_handle_t thread) __THROW
{
((Cyg_Thread *)thread)->kill();
}
externC void cyg_thread_release( cyg_handle_t thread) __THROW
{
((Cyg_Thread *)thread)->release();
}
externC void cyg_thread_yield() __THROW
{
Cyg_Thread::yield();
}
externC cyg_handle_t cyg_thread_self() __THROW
{
return (cyg_handle_t)Cyg_Thread::self();
}
externC cyg_uint16 cyg_thread_get_id( cyg_handle_t thread) __THROW
{
return ((Cyg_Thread *)thread)->get_unique_id();
}
// idle thread is not really a plain CygThread; danger.
externC cyg_handle_t cyg_thread_idle_thread() __THROW
{
extern Cyg_Thread idle_thread;
return (cyg_handle_t)&idle_thread;
}
/* Priority manipulation */
externC void cyg_thread_set_priority(
cyg_handle_t thread, cyg_priority_t priority ) __THROW
{
#ifdef CYGIMP_THREAD_PRIORITY
((Cyg_Thread *)thread)->set_priority(priority);
#endif
}
/* Get the normal priority, ie without any applied mutex inheritance or
* ceiling protocol. */
externC cyg_priority_t cyg_thread_get_priority(cyg_handle_t thread) __THROW
{
#ifdef CYGIMP_THREAD_PRIORITY
return ((Cyg_Thread *)thread)->get_priority();
#else
return 0;
#endif
}
/* Get the current priority, ie any applied mutex inheritance or
* ceiling protocol. */
externC cyg_priority_t cyg_thread_get_current_priority(cyg_handle_t thread) __THROW
{
#ifdef CYGIMP_THREAD_PRIORITY
return ((Cyg_Thread *)thread)->get_current_priority();
#else
return 0;
#endif
}
/* Deadline scheduling control (optional) */
externC void cyg_thread_deadline_wait(
cyg_tick_count_t start_time, /* abs earliest start time */
cyg_tick_count_t run_time, /* worst case execution time */
cyg_tick_count_t deadline /* absolute deadline */
) __THROW
{
CYG_ASSERT(0,"Not implemented");
}
externC void cyg_thread_delay(cyg_tick_count_t delay) __THROW
{
Cyg_Thread::self()->delay(delay);
}
/* Stack information */
externC cyg_addrword_t cyg_thread_get_stack_base(cyg_handle_t thread) __THROW
{
return ((Cyg_Thread *)thread)->get_stack_base();
}
externC cyg_uint32 cyg_thread_get_stack_size(cyg_handle_t thread) __THROW
{
return ((Cyg_Thread *)thread)->get_stack_size();
}
#ifdef CYGFUN_KERNEL_THREADS_STACK_MEASUREMENT
externC cyg_uint32 cyg_thread_measure_stack_usage(cyg_handle_t thread) __THROW
{
return ((Cyg_Thread *)thread)->measure_stack_usage();
}
#endif
/*---------------------------------------------------------------------------*/
/* Thread enumeration and information */
#ifdef CYGVAR_KERNEL_THREADS_LIST
cyg_bool_t cyg_thread_get_next( cyg_handle_t *current, cyg_uint16 *id ) __THROW
{
cyg_bool_t result = true;
// There is a minute but finite chance that the thread could have
// exitted since the previous cyg_thread_get_next() call, and we can't
// detect the ID mismatch further down. So be quite zealous with checking.
CYG_CHECK_DATA_PTRC( current );
CYG_CHECK_DATA_PTRC( id );
if ( *current != 0 )
CYG_CHECK_DATA_PTRC( *current );
Cyg_Scheduler::lock();
Cyg_Thread *thread = (Cyg_Thread *)*current;
CYG_ASSERT_ZERO_OR_CLASSC( thread );
if( *current == 0 )
{
thread = Cyg_Thread::get_list_head();
*current = (cyg_handle_t)thread;
*id = thread->get_unique_id();
}
else if( (thread->get_unique_id() == *id) &&
(thread = thread->get_list_next()) != NULL )
{
CYG_CHECK_DATA_PTRC( thread );
CYG_ASSERT_CLASSC( thread );
*current = (cyg_handle_t)thread;
*id = thread->get_unique_id();
}
else
{
*current = 0;
*id = 0;
result = false;
}
Cyg_Scheduler::unlock();
return result;
}
cyg_handle_t cyg_thread_find( cyg_uint16 id ) __THROW
{
Cyg_Scheduler::lock();
Cyg_Thread *thread = Cyg_Thread::get_list_head();
while( thread != NULL )
{
if( thread->get_unique_id() == id )
break;
thread = thread->get_list_next();
}
Cyg_Scheduler::unlock();
return (cyg_handle_t)thread;
}
#endif
cyg_bool_t cyg_thread_get_info( cyg_handle_t threadh,
cyg_uint16 id,
cyg_thread_info *info ) __THROW
{
cyg_bool_t result = true;
Cyg_Thread *thread = (Cyg_Thread *)threadh;
CYG_CHECK_DATA_PTRC( thread );
if ( NULL != info )
CYG_CHECK_DATA_PTRC( info );
Cyg_Scheduler::lock();
if( thread->get_unique_id() == id && info != NULL )
{
CYG_ASSERT_CLASSC( thread );
info->handle = threadh;
info->id = id;
info->state = thread->get_state();
#ifdef CYGVAR_KERNEL_THREADS_NAME
info->name = thread->get_name();
#else
info->name = NULL;
#endif
info->set_pri = thread->get_priority();
info->cur_pri = thread->get_current_priority();
info->stack_base = thread->get_stack_base();
info->stack_size = thread->get_stack_size();
#ifdef CYGFUN_KERNEL_THREADS_STACK_MEASUREMENT
info->stack_used = thread->measure_stack_usage();
#else
info->stack_used = 0;
#endif
}
else result = false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -