Nigel Rantor / azure_c_shared_utility

Fork of azure_c_shared_utility by Azure IoT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers threadapi_rtx_mbed.cpp Source File

threadapi_rtx_mbed.cpp

00001 // Copyright (c) Microsoft. All rights reserved.
00002 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
00003 
00004 #include <stdlib.h>
00005 #include "azure_c_shared_utility/threadapi.h"
00006 #include "azure_c_shared_utility/xlogging.h"
00007 #include "rtos.h"
00008 
00009 DEFINE_ENUM_STRINGS(THREADAPI_RESULT, THREADAPI_RESULT_VALUES);
00010 
00011 #define MAX_THREADS 4
00012 #define STACK_SIZE  0x4000
00013 
00014 typedef struct _thread
00015 {
00016     Thread*       thrd;
00017     osThreadId    id;
00018     Queue<int, 1> result;
00019 } mbedThread;
00020 static mbedThread threads[MAX_THREADS] = { 0 };
00021 
00022 typedef struct _create_param
00023 {
00024     THREAD_START_FUNC func;
00025     const void* arg;
00026     mbedThread *p_thread;
00027 } create_param;
00028 
00029 static void thread_wrapper(const void* createParamArg)
00030 {
00031     const create_param* p = (const create_param*)createParamArg;
00032     p->p_thread->id = Thread::gettid();
00033     (*(p->func))((void*)p->arg);
00034     free((void*)p);
00035 }
00036 
00037 THREADAPI_RESULT ThreadAPI_Create(THREAD_HANDLE* threadHandle, THREAD_START_FUNC func, void* arg)
00038 {
00039     THREADAPI_RESULT result;
00040     if ((threadHandle == NULL) ||
00041         (func == NULL))
00042     {
00043         result = THREADAPI_INVALID_ARG;
00044         LogError("(result = %s)", ENUM_TO_STRING(THREADAPI_RESULT, result));
00045     }
00046     else
00047     {
00048         size_t slot;
00049         for (slot = 0; slot < MAX_THREADS; slot++)
00050         {
00051             if (threads[slot].id == NULL)
00052                 break;
00053         }
00054 
00055         if (slot < MAX_THREADS)
00056         {
00057             create_param* param = (create_param*)malloc(sizeof(create_param));
00058             if (param != NULL)
00059             {
00060                 param->func = func;
00061                 param->arg = arg;
00062                 param->p_thread = threads + slot;
00063                 threads[slot].thrd = new Thread(thread_wrapper, param, osPriorityNormal, STACK_SIZE);
00064                 *threadHandle = (THREAD_HANDLE)(threads + slot);
00065                 result = THREADAPI_OK;
00066             }
00067             else
00068             {
00069                 result = THREADAPI_NO_MEMORY;
00070                 LogError("(result = %s)", ENUM_TO_STRING(THREADAPI_RESULT, result));
00071             }
00072         }
00073         else
00074         {
00075             result = THREADAPI_NO_MEMORY;
00076             LogError("(result = %s)", ENUM_TO_STRING(THREADAPI_RESULT, result));
00077         }
00078     }
00079 
00080     return result;
00081 }
00082 
00083 THREADAPI_RESULT ThreadAPI_Join(THREAD_HANDLE thr, int *res)
00084 {
00085     THREADAPI_RESULT result = THREADAPI_OK;
00086     mbedThread* p = (mbedThread*)thr;
00087     if (p)
00088     {
00089         osEvent evt = p->result.get();
00090         if (evt.status == osEventMessage) {
00091             Thread* t = p->thrd;
00092             if (res)
00093             {
00094                 *res = (int)evt.value.p;
00095             }
00096             (void)t->terminate();
00097         }
00098         else
00099         {
00100             result = THREADAPI_ERROR;
00101             LogError("(result = %s)", ENUM_TO_STRING(THREADAPI_RESULT, result));
00102         }
00103     }
00104     else
00105     {
00106         result = THREADAPI_INVALID_ARG;
00107         LogError("(result = %s)", ENUM_TO_STRING(THREADAPI_RESULT, result));
00108     }
00109     return result;
00110 }
00111 
00112 void ThreadAPI_Exit(int res)
00113 {
00114     mbedThread* p;
00115     for (p = threads; p < &threads[MAX_THREADS]; p++)
00116     {
00117         if (p->id == Thread::gettid())
00118         {
00119             p->result.put((int*)res);
00120             break;
00121         }
00122     }
00123 }
00124 
00125 void ThreadAPI_Sleep(unsigned int millisec)
00126 {
00127     //
00128     // The timer on mbed seems to wrap around 65 seconds. Hmmm.
00129     // So we will do our waits in increments of 30 seconds.
00130     //
00131     const int thirtySeconds = 30000;
00132     int numberOfThirtySecondWaits = millisec / thirtySeconds;
00133     int remainderOfThirtySeconds = millisec % thirtySeconds;
00134     int i;
00135     for (i = 1; i <= numberOfThirtySecondWaits; i++)
00136     {
00137         Thread::wait(thirtySeconds);
00138     }
00139     Thread::wait(remainderOfThirtySeconds);
00140 }