1 /**
2  * @file os_thread.c
3  * @author ALLWINNERTECH IOT WLAN Team
4  */
5 
6 /*
7  * Copyright (C) 2017 ALLWINNERTECH TECHNOLOGY CO., LTD. All rights reserved.
8  *
9  *  Redistribution and use in source and binary forms, with or without
10  *  modification, are permitted provided that the following conditions
11  *  are met:
12  *    1. Redistributions of source code must retain the above copyright
13  *       notice, this list of conditions and the following disclaimer.
14  *    2. Redistributions in binary form must reproduce the above copyright
15  *       notice, this list of conditions and the following disclaimer in the
16  *       documentation and/or other materials provided with the
17  *       distribution.
18  *    3. Neither the name of ALLWINNERTECH TECHNOLOGY CO., LTD. nor the names of
19  *       its contributors may be used to endorse or promote products derived
20  *       from this software without specific prior written permission.
21  *
22  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include "os_thread.h"
36 #include "os_util.h"
37 
38 
39 /**
40  * @brief Create and start a thread
41  *
42  * This function starts a new thread. The new thread starts execution by
43  * invoking entry(). The argument arg is passed as the sole argument of entry().
44  *
45  * @note After finishing execution, the new thread should call OS_ThreadDelete()
46  *       to delete itself. Failing to do this and just returning from entry()
47  *       will result in undefined behavior.
48  *
49  * @param[in] thread Pointer to the thread object
50  * @param[in] name A descriptive name for the thread. This is mainly used to
51  *                 facilitate debugging.
52  * @param[in] entry Entry, which is a function pointer, to the thread function
53  * @param[in] arg The sole argument passed to entry()
54  * @param[in] priority The priority at which the thread will execute
55  * @param[in] stackSize The number of bytes the thread stack can hold
56  * @retval OS_Status, OS_OK on success
57  */
OS_ThreadCreate(OS_Thread_t * thread,const char * name,OS_ThreadEntry_t entry,void * arg,OS_Priority priority,uint32_t stackSize)58 OS_Status OS_ThreadCreate(OS_Thread_t *thread, const char *name,
59                           OS_ThreadEntry_t entry, void *arg,
60                           OS_Priority priority, uint32_t stackSize)
61 {
62     BaseType_t ret;
63 
64     OS_HANDLE_ASSERT(!OS_ThreadIsValid(thread), thread->handle);
65 
66     ret = xTaskCreate(entry, name, stackSize / sizeof(StackType_t), arg,
67                       priority, &thread->handle);
68     if (ret != pdPASS) {
69         OS_ERR("err %"OS_BASETYPE_F"\n", ret);
70         OS_ThreadSetInvalid(thread);
71         return OS_FAIL;
72     }
73     return OS_OK;
74 }
75 
76 /**
77  * @brief Terminate the thread
78  * @note Only memory that is allocated to a thread by the kernel itself is
79  *       automatically freed when a thread is deleted. Memory, or any other
80  *       resource, that the application (rather than the kernel) allocates
81  *       to a thread must be explicitly freed by the application when the task
82  *       is deleted.
83  * @param[in] thread Pointer to the thread object to be deleted.
84  *                   A thread can delete itself by passing NULL in place of a
85  *                   valid thread object.
86  * @retval OS_Status, OS_OK on success
87  */
OS_ThreadDelete(OS_Thread_t * thread)88 OS_Status OS_ThreadDelete(OS_Thread_t *thread)
89 {
90     TaskHandle_t handle;
91     TaskHandle_t curHandle;
92 
93     if (thread == NULL) {
94         vTaskDelete(NULL); /* delete self */
95         return OS_OK;
96     }
97 
98     OS_HANDLE_ASSERT(OS_ThreadIsValid(thread), thread->handle);
99 
100     handle = thread->handle;
101     curHandle = xTaskGetCurrentTaskHandle();
102     if (handle == curHandle) {
103         /* delete self */
104         OS_ThreadSetInvalid(thread);
105         vTaskDelete(NULL);
106     } else {
107         /* delete other thread */
108         OS_WRN("thread %"OS_HANDLE_F" delete %"OS_HANDLE_F"\n", curHandle, handle);
109         vTaskDelete(handle);
110         OS_ThreadSetInvalid(thread);
111     }
112 
113     return OS_OK;
114 }
115 
116 #if INCLUDE_uxTaskGetStackHighWaterMark
117 /**
118  * @brief Get the minimum amount of free stack space that has been available
119  *        since the thread started executing.
120  * @param[in] thread Pointer to the thread object
121  * @return The minimum amount of free stack space that has been available since
122  *         the thread started executing. This is the amount of stack that
123  *         remained unused when stack usage was at its greatest (or deepest)
124  *         value.
125  */
OS_ThreadGetStackMinFreeSize(OS_Thread_t * thread)126 uint32_t OS_ThreadGetStackMinFreeSize(OS_Thread_t *thread)
127 {
128     TaskHandle_t handle;
129 
130     handle =  thread ? thread->handle : NULL;
131     return (uxTaskGetStackHighWaterMark(handle) * sizeof(StackType_t));
132 }
133 #endif
134 
135 #if (configCHECK_FOR_STACK_OVERFLOW > 0)
136 /*
137 void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
138 {
139     OS_ERR("task %p(%s) stack over flow\n", xTask, pcTaskName);
140     OS_ABORT();
141 }
142 */
143 #endif
144 
145 #if (configUSE_TRACE_FACILITY == 1)
OS_ThreadList(void)146 void OS_ThreadList(void)
147 {
148 #if 0
149     TaskStatus_t *taskStatusArray;
150     UBaseType_t taskNum, i;
151     char state;
152 
153     taskNum = uxTaskGetNumberOfTasks();
154     taskStatusArray = OS_Malloc(taskNum * sizeof(TaskStatus_t));
155     if (taskStatusArray == NULL) {
156         OS_ERR("no mem\n");
157         return;
158     }
159 
160     i = uxTaskGetSystemState(taskStatusArray, taskNum, NULL);
161     if (i != taskNum) {
162         OS_WRN("task num %lu != %lu\n", i, taskNum);
163     }
164 
165     OS_LOG(1, "%*sState Pri Idx StkCur     StkBot     StkFree StkFreeMin\n",
166            -configMAX_TASK_NAME_LEN, "Name");
167     for (i = 0; i < taskNum; ++i) {
168         OS_LOG(1, "%*.*s", -configMAX_TASK_NAME_LEN, configMAX_TASK_NAME_LEN,
169                taskStatusArray[i].pcTaskName);
170 
171         switch (taskStatusArray[i].eCurrentState) {
172         case eReady:        state = 'R'; break;
173         case eBlocked:      state = 'B'; break;
174         case eSuspended:    state = 'S'; break;
175         case eDeleted:      state = 'D'; break;
176         default:            state = '?'; break;
177         }
178         OS_LOG(1, "%-5c %-3lu %-3lu  %-u\n",
179                   state,
180                   taskStatusArray[i].uxCurrentPriority,
181                   taskStatusArray[i].xTaskNumber,
182                   //taskStatusArray[i].pxTopOfStack,
183                   //taskStatusArray[i].pxStack,
184                   //(taskStatusArray[i].pxTopOfStack - taskStatusArray[i].pxStack) * sizeof(StackType_t),
185                   taskStatusArray[i].usStackHighWaterMark * sizeof(StackType_t));
186     /*
187         OS_LOG(1, "%-5c %-3lu %-3lu %-10p %-10p %-7u %-u\n",
188                   state,
189                   taskStatusArray[i].uxCurrentPriority,
190                   taskStatusArray[i].xTaskNumber,
191                   taskStatusArray[i].pxTopOfStack,
192                   taskStatusArray[i].pxStack,
193                   (taskStatusArray[i].pxTopOfStack - taskStatusArray[i].pxStack) * sizeof(StackType_t),
194                   taskStatusArray[i].usStackHighWaterMark * sizeof(StackType_t));
195     */
196     }
197     OS_Free(taskStatusArray);
198 #endif
199 }
200 #endif
201