| | 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 | |