ThreadImplLxrt38.cpp
Go to the documentation of this file.
00001 // this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
00002 
00003 // -- BEGIN LICENSE BLOCK ----------------------------------------------
00004 // This file is part of FZIs ic_workspace.
00005 //
00006 // This program is free software licensed under the LGPL
00007 // (GNU LESSER GENERAL PUBLIC LICENSE Version 3).
00008 // You can find a copy of this license in LICENSE folder in the top
00009 // directory of the source code.
00010 //
00011 // © Copyright 2016 FZI Forschungszentrum Informatik, Karlsruhe, Germany
00012 //
00013 // -- END LICENSE BLOCK ------------------------------------------------
00014 
00015 //----------------------------------------------------------------------
00022 //----------------------------------------------------------------------
00023 #include "ThreadImplLxrt38.h"
00024 
00025 #include <icl_core/internal_raw_debug.h>
00026 #include <icl_core/os_lxrt.h>
00027 
00028 #include "Thread.h"
00029 #include "Logging.h"
00030 
00031 #define DEFAULT_STACK_SIZE 0x4000
00032 
00033 namespace icl_core {
00034 namespace thread {
00035 
00036 ThreadImplLxrt38::ThreadImplLxrt38(Thread *thread, const icl_core::String& description,
00037                                    icl_core::ThreadPriority priority)
00038   : m_thread_id(0),
00039     m_thread(thread),
00040     m_priority(priority),
00041     m_description(description),
00042     m_rt_task(NULL),
00043     m_rt_start_sync(NULL)
00044 { }
00045 
00046 ThreadImplLxrt38::~ThreadImplLxrt38()
00047 {
00048   // Ensure that the thread is really destroyed.
00049   join();
00050 
00051   if (m_rt_start_sync == NULL)
00052   {
00053     // Nothing to be done here.
00054   }
00055   else
00056   {
00057     rt_sem_delete(m_rt_start_sync);
00058     m_rt_start_sync = NULL;
00059   }
00060 }
00061 
00062 void ThreadImplLxrt38::cancel()
00063 {
00064   if (m_thread_id == 0)
00065   {
00066     // Nothing to be done here. The thread has already been destroyed.
00067   }
00068   else
00069   {
00070     pthread_cancel_rt(m_thread_id);
00071     pthread_join_rt(m_thread_id, NULL);
00072     m_thread_id = 0;
00073     m_rt_task = NULL;
00074   }
00075 }
00076 
00077 bool ThreadImplLxrt38::isHardRealtime() const
00078 {
00079   return m_priority < 0;
00080 }
00081 
00082 bool ThreadImplLxrt38::executesHardRealtime() const
00083 {
00084   return os::isThisHRT();
00085 }
00086 
00087 void ThreadImplLxrt38::join()
00088 {
00089   if (m_thread_id == 0)
00090   {
00091     // Nothing to be done here. The thread has already been destroyed.
00092   }
00093   else
00094   {
00095     pthread_join_rt(m_thread_id, NULL);
00096     m_thread_id = 0;
00097     m_rt_task = NULL;
00098   }
00099 }
00100 
00101 icl_core::ThreadPriority ThreadImplLxrt38::priority() const
00102 {
00103   return m_priority;
00104 }
00105 
00106 bool ThreadImplLxrt38::setHardRealtime(bool hard_realtime)
00107 {
00108   if (hard_realtime && !os::isThisHRT())
00109   {
00110     rt_make_hard_real_time();
00111     return os::isThisHRT();
00112   }
00113   else if (!hard_realtime && os::isThisHRT())
00114   {
00115     rt_make_soft_real_time();
00116     return !os::isThisHRT();
00117   }
00118   else
00119   {
00120     return false;
00121   }
00122 }
00123 
00124 bool ThreadImplLxrt38::setPriority(icl_core::ThreadPriority /*priority*/)
00125 {
00126   // TODO: Make this work!
00127   /*
00128     if (m_rt_task != NULL) {
00129     int ret = rt_change_prio(m_rt_task, abs(priority));
00130     if (ret == 0) {
00131     m_priority = priority;
00132 
00133     if (priority > 0 && IsHardRealtimeThread()) {
00134     rt_make_soft_real_time();
00135     } else if (priority < 0 && !IsHardRealtimeThread()) {
00136     rt_make_hard_real_time();
00137     }
00138 
00139     return true;
00140     }
00141     }
00142   */
00143 
00144   return false;
00145 }
00146 
00147 bool ThreadImplLxrt38::start()
00148 {
00149   m_rt_start_sync = rt_typed_sem_init(size_t(this), 2, CNT_SEM | PRIO_Q);
00150   if (m_rt_start_sync == NULL)
00151   {
00152     // We cannot proceed, if this happens!
00153   }
00154   else
00155   {
00156     if (pthread_create(&m_thread_id, NULL, ThreadImplLxrt38::runThread, this))
00157     {
00158       m_thread_id = 0;
00159       m_rt_task = NULL;
00160 
00161       rt_sem_delete(m_rt_start_sync);
00162       m_rt_start_sync = NULL;
00163     }
00164     else
00165     {
00166       rt_sem_wait_barrier(m_rt_start_sync);
00167     }
00168   }
00169 
00170   return m_thread_id != 0;
00171 }
00172 
00173 icl_core::ThreadId ThreadImplLxrt38::threadId() const
00174 {
00175   return ::icl_core::ThreadId(m_thread_id);
00176 }
00177 
00178 void * ThreadImplLxrt38::runThread(void *arg)
00179 {
00180   ThreadImplLxrt38 *self = static_cast<ThreadImplLxrt38*>(arg);
00181 
00182   if (self->m_rt_start_sync == NULL)
00183   {
00184     // Technically, this can never happen because this condition is
00185     // already checked in the Start() function. But who knows!
00186     PRINTF("ERROR: NULL thread start barrier!\n");
00187   }
00188   else
00189   {
00190     self->m_rt_task = rt_task_init(getpid() + pthread_self_rt(), abs(self->m_priority),
00191                                    DEFAULT_STACK_SIZE, 0);
00192     if (self->m_rt_task == NULL)
00193     {
00194       PRINTF("ERROR: Cannot initialize LXRT task %lu!\n", self->m_thread_id);
00195       PRINTF("       Probably another thread with the same name already exists.\n");
00196 
00197       // Let the thread, which started us, continue!
00198       rt_sem_wait_barrier(self->m_rt_start_sync);
00199     }
00200     else
00201     {
00202       if (self->m_priority < 0)
00203       {
00204         rt_make_hard_real_time();
00205         if (!rt_is_hard_real_time(rt_buddy()))
00206         {
00207           PRINTF("ERROR: Setting thread %lu to hard real-time failed!\n", self->m_thread_id);
00208         }
00209         else
00210         {
00211           // Everything worked as expected, so no message here.
00212         }
00213       }
00214       else
00215       {
00216         // This is a soft realtime thread, so nothing additional has
00217         // to be done here.
00218       }
00219 
00220       rt_sem_wait_barrier(self->m_rt_start_sync);
00221 
00222       self->m_thread->runThread();
00223 
00224       // Remark: It does not hurt to call this in a soft realtime
00225       // thread, so just skip the hard realtime test.
00226       rt_make_soft_real_time();
00227     }
00228   }
00229 
00230   return NULL;
00231 }
00232 
00233 }
00234 }


fzi_icl_core
Author(s):
autogenerated on Thu Jun 6 2019 20:22:24