vxworks.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. // (C) Copyright Dustin Spicuzza 2009.
  2. // Adapted to vxWorks 6.9 by Peter Brockamp 2012.
  3. // Updated for VxWorks 7 by Brian Kuhl 2016
  4. // Use, modification and distribution are subject to the
  5. // Boost Software License, Version 1.0. (See accompanying file
  6. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. // See http://www.boost.org for most recent version.
  8. // Old versions of vxWorks (namely everything below 6.x) are
  9. // absolutely unable to use boost. Old STLs and compilers
  10. // like (GCC 2.96) . Do not even think of getting this to work,
  11. // a miserable failure will be guaranteed!
  12. //
  13. // VxWorks supports C++ linkage in the kernel with
  14. // DKMs (Downloadable Kernel Modules). But, until recently
  15. // the kernel used a C89 library with no
  16. // wide character support and no guarantee of ANSI C.
  17. // Regardless of the C library the same Dinkum
  18. // STL library is used in both contexts.
  19. //
  20. // Similarly the Dinkum abridged STL that supports the loosely specified
  21. // embedded C++ standard has not been tested and is unlikely to work
  22. // on anything but the simplest library.
  23. // ====================================================================
  24. //
  25. // Some important information regarding the usage of POSIX semaphores:
  26. // -------------------------------------------------------------------
  27. //
  28. // VxWorks as a real time operating system handles threads somewhat
  29. // different from what "normal" OSes do, regarding their scheduling!
  30. // This could lead to a scenario called "priority inversion" when using
  31. // semaphores, see http://en.wikipedia.org/wiki/Priority_inversion.
  32. //
  33. // Now, VxWorks POSIX-semaphores for DKM's default to the usage of
  34. // priority inverting semaphores, which is fine. On the other hand,
  35. // for RTP's it defaults to using non priority inverting semaphores,
  36. // which could easily pose a serious problem for a real time process.
  37. //
  38. // To change the default properties for POSIX-semaphores in VxWorks 7
  39. // enable core > CORE_USER Menu > DEFAULT_PTHREAD_PRIO_INHERIT
  40. //
  41. // In VxWorks 6.x so as to integrate with boost.
  42. // - Edit the file
  43. // installDir/vxworks-6.x/target/usr/src/posix/pthreadLib.c
  44. // - Around line 917 there should be the definition of the default
  45. // mutex attributes:
  46. //
  47. // LOCAL pthread_mutexattr_t defaultMutexAttr =
  48. // {
  49. // PTHREAD_INITIALIZED_OBJ, PTHREAD_PRIO_NONE, 0,
  50. // PTHREAD_MUTEX_DEFAULT
  51. // };
  52. //
  53. // Here, replace PTHREAD_PRIO_NONE by PTHREAD_PRIO_INHERIT.
  54. // - Around line 1236 there should be a definition for the function
  55. // pthread_mutexattr_init(). A couple of lines below you should
  56. // find a block of code like this:
  57. //
  58. // pAttr->mutexAttrStatus = PTHREAD_INITIALIZED_OBJ;
  59. // pAttr->mutexAttrProtocol = PTHREAD_PRIO_NONE;
  60. // pAttr->mutexAttrPrioceiling = 0;
  61. // pAttr->mutexAttrType = PTHREAD_MUTEX_DEFAULT;
  62. //
  63. // Here again, replace PTHREAD_PRIO_NONE by PTHREAD_PRIO_INHERIT.
  64. // - Finally, rebuild your VSB. This will rebuild the libraries
  65. // with the changed properties. That's it! Now, using boost should
  66. // no longer cause any problems with task deadlocks!
  67. //
  68. // ====================================================================
  69. // Block out all versions before vxWorks 6.x, as these don't work:
  70. // Include header with the vxWorks version information and query them
  71. #include <version.h>
  72. #if !defined(_WRS_VXWORKS_MAJOR) || (_WRS_VXWORKS_MAJOR < 6)
  73. # error "The vxWorks version you're using is so badly outdated,\
  74. it doesn't work at all with boost, sorry, no chance!"
  75. #endif
  76. // Handle versions above 5.X but below 6.9
  77. #if (_WRS_VXWORKS_MAJOR == 6) && (_WRS_VXWORKS_MINOR < 9)
  78. // TODO: Starting from what version does vxWorks work with boost?
  79. // We can't reasonably insert a #warning "" as a user hint here,
  80. // as this will show up with every file including some boost header,
  81. // badly bugging the user... So for the time being we just leave it.
  82. #endif
  83. // vxWorks specific config options:
  84. // --------------------------------
  85. #define BOOST_PLATFORM "vxWorks"
  86. // Generally available headers:
  87. #define BOOST_HAS_UNISTD_H
  88. #define BOOST_HAS_STDINT_H
  89. #define BOOST_HAS_DIRENT_H
  90. //#define BOOST_HAS_SLIST
  91. // vxWorks does not have installed an iconv-library by default,
  92. // so unfortunately no Unicode support from scratch is available!
  93. // Thus, instead it is suggested to switch to ICU, as this seems
  94. // to be the most complete and portable option...
  95. #ifndef BOOST_LOCALE_WITH_ICU
  96. #define BOOST_LOCALE_WITH_ICU
  97. #endif
  98. // Generally available functionality:
  99. #define BOOST_HAS_THREADS
  100. #define BOOST_HAS_NANOSLEEP
  101. #define BOOST_HAS_GETTIMEOFDAY
  102. #define BOOST_HAS_CLOCK_GETTIME
  103. #define BOOST_HAS_MACRO_USE_FACET
  104. // Generally available threading API's:
  105. #define BOOST_HAS_PTHREADS
  106. #define BOOST_HAS_SCHED_YIELD
  107. #define BOOST_HAS_SIGACTION
  108. // Functionality available for RTPs only:
  109. #ifdef __RTP__
  110. # define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
  111. # define BOOST_HAS_LOG1P
  112. # define BOOST_HAS_EXPM1
  113. #endif
  114. // Functionality available for DKMs only:
  115. #ifdef _WRS_KERNEL
  116. // Luckily, at the moment there seems to be none!
  117. #endif
  118. // These #defines allow detail/posix_features to work, since vxWorks doesn't
  119. // #define them itself for DKMs (for RTPs on the contrary it does):
  120. #ifdef _WRS_KERNEL
  121. # ifndef _POSIX_TIMERS
  122. # define _POSIX_TIMERS 1
  123. # endif
  124. # ifndef _POSIX_THREADS
  125. # define _POSIX_THREADS 1
  126. # endif
  127. // no sysconf( _SC_PAGESIZE) in kernel
  128. # define BOOST_THREAD_USES_GETPAGESIZE
  129. #endif
  130. #if (_WRS_VXWORKS_MAJOR < 7)
  131. // vxWorks-around: <time.h> #defines CLOCKS_PER_SEC as sysClkRateGet() but
  132. // miserably fails to #include the required <sysLib.h> to make
  133. // sysClkRateGet() available! So we manually include it here.
  134. # ifdef __RTP__
  135. # include <time.h>
  136. # include <sysLib.h>
  137. # endif
  138. // vxWorks-around: In <stdint.h> the macros INT32_C(), UINT32_C(), INT64_C() and
  139. // UINT64_C() are defined erroneously, yielding not a signed/
  140. // unsigned long/long long type, but a signed/unsigned int/long
  141. // type. Eventually this leads to compile errors in ratio_fwd.hpp,
  142. // when trying to define several constants which do not fit into a
  143. // long type! We correct them here by redefining.
  144. # include <cstdint>
  145. // Special behaviour for DKMs:
  146. // Some macro-magic to do the job
  147. # define VX_JOIN(X, Y) VX_DO_JOIN(X, Y)
  148. # define VX_DO_JOIN(X, Y) VX_DO_JOIN2(X, Y)
  149. # define VX_DO_JOIN2(X, Y) X##Y
  150. // Correctly setup the macros
  151. # undef INT32_C
  152. # undef UINT32_C
  153. # undef INT64_C
  154. # undef UINT64_C
  155. # define INT32_C(x) VX_JOIN(x, L)
  156. # define UINT32_C(x) VX_JOIN(x, UL)
  157. # define INT64_C(x) VX_JOIN(x, LL)
  158. # define UINT64_C(x) VX_JOIN(x, ULL)
  159. // #include Libraries required for the following function adaption
  160. # include <sys/time.h>
  161. #endif // _WRS_VXWORKS_MAJOR < 7
  162. #include <ioLib.h>
  163. #include <tickLib.h>
  164. #if defined(_WRS_KERNEL) && (_CPPLIB_VER < 700)
  165. // recent kernels use Dinkum clib v7.00+
  166. // with widechar but older kernels
  167. // do not have the <cwchar>-header,
  168. // but apparently they do have an intrinsic wchar_t meanwhile!
  169. # define BOOST_NO_CWCHAR
  170. // Lots of wide-functions and -headers are unavailable for DKMs as well:
  171. # define BOOST_NO_CWCTYPE
  172. # define BOOST_NO_SWPRINTF
  173. # define BOOST_NO_STD_WSTRING
  174. # define BOOST_NO_STD_WSTREAMBUF
  175. #endif
  176. // Use C-linkage for the following helper functions
  177. #ifdef __cplusplus
  178. extern "C" {
  179. #endif
  180. // vxWorks-around: The required functions getrlimit() and getrlimit() are missing.
  181. // But we have the similar functions getprlimit() and setprlimit(),
  182. // which may serve the purpose.
  183. // Problem: The vxWorks-documentation regarding these functions
  184. // doesn't deserve its name! It isn't documented what the first two
  185. // parameters idtype and id mean, so we must fall back to an educated
  186. // guess - null, argh... :-/
  187. // TODO: getprlimit() and setprlimit() do exist for RTPs only, for whatever reason.
  188. // Thus for DKMs there would have to be another implementation.
  189. #if defined ( __RTP__) && (_WRS_VXWORKS_MAJOR < 7)
  190. inline int getrlimit(int resource, struct rlimit *rlp){
  191. return getprlimit(0, 0, resource, rlp);
  192. }
  193. inline int setrlimit(int resource, const struct rlimit *rlp){
  194. return setprlimit(0, 0, resource, const_cast<struct rlimit*>(rlp));
  195. }
  196. #endif
  197. // vxWorks has ftruncate() only, so we do simulate truncate():
  198. inline int truncate(const char *p, off_t l){
  199. int fd = open(p, O_WRONLY);
  200. if (fd == -1){
  201. errno = EACCES;
  202. return -1;
  203. }
  204. if (ftruncate(fd, l) == -1){
  205. close(fd);
  206. errno = EACCES;
  207. return -1;
  208. }
  209. return close(fd);
  210. }
  211. #ifdef __GNUC__
  212. # define ___unused __attribute__((unused))
  213. #else
  214. # define ___unused
  215. #endif
  216. // Fake symlink handling by dummy functions:
  217. inline int symlink(const char* path1 ___unused, const char* path2 ___unused){
  218. // vxWorks has no symlinks -> always return an error!
  219. errno = EACCES;
  220. return -1;
  221. }
  222. inline ssize_t readlink(const char* path1 ___unused, char* path2 ___unused, size_t size ___unused){
  223. // vxWorks has no symlinks -> always return an error!
  224. errno = EACCES;
  225. return -1;
  226. }
  227. #if (_WRS_VXWORKS_MAJOR < 7)
  228. inline int gettimeofday(struct timeval *tv, void * /*tzv*/) {
  229. struct timespec ts;
  230. clock_gettime(CLOCK_MONOTONIC, &ts);
  231. tv->tv_sec = ts.tv_sec;
  232. tv->tv_usec = ts.tv_nsec / 1000;
  233. return 0;
  234. }
  235. #endif
  236. #ifdef __cplusplus
  237. } // extern "C"
  238. #endif
  239. /*
  240. * moved to os/utils/unix/freind_h/times.h in VxWorks 7
  241. * to avoid conflict with MPL operator times
  242. */
  243. #if (_WRS_VXWORKS_MAJOR < 7)
  244. # ifdef __cplusplus
  245. // vxWorks provides neither struct tms nor function times()!
  246. // We implement an empty dummy-function, simply setting the user
  247. // and system time to the half of thew actual system ticks-value
  248. // and the child user and system time to 0.
  249. // Rather ugly but at least it suppresses compiler errors...
  250. // Unfortunately, this of course *does* have an severe impact on
  251. // dependant libraries, actually this is chrono only! Here it will
  252. // not be possible to correctly use user and system times! But
  253. // as vxWorks is lacking the ability to calculate user and system
  254. // process times there seems to be no other possible solution.
  255. struct tms{
  256. clock_t tms_utime; // User CPU time
  257. clock_t tms_stime; // System CPU time
  258. clock_t tms_cutime; // User CPU time of terminated child processes
  259. clock_t tms_cstime; // System CPU time of terminated child processes
  260. };
  261. inline clock_t times(struct tms *t){
  262. struct timespec ts;
  263. clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
  264. clock_t ticks(static_cast<clock_t>(static_cast<double>(ts.tv_sec) * CLOCKS_PER_SEC +
  265. static_cast<double>(ts.tv_nsec) * CLOCKS_PER_SEC / 1000000.0));
  266. t->tms_utime = ticks/2U;
  267. t->tms_stime = ticks/2U;
  268. t->tms_cutime = 0; // vxWorks is lacking the concept of a child process!
  269. t->tms_cstime = 0; // -> Set the wait times for childs to 0
  270. return ticks;
  271. }
  272. namespace std {
  273. using ::times;
  274. }
  275. # endif // __cplusplus
  276. #endif // _WRS_VXWORKS_MAJOR < 7
  277. #ifdef __cplusplus
  278. extern "C" void bzero (void *, size_t); // FD_ZERO uses bzero() but doesn't include strings.h
  279. // Put the selfmade functions into the std-namespace, just in case
  280. namespace std {
  281. # ifdef __RTP__
  282. using ::getrlimit;
  283. using ::setrlimit;
  284. # endif
  285. using ::truncate;
  286. using ::symlink;
  287. using ::readlink;
  288. # if (_WRS_VXWORKS_MAJOR < 7)
  289. using ::gettimeofday;
  290. # endif
  291. }
  292. #endif // __cplusplus
  293. // Some more macro-magic:
  294. // vxWorks-around: Some functions are not present or broken in vxWorks
  295. // but may be patched to life via helper macros...
  296. // Include signal.h which might contain a typo to be corrected here
  297. #include <signal.h>
  298. #if (_WRS_VXWORKS_MAJOR < 7)
  299. # define getpagesize() sysconf(_SC_PAGESIZE) // getpagesize is deprecated anyway!
  300. inline int lstat(p, b) { return stat(p, b); } // lstat() == stat(), as vxWorks has no symlinks!
  301. #endif
  302. #ifndef S_ISSOCK
  303. # define S_ISSOCK(mode) ((mode & S_IFMT) == S_IFSOCK) // Is file a socket?
  304. #endif
  305. #ifndef FPE_FLTINV
  306. # define FPE_FLTINV (FPE_FLTSUB+1) // vxWorks has no FPE_FLTINV, so define one as a dummy
  307. #endif
  308. #if !defined(BUS_ADRALN) && defined(BUS_ADRALNR)
  309. # define BUS_ADRALN BUS_ADRALNR // Correct a supposed typo in vxWorks' <signal.h>
  310. #endif
  311. typedef int locale_t; // locale_t is a POSIX-extension, currently not present in vxWorks!
  312. // #include boilerplate code:
  313. #include <boost/config/detail/posix_features.hpp>
  314. // vxWorks lies about XSI conformance, there is no nl_types.h:
  315. #undef BOOST_HAS_NL_TYPES_H
  316. // vxWorks 7 adds C++11 support
  317. // however it is optional, and does not match exactly the support determined
  318. // by examining the Dinkum STL version and GCC version (or ICC and DCC)
  319. #if !( defined( _WRS_CONFIG_LANG_LIB_CPLUS_CPLUS_USER_2011) || defined(_WRS_CONFIG_LIBCPLUS_STD))
  320. # define BOOST_NO_CXX11_ADDRESSOF // C11 addressof operator on memory location
  321. # define BOOST_NO_CXX11_ALLOCATOR
  322. # define BOOST_NO_CXX11_ATOMIC_SMART_PTR
  323. # define BOOST_NO_CXX11_NUMERIC_LIMITS // max_digits10 in test/../print_helper.hpp
  324. # define BOOST_NO_CXX11_SMART_PTR
  325. # define BOOST_NO_CXX11_STD_ALIGN
  326. # define BOOST_NO_CXX11_HDR_ARRAY
  327. # define BOOST_NO_CXX11_HDR_ATOMIC
  328. # define BOOST_NO_CXX11_HDR_CHRONO
  329. # define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE
  330. # define BOOST_NO_CXX11_HDR_FORWARD_LIST //serialization/test/test_list.cpp
  331. # define BOOST_NO_CXX11_HDR_FUNCTIONAL
  332. # define BOOST_NO_CXX11_HDR_FUTURE
  333. # define BOOST_NO_CXX11_HDR_MUTEX
  334. # define BOOST_NO_CXX11_HDR_RANDOM //math/../test_data.hpp
  335. # define BOOST_NO_CXX11_HDR_RATIO
  336. # define BOOST_NO_CXX11_HDR_REGEX
  337. # define BOOST_NO_CXX14_HDR_SHARED_MUTEX
  338. # define BOOST_NO_CXX11_HDR_SYSTEM_ERROR
  339. # define BOOST_NO_CXX11_HDR_THREAD
  340. # define BOOST_NO_CXX11_HDR_TYPEINDEX
  341. # define BOOST_NO_CXX11_HDR_TYPE_TRAITS
  342. # define BOOST_NO_CXX11_HDR_TUPLE
  343. # define BOOST_NO_CXX11_HDR_UNORDERED_MAP
  344. # define BOOST_NO_CXX11_HDR_UNORDERED_SET
  345. #else
  346. # ifndef BOOST_SYSTEM_NO_DEPRECATED
  347. # define BOOST_SYSTEM_NO_DEPRECATED // workaround link error in spirit
  348. # endif
  349. #endif
  350. // NONE is used in enums in lamda and other libraries
  351. #undef NONE
  352. // restrict is an iostreams class
  353. #undef restrict
  354. // affects some typeof tests
  355. #undef V7
  356. // use fake poll() from Unix layer in ASIO to get full functionality
  357. // most libraries will use select() but this define allows 'iostream' functionality
  358. // which is based on poll() only
  359. #if (_WRS_VXWORKS_MAJOR > 6)
  360. # ifndef BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR
  361. # define BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR
  362. # endif
  363. #else
  364. # define BOOST_ASIO_DISABLE_SERIAL_PORT
  365. #endif