| 28 | // ==================================================================== |
| 29 | // |
| 30 | // Some important information regarding the usage of POSIX semaphores: |
| 31 | // ------------------------------------------------------------------- |
| 32 | // |
| 33 | // VxWorks as a real time operating system handles threads somewhat |
| 34 | // different from what "normal" OSes do, regarding their scheduling! |
| 35 | // This could lead to a scenario called "priority inversion" when using |
| 36 | // semaphores, see http://en.wikipedia.org/wiki/Priority_inversion. |
| 37 | // |
| 38 | // Now, VxWorks POSIX-semaphores for DKM's default to the usage of |
| 39 | // priority inverting semaphores, which is fine. On the other hand, |
| 40 | // for RTP's it defaults to using non priority inverting semaphores, |
| 41 | // which could easily pose a serious problem for a real time process, |
| 42 | // i.e. deadlocks! To overcome this two possibilities do exist: |
| 43 | // |
| 44 | // a) Patch every piece of boost that uses semaphores to instanciate |
| 45 | // the proper type of semaphores. This is non-intrusive with respect |
| 46 | // to the OS and could relatively easy been done by giving all |
| 47 | // semaphores attributes deviating from the default (for in-depth |
| 48 | // information see the POSIX functions pthread_mutexattr_init() |
| 49 | // and pthread_mutexattr_setprotocol()). However this breaks all |
| 50 | // too easily, as with every new version some boost library could |
| 51 | // all in a sudden start using semaphores, resurrecting the very |
| 52 | // same, hard to locate problem over and over again! |
| 53 | // |
| 54 | // b) We could change the default properties for POSIX-semaphores |
| 55 | // that VxWorks uses for RTP's and this is being suggested here, |
| 56 | // as it will more or less seamlessly integrate with boost. I got |
| 57 | // the following information from WRS how to do this, compare |
| 58 | // Wind River TSR# 1209768: |
| 59 | // |
| 60 | // Instructions for changing the default properties of POSIX- |
| 61 | // semaphores for RTP's in VxWorks 6.9: |
| 62 | // - Edit the file /vxworks-6.9/target/usr/src/posix/pthreadLib.c |
| 63 | // in the root of your Workbench-installation. |
| 64 | // - Around line 917 there should be the definition of the default |
| 65 | // mutex attributes: |
| 66 | // |
| 67 | // LOCAL pthread_mutexattr_t defaultMutexAttr = |
| 68 | // { |
| 69 | // PTHREAD_INITIALIZED_OBJ, PTHREAD_PRIO_NONE, 0, |
| 70 | // PTHREAD_MUTEX_DEFAULT |
| 71 | // }; |
| 72 | // |
| 73 | // Here, replace PTHREAD_PRIO_NONE by PTHREAD_PRIO_INHERIT. |
| 74 | // - Around line 1236 there should be a definition for the function |
| 75 | // pthread_mutexattr_init(). A couple of lines below you should |
| 76 | // find a block of code like this: |
| 77 | // |
| 78 | // pAttr->mutexAttrStatus = PTHREAD_INITIALIZED_OBJ; |
| 79 | // pAttr->mutexAttrProtocol = PTHREAD_PRIO_NONE; |
| 80 | // pAttr->mutexAttrPrioceiling = 0; |
| 81 | // pAttr->mutexAttrType = PTHREAD_MUTEX_DEFAULT; |
| 82 | // |
| 83 | // Here again, replace PTHREAD_PRIO_NONE by PTHREAD_PRIO_INHERIT. |
| 84 | // - Finally, rebuild your VSB. This will create a new VxWorks kernel |
| 85 | // with the changed properties. That's it! Now, using boost should |
| 86 | // no longer cause any problems with task deadlocks! |
| 87 | // |
| 88 | // And here's another useful piece of information concerning VxWorks' |
| 89 | // POSIX-functionality in general: |
| 90 | // VxWorks is not a genuine POSIX-OS in itself, rather it is using a |
| 91 | // kind of compatibility layer (sort of a wrapper) to emulate the |
| 92 | // POSIX-functionality by using its own resources and functions. |
| 93 | // At the time a task (thread) calls it's first POSIX-function during |
| 94 | // runtime it is being transformed by the OS into a POSIX-thread. |
| 95 | // This transformation does include a call to malloc() to allocate the |
| 96 | // memory required for the housekeeping of POSIX-threads. In a high |
| 97 | // priority RTP this malloc() call may be highly undesirable, as its |
| 98 | // timing is more or less unpredictable (depending on what your actual |
| 99 | // heap looks like). You can circumvent this problem by calling the |
| 100 | // function thread_self() at a well defined point in the code of the |
| 101 | // task, e.g. shortly after the task spawns up. Thereby you are able |
| 102 | // to define the time when the task-transformation will take place and |
| 103 | // you could shift it to an uncritical point where a malloc() call is |
| 104 | // tolerable. So, if this could pose a problem for your code, remember |
| 105 | // to call thread_self() from the affected task at an early stage. |
| 106 | // |
| 107 | // ==================================================================== |
| 108 | |