fork

Revision:
123:58563e6cba1e
Parent:
119:19af2d39a542
diff -r b744dfee1cf2 -r 58563e6cba1e rtos/Thread.cpp
--- a/rtos/Thread.cpp	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtos/Thread.cpp	Mon Nov 14 17:14:42 2016 -0600
@@ -19,10 +19,10 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
-#include "Thread.h"
+#include "rtos/Thread.h"
 
 #include "mbed.h"
-#include "rtos_idle.h"
+#include "rtos/rtos_idle.h"
 
 // rt_tid2ptcb is an internal function which we exposed to get TCB for thread id
 #undef NULL  //Workaround for conflicting macros in rt_TypeDef.h and stdio.h
@@ -30,6 +30,15 @@
 
 extern "C" P_TCB rt_tid2ptcb(osThreadId thread_id);
 
+
+static void (*terminate_hook)(osThreadId id) = 0;
+extern "C" void thread_terminate_hook(osThreadId id)
+{
+    if (terminate_hook != (void (*)(osThreadId))NULL) {
+        terminate_hook(id);
+    }
+}
+
 namespace rtos {
 
 void Thread::constructor(osPriority priority,
@@ -74,10 +83,7 @@
     _thread_def.pthread = Thread::_thunk;
     if (_thread_def.stack_pointer == NULL) {
         _thread_def.stack_pointer = new uint32_t[_thread_def.stacksize/sizeof(uint32_t)];
-        if (_thread_def.stack_pointer == NULL) {
-            _mutex.unlock();
-            return osErrorNoMemory;
-        }
+        MBED_ASSERT(_thread_def.stack_pointer != NULL);
     }
 
     //Fill the stack with a magic word for maximum usage checking
@@ -88,8 +94,12 @@
     _task = task;
     _tid = osThreadCreate(&_thread_def, this);
     if (_tid == NULL) {
-        if (_dynamic_stack) delete[] (_thread_def.stack_pointer);
+        if (_dynamic_stack) {
+            delete[] (_thread_def.stack_pointer);
+            _thread_def.stack_pointer = (uint32_t*)NULL;
+        }
         _mutex.unlock();
+        _join_sem.release();
         return osErrorResource;
     }
 
@@ -101,11 +111,14 @@
     osStatus ret;
     _mutex.lock();
 
-    ret = osThreadTerminate(_tid);
+    // Set the Thread's tid to NULL and
+    // release the semaphore before terminating
+    // since this thread could be terminating itself
+    osThreadId local_id = _tid;
+    _join_sem.release();
     _tid = (osThreadId)NULL;
 
-    // Wake threads joining the terminated thread
-    _join_sem.release();
+    ret = osThreadTerminate(local_id);
 
     _mutex.unlock();
     return ret;
@@ -116,6 +129,14 @@
     if (ret < 0) {
         return osErrorOS;
     }
+
+    // The semaphore has been released so this thread is being
+    // terminated or has been terminated. Once the mutex has
+    // been locked it is ensured that the thread is deleted.
+    _mutex.lock();
+    MBED_ASSERT(NULL == _tid);
+    _mutex.unlock();
+
     // Release sem so any other threads joining this thread wake up
     _join_sem.release();
     return osOK;
@@ -325,12 +346,17 @@
     rtos_attach_idle_hook(fptr);
 }
 
+void Thread::attach_terminate_hook(void (*fptr)(osThreadId id)) {
+    terminate_hook = fptr;
+}
+
 Thread::~Thread() {
     // terminate is thread safe
     terminate();
 #ifdef __MBED_CMSIS_RTOS_CM
     if (_dynamic_stack) {
         delete[] (_thread_def.stack_pointer);
+        _thread_def.stack_pointer = (uint32_t*)NULL;
     }
 #endif
 }