ThreadImplLxrt35.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 "ThreadImplLxrt35.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 ThreadImplLxrt35::ThreadImplLxrt35(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 ThreadImplLxrt35::~ThreadImplLxrt35()
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     pthread_barrier_destroy_rt(m_rt_start_sync);
00058     delete m_rt_start_sync;
00059     m_rt_start_sync = NULL;
00060   }
00061 }
00062 
00063 void ThreadImplLxrt35::cancel()
00064 {
00065   if (m_thread_id == 0)
00066   {
00067     // Nothing to be done here. The thread has already been destroyed.
00068   }
00069   else
00070   {
00071     pthread_cancel_rt(m_thread_id);
00072     pthread_join_rt(m_thread_id, NULL);
00073     m_thread_id = 0;
00074     m_rt_task = NULL;
00075   }
00076 }
00077 
00078 bool ThreadImplLxrt35::isHardRealtime() const
00079 {
00080   return m_priority < 0;
00081 }
00082 
00083 bool ThreadImplLxrt35::executesHardRealtime() const
00084 {
00085   return os::isThisHRT();
00086 }
00087 
00088 void ThreadImplLxrt35::join()
00089 {
00090   if (m_thread_id == 0)
00091   {
00092     // Nothing to be done here. The thread has already been destroyed.
00093   }
00094   else
00095   {
00096     pthread_join_rt(m_thread_id, NULL);
00097     m_thread_id = 0;
00098     m_rt_task = NULL;
00099   }
00100 }
00101 
00102 icl_core::ThreadPriority ThreadImplLxrt35::priority() const
00103 {
00104   return m_priority;
00105 }
00106 
00107 bool ThreadImplLxrt35::setHardRealtime(bool hard_realtime)
00108 {
00109   if (hard_realtime && !os::isThisHRT())
00110   {
00111     rt_make_hard_real_time();
00112     return os::isThisHRT();
00113   }
00114   else if (!hard_realtime && os::isThisHRT())
00115   {
00116     rt_make_soft_real_time();
00117     return !os::isThisHRT();
00118   }
00119   else
00120   {
00121     return false;
00122   }
00123 }
00124 
00125 bool ThreadImplLxrt35::setPriority(icl_core::ThreadPriority /*priority*/)
00126 {
00127   // TODO: Make this work!
00128   /*
00129     if (m_rt_task != NULL) {
00130     int ret = rt_change_prio(m_rt_task, abs(priority));
00131     if (ret == 0) {
00132     m_priority = priority;
00133 
00134     if (priority > 0 && IsHardRealtimeThread()) {
00135     rt_make_soft_real_time();
00136     } else if (priority < 0 && !IsHardRealtimeThread()) {
00137     rt_make_hard_real_time();
00138     }
00139 
00140     return true;
00141     }
00142     }
00143   */
00144 
00145   return false;
00146 }
00147 
00148 bool ThreadImplLxrt35::start()
00149 {
00150   m_rt_start_sync = new (std::nothrow) pthread_barrier_t;
00151   if (m_rt_start_sync == NULL)
00152   {
00153     // We cannot proceed, if this happens!
00154   }
00155   else
00156   {
00157     pthread_barrier_init_rt(m_rt_start_sync, NULL, 2);
00158 
00159     if (pthread_create(&m_thread_id, NULL, ThreadImplLxrt35::runThread, this))
00160     {
00161       m_thread_id = 0;
00162       m_rt_task = NULL;
00163 
00164       pthread_barrier_destroy_rt(m_rt_start_sync);
00165       delete m_rt_start_sync;
00166       m_rt_start_sync = NULL;
00167     }
00168     else
00169     {
00170       pthread_barrier_wait_rt(m_rt_start_sync);
00171     }
00172   }
00173 
00174   return m_thread_id != 0;
00175 }
00176 
00177 icl_core::ThreadId ThreadImplLxrt35::threadId() const
00178 {
00179   return ::icl_core::ThreadId(m_thread_id);
00180 }
00181 
00182 void *ThreadImplLxrt35::runThread(void *arg)
00183 {
00184   ThreadImplLxrt35 *self = static_cast<ThreadImplLxrt35*>(arg);
00185 
00186   if (self->m_rt_start_sync == NULL)
00187   {
00188     // Technically, this can never happen because this condition is
00189     // already checked in the Start() function. But who knows!
00190     PRINTF("ERROR: NULL thread start barrier!\n");
00191   }
00192   else
00193   {
00194     self->m_rt_task = rt_task_init(getpid() + pthread_self_rt(), abs(self->m_priority),
00195                                    DEFAULT_STACK_SIZE, 0);
00196     if (self->m_rt_task == NULL)
00197     {
00198       PRINTF("ERROR: Cannot initialize LXRT task %lu!\n", self->m_thread_id);
00199       PRINTF("       Probably another thread with the same name already exists.\n");
00200 
00201       // Let the thread, which started us, continue!
00202       pthread_barrier_wait_rt(self->m_rt_start_sync);
00203     }
00204     else
00205     {
00206       if (self->m_priority < 0)
00207       {
00208         rt_make_hard_real_time();
00209         if (!rt_is_hard_real_time(rt_buddy()))
00210         {
00211           PRINTF("ERROR: Setting thread %lu to hard real-time failed!\n", self->m_thread_id);
00212         }
00213         else
00214         {
00215           // Everything worked as expected, so no message here.
00216         }
00217       }
00218       else
00219       {
00220         // This is a soft realtime thread, so nothing additional has
00221         // to be done here.
00222       }
00223 
00224       pthread_barrier_wait_rt(self->m_rt_start_sync);
00225 
00226       self->m_thread->runThread();
00227 
00228       // Remark: It does not hurt to call this in a soft realtime
00229       // thread, so just skip the hard realtime test.
00230       rt_make_soft_real_time();
00231     }
00232   }
00233 
00234   return NULL;
00235 }
00236 
00237 }
00238 }


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