⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fosi_internal.cpp

📁 机器人开源项目orocos的源代码
💻 CPP
字号:
/***************************************************************************  tag: Peter Soetens  Wed Jan 18 14:11:39 CET 2006  fosi_internal.hpp                         fosi_internal.hpp -  description                           -------------------    begin                : Wed January 18 2006    copyright            : (C) 2006 Peter Soetens    email                : peter.soetens@mech.kuleuven.be  *************************************************************************** *   This library 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;                 * *   version 2 of the License.                                             * *                                                                         * *   As a special exception, you may use this file as part of a free       * *   software library without restriction.  Specifically, if other files   * *   instantiate templates or use macros or inline functions from this     * *   file, or you compile this file and link it with other files to        * *   produce an executable, this file does not by itself cause the         * *   resulting executable to be covered by the GNU General Public          * *   License.  This exception does not however invalidate any other        * *   reasons why the executable file might be covered by the GNU General   * *   Public License.                                                       * *                                                                         * *   This library 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     * *   Lesser General Public License for more details.                       * *                                                                         * *   You should have received a copy of the GNU General Public             * *   License along with this library; if not, write to the Free Software   * *   Foundation, Inc., 59 Temple Place,                                    * *   Suite 330, Boston, MA  02111-1307  USA                                * *                                                                         * ***************************************************************************/  #define OROBLD_OS_INTERNAL#include "os/ThreadInterface.hpp"#include "fosi.h"#include "../fosi_internal_interface.hpp"#include <cassert>#define INTERNAL_QUAL #include "Logger.hpp"namespace RTT{ namespace OS {    namespace detail {        INTERNAL_QUAL int rtos_task_create_main(RTOS_TASK* main)        {            // first check if root.            if ( geteuid() != 0 ) {                printf( "You are not root. This program requires that you are root.\n");                exit(1);            }            // locking of all memory for this process            int rv = mlockall(MCL_CURRENT | MCL_FUTURE);            if ( rv != 0 ) {                perror( "rtos_task_create_main: Could not lock memory using mlockall" ); // Logger unavailable.            }            struct sched_param param;            // we set the MT to the highest sched priority to allow the console            // to interrupt a loose running thread.            param.sched_priority = sched_get_priority_max(ORO_SCHED_OTHER);            if (param.sched_priority != -1 )                sched_setscheduler( 0, ORO_SCHED_OTHER, &param);            const char* mt_name = "MainThread";            main->sched_type = SCHED_XENOMAI_SOFT; // default for MainThread            main->name = strncpy( (char*)malloc( (strlen(mt_name)+1)*sizeof(char) ), mt_name, strlen(mt_name)+1 );            int ret = -1;            while( ret != 0) {                // name, priority, mode                if ( (ret = rt_task_shadow( &(main->xenotask),mt_name, 10, 0)) != 0 ) {                    if ( ret == -ENOMEM ) {                        // fail: abort                        printf( "Cannot rt_task_create() MainThread: Out of memory.\n");                        exit(1);                    }                    if ( ret == -EBUSY ) {                        // ok: we are a xeno thread (may log() ):                        log(Info) << "MainThread already a Xenomai task." <<endlog();                        break;                    }                    if ( ret == -EEXIST ) {                        // fail: retry without using a name.                        mt_name = 0; // do not register                        continue;                    }                    if ( ret == -EPERM ) {                        // fail: abort                        printf( "Can not rt_task_create() MainThread: No permission.\n");                        exit(1);                    }                    // uncaught error: abort                    printf( "Can not rt_task_create() MainThread: Error %d.\n",ret);                    exit(1);                }            }            // We are a xeno thread now:            // Only use Logger after this point (i.e. when rt_task_shadow was succesful).            if ( mt_name == 0) {                log(Warning) << "'MainThread' name was already in use.\n" <<endlog();            }#ifdef OROSEM_OS_XENO_PERIODIC# if CONFIG_XENO_VERSION_MAJOR == 2 && CONFIG_XENO_VERSION_MINOR == 0            // time in nanoseconds            rt_timer_start( ORODAT_OS_XENO_PERIODIC_TICK*1000*1000*1000 );            Logger::In in("Scheduler");            Logger::log() << Logger::Info << "Xenomai Periodic Timer started using "<<ORODAT_OS_XENO_PERIODIC_TICK<<" seconds." << Logger::endl;# else            Logger::In in("Scheduler");            Logger::log() << Logger::Error << "Set Xenomai Periodic Timer using the Linux kernel configuration." << Logger::endl;# endif#else# if CONFIG_XENO_VERSION_MAJOR == 2 && CONFIG_XENO_VERSION_MINOR == 0            rt_timer_start( TM_ONESHOT );            Logger::log() << Logger::Info << "Xenomai Periodic Timer runs in preemptive 'one-shot' mode." << Logger::endl;# else#  if CONFIG_XENO_OPT_TIMING_PERIODIC            Logger::log() << Logger::Info << "Xenomai Periodic Timer configured in 'periodic' mode." << Logger::endl;#   else            Logger::log() << Logger::Info << "Xenomai Periodic Timer runs in preemptive 'one-shot' mode." << Logger::endl;#  endif# endif#endif            Logger::log() << Logger::Debug << "Xenomai Timer and Main Task Created" << Logger::endl;            return 0;        }        INTERNAL_QUAL int rtos_task_delete_main(RTOS_TASK* main_task)        {            rt_task_delete( &(main_task->xenotask) );            free (main_task->name);            munlockall();            return 0;        }        struct XenoCookie {            void* data;            void* (*wrapper)(void*);        };        INTERNAL_QUAL void rtos_xeno_thread_wrapper( void* cookie )        {            // store 'self'            RTOS_TASK* task = ((ThreadInterface*)((XenoCookie*)cookie)->data)->getTask();            task->xenoptr = rt_task_self();            // create hard mode by default.            rt_task_set_mode( 0, T_PRIMARY, 0 );            // call user function            ((XenoCookie*)cookie)->wrapper( ((XenoCookie*)cookie)->data );            free(cookie);        }        INTERNAL_QUAL int rtos_task_create(RTOS_TASK* task,                                           int priority,                                           const char* name,                                           int sched_type,                                           void * (*start_routine)(void *),                                           ThreadInterface* obj)         {            if ( priority < 1 )                priority = 1;            if ( priority > 99)                priority = 99;            XenoCookie* xcookie = (XenoCookie*)malloc( sizeof(XenoCookie) );            xcookie->data = obj;            xcookie->wrapper = start_routine;            if ( name == 0 || strlen(name) == 0)                name = "XenoThread";            task->name = strncpy( (char*)malloc( (strlen(name)+1)*sizeof(char) ), name, strlen(name)+1 );            task->sched_type = SCHED_XENOMAI_HARD; // default            int rv;            // task, name, stack, priority, mode, fun, arg            // UGLY, how can I check in Xenomai that a name is in use before calling rt_task_spawn ???            rv = rt_task_spawn(&(task->xenotask), name, 0, priority, 0, rtos_xeno_thread_wrapper, xcookie);            if ( rv == -EEXIST ) {                free( task->name );                task->name = strncpy( (char*)malloc( (strlen(name)+2)*sizeof(char) ), name, strlen(name)+1 );                task->name[ strlen(name) ] = '0';                task->name[ strlen(name)+1 ] = 0;                while ( rv == -EEXIST &&  task->name[ strlen(name) ] != '9') {                    task->name[ strlen(name) ] += 1;                    rv = rt_task_spawn(&(task->xenotask), task->name, 0, priority, 0, rtos_xeno_thread_wrapper, xcookie);                }            }            if ( rv == -EEXIST ) {                log(Warning) << name << ": an object with that name is already existing in Xenomai." << endlog();                rv = rt_task_spawn(&(task->xenotask), 0, 0, priority, 0, rtos_xeno_thread_wrapper, xcookie);            }            if ( rv != 0) {                log(Error) << name << " : CANNOT INIT Xeno TASK " << task->name <<" error code: "<< rv << endlog();            }            return rv;        }        INTERNAL_QUAL void rtos_task_yield(RTOS_TASK*) {            rt_task_yield();        }    INTERNAL_QUAL int rtos_task_check_scheduler(int* scheduler)    {        if (*scheduler != SCHED_XENOMAI_HARD && *scheduler != SCHED_XENOMAI_SOFT ) {            log(Error) << "Unknown scheduler type." <<endlog();            *scheduler = SCHED_XENOMAI_SOFT;            return -1;        }        return 0;    }	INTERNAL_QUAL int rtos_task_check_priority(int* scheduler, int* priority)    {        int ret = 0;        // check scheduler first.        ret = rtos_task_check_scheduler(scheduler);        // correct priority        // Hard & Soft:        if (*priority <= 0){            log(Warning) << "Forcing priority ("<<*priority<<") of thread to 1." <<endlog();            *priority = 1;            ret = -1;        }        if (*priority >= 99){            log(Warning) << "Forcing priority ("<<*priority<<") of thread to 99." <<endlog();            *priority = 99;            ret = -1;        }        return ret;    }        // we could implement here the interrupt shield logic.        INTERNAL_QUAL int rtos_task_set_scheduler(RTOS_TASK* t, int sched_type) {            Logger::In in( t->name );            // xenoptr was initialised from the thread wrapper.            if (t->xenoptr != rt_task_self() ) {                log(Error) << "Xenomai can not change the scheduler type from another thread." <<endlog();                return -1;            }            if ( rtos_task_check_scheduler( &sched_type ) == -1)                return -1;            if (sched_type == SCHED_XENOMAI_HARD)                if ( rt_task_set_mode( 0, T_PRIMARY, 0 ) == 0 ) {                    t->sched_type = SCHED_XENOMAI_HARD;                    return 0;                } else                    return -1;            else if ( sched_type == SCHED_XENOMAI_SOFT)                 if (rt_task_set_mode( T_PRIMARY, 0, 0 ) == 0 ) {                    t->sched_type = SCHED_XENOMAI_SOFT;                    return 0;                } else                    return -1;            assert(false);            return -1;        }        INTERNAL_QUAL int rtos_task_get_scheduler(const RTOS_TASK* mytask) {#if 0            // WORK AROUND constness: (need non-const mytask)            RT_TASK* tt = mytask->xenoptr;            RT_TASK_INFO info;            if ( tt )                if ( rt_task_inquire( tt, &info) == 0 )                     if ( info.status & XNRELAX )                        return SCHED_XENOMAI_SOFT;                    else                        return SCHED_XENOMAI_HARD;            return -1;#else            return mytask->sched_type;#endif        }        INTERNAL_QUAL void rtos_task_make_periodic(RTOS_TASK* mytask, NANO_TIME nanosecs )        {            if (nanosecs == 0) {                rt_task_set_periodic( &(mytask->xenotask), TM_NOW, TM_INFINITE);            }            else {                rt_task_set_periodic( &(mytask->xenotask), TM_NOW, rt_timer_ns2ticks(nanosecs) );            }        }        INTERNAL_QUAL void rtos_task_set_period( RTOS_TASK* mytask, NANO_TIME nanosecs )        {            rtos_task_make_periodic( mytask, nanosecs);            //rt_task_set_period(&(mytask->xenotask), rt_timer_ns2ticks( nanosecs ));        }        INTERNAL_QUAL int rtos_task_wait_period( RTOS_TASK* mytask )        {            // detect overrun.#if CONFIG_XENO_VERSION_MAJOR == 2 && CONFIG_XENO_VERSION_MINOR == 0            if ( rt_task_wait_period() == -ETIMEDOUT)                 return 1;#else // 2.1, 2.2, 2.3,...            long unsigned int overrun = 0;            rt_task_wait_period(&overrun);            if ( overrun != 0)                return 1;#endif            return 0;        }        INTERNAL_QUAL const char* rtos_task_get_name(const RTOS_TASK* mytask) {            return mytask->name;        }        INTERNAL_QUAL int rtos_task_get_priority(const RTOS_TASK* mytask) {            RT_TASK_INFO info;            // WORK AROUND constness: (need non-const mytask)            RT_TASK* tt = mytask->xenoptr;            if ( tt )                if ( rt_task_inquire ( tt, &info) == 0 )                     return info.bprio;            return -1;        }        INTERNAL_QUAL void rtos_task_delete(RTOS_TASK* mytask) {            rt_task_delete(&(mytask->xenotask));        }        INTERNAL_QUAL int rtos_task_set_priority(RTOS_TASK * mytask, int priority)        {            // ignorint 'type'            RT_TASK* tt = mytask->xenoptr;            if ( tt )                return rt_task_set_priority( tt, priority);            return -1;        }    }}}#undef INTERNAL_QUAL

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -