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