Improved thread lifecycle (#2534)
* Core, Thread: mark thread to join from prvDeleteTCB * USB HAL: move vars to MEM2 * Core, Thread: cleanup sources * Cli: add magic delays on rx pipe error, prevent cli from consuming processor time * Furi: update thread documentation Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									3617ad33e4
								
							
						
					
					
						commit
						8b2dfea925
					
				| @ -37,9 +37,11 @@ char cli_getc(Cli* cli) { | |||||||
|     if(cli->session != NULL) { |     if(cli->session != NULL) { | ||||||
|         if(cli->session->rx((uint8_t*)&c, 1, FuriWaitForever) == 0) { |         if(cli->session->rx((uint8_t*)&c, 1, FuriWaitForever) == 0) { | ||||||
|             cli_reset(cli); |             cli_reset(cli); | ||||||
|  |             furi_delay_tick(10); | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         cli_reset(cli); |         cli_reset(cli); | ||||||
|  |         furi_delay_tick(10); | ||||||
|     } |     } | ||||||
|     return c; |     return c; | ||||||
| } | } | ||||||
|  | |||||||
| @ -73,12 +73,11 @@ typedef enum { | |||||||
| #define USB_SRV_ALL_EVENTS (UsbEventReset | UsbEventRequest | UsbEventMessage) | #define USB_SRV_ALL_EVENTS (UsbEventReset | UsbEventRequest | UsbEventMessage) | ||||||
| 
 | 
 | ||||||
| PLACE_IN_SECTION("MB_MEM2") static UsbSrv usb = {0}; | PLACE_IN_SECTION("MB_MEM2") static UsbSrv usb = {0}; | ||||||
|  | PLACE_IN_SECTION("MB_MEM2") static uint32_t ubuf[0x20]; | ||||||
|  | PLACE_IN_SECTION("MB_MEM2") usbd_device udev; | ||||||
| 
 | 
 | ||||||
| static const struct usb_string_descriptor dev_lang_desc = USB_ARRAY_DESC(USB_LANGID_ENG_US); | static const struct usb_string_descriptor dev_lang_desc = USB_ARRAY_DESC(USB_LANGID_ENG_US); | ||||||
| 
 | 
 | ||||||
| static uint32_t ubuf[0x20]; |  | ||||||
| usbd_device udev; |  | ||||||
| 
 |  | ||||||
| static int32_t furi_hal_usb_thread(void* context); | static int32_t furi_hal_usb_thread(void* context); | ||||||
| static usbd_respond usb_descriptor_get(usbd_ctlreq* req, void** address, uint16_t* length); | static usbd_respond usb_descriptor_get(usbd_ctlreq* req, void** address, uint16_t* length); | ||||||
| static void reset_evt(usbd_device* dev, uint8_t event, uint8_t ep); | static void reset_evt(usbd_device* dev, uint8_t event, uint8_t ep); | ||||||
|  | |||||||
| @ -58,6 +58,7 @@ extern uint32_t SystemCoreClock; | |||||||
| #define configTIMER_SERVICE_TASK_NAME "TimersSrv" | #define configTIMER_SERVICE_TASK_NAME "TimersSrv" | ||||||
| 
 | 
 | ||||||
| #define configIDLE_TASK_NAME "(-_-)" | #define configIDLE_TASK_NAME "(-_-)" | ||||||
|  | #define configIDLE_TASK_STACK_DEPTH 128 | ||||||
| 
 | 
 | ||||||
| /* Set the following definitions to 1 to include the API function, or zero
 | /* Set the following definitions to 1 to include the API function, or zero
 | ||||||
| to exclude the API function. */ | to exclude the API function. */ | ||||||
| @ -138,3 +139,7 @@ standard names. */ | |||||||
| #define traceTASK_SWITCHED_IN()                                     \ | #define traceTASK_SWITCHED_IN()                                     \ | ||||||
|     extern void furi_hal_mpu_set_stack_protection(uint32_t* stack); \ |     extern void furi_hal_mpu_set_stack_protection(uint32_t* stack); \ | ||||||
|     furi_hal_mpu_set_stack_protection((uint32_t*)pxCurrentTCB->pxStack) |     furi_hal_mpu_set_stack_protection((uint32_t*)pxCurrentTCB->pxStack) | ||||||
|  | 
 | ||||||
|  | #define portCLEAN_UP_TCB(pxTCB)                                   \ | ||||||
|  |     extern void furi_thread_cleanup_tcb_event(TaskHandle_t task); \ | ||||||
|  |     furi_thread_cleanup_tcb_event(pxTCB) | ||||||
|  | |||||||
| @ -24,7 +24,6 @@ struct FuriThreadStdout { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct FuriThread { | struct FuriThread { | ||||||
|     bool is_service; |  | ||||||
|     FuriThreadState state; |     FuriThreadState state; | ||||||
|     int32_t ret; |     int32_t ret; | ||||||
| 
 | 
 | ||||||
| @ -37,14 +36,19 @@ struct FuriThread { | |||||||
|     char* name; |     char* name; | ||||||
|     char* appid; |     char* appid; | ||||||
| 
 | 
 | ||||||
|     configSTACK_DEPTH_TYPE stack_size; |  | ||||||
|     FuriThreadPriority priority; |     FuriThreadPriority priority; | ||||||
| 
 | 
 | ||||||
|     TaskHandle_t task_handle; |     TaskHandle_t task_handle; | ||||||
|     bool heap_trace_enabled; |  | ||||||
|     size_t heap_size; |     size_t heap_size; | ||||||
| 
 | 
 | ||||||
|     FuriThreadStdout output; |     FuriThreadStdout output; | ||||||
|  | 
 | ||||||
|  |     // Keep all non-alignable byte types in one place,
 | ||||||
|  |     // this ensures that the size of this structure is minimal
 | ||||||
|  |     bool is_service; | ||||||
|  |     bool heap_trace_enabled; | ||||||
|  | 
 | ||||||
|  |     configSTACK_DEPTH_TYPE stack_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static size_t __furi_thread_stdout_write(FuriThread* thread, const char* data, size_t size); | static size_t __furi_thread_stdout_write(FuriThread* thread, const char* data, size_t size); | ||||||
| @ -107,14 +111,8 @@ static void furi_thread_body(void* context) { | |||||||
|     // flush stdout
 |     // flush stdout
 | ||||||
|     __furi_thread_stdout_flush(thread); |     __furi_thread_stdout_flush(thread); | ||||||
| 
 | 
 | ||||||
|     // from here we can't use thread pointer
 |  | ||||||
|     furi_thread_set_state(thread, FuriThreadStateStopped); |     furi_thread_set_state(thread, FuriThreadStateStopped); | ||||||
| 
 | 
 | ||||||
|     // clear thread local storage
 |  | ||||||
|     furi_assert(pvTaskGetThreadLocalStoragePointer(NULL, 0) != NULL); |  | ||||||
|     vTaskSetThreadLocalStoragePointer(NULL, 0, NULL); |  | ||||||
| 
 |  | ||||||
|     thread->task_handle = NULL; |  | ||||||
|     vTaskDelete(NULL); |     vTaskDelete(NULL); | ||||||
|     furi_thread_catch(); |     furi_thread_catch(); | ||||||
| } | } | ||||||
| @ -249,11 +247,11 @@ void furi_thread_start(FuriThread* thread) { | |||||||
|     furi_assert(thread); |     furi_assert(thread); | ||||||
|     furi_assert(thread->callback); |     furi_assert(thread->callback); | ||||||
|     furi_assert(thread->state == FuriThreadStateStopped); |     furi_assert(thread->state == FuriThreadStateStopped); | ||||||
|     furi_assert(thread->stack_size > 0 && thread->stack_size < 0xFFFF * 4); |     furi_assert(thread->stack_size > 0 && thread->stack_size < (UINT16_MAX * sizeof(StackType_t))); | ||||||
| 
 | 
 | ||||||
|     furi_thread_set_state(thread, FuriThreadStateStarting); |     furi_thread_set_state(thread, FuriThreadStateStarting); | ||||||
| 
 | 
 | ||||||
|     uint32_t stack = thread->stack_size / 4; |     uint32_t stack = thread->stack_size / sizeof(StackType_t); | ||||||
|     UBaseType_t priority = thread->priority ? thread->priority : FuriThreadPriorityNormal; |     UBaseType_t priority = thread->priority ? thread->priority : FuriThreadPriorityNormal; | ||||||
|     if(thread->is_service) { |     if(thread->is_service) { | ||||||
|         thread->task_handle = xTaskCreateStatic( |         thread->task_handle = xTaskCreateStatic( | ||||||
| @ -273,12 +271,25 @@ void furi_thread_start(FuriThread* thread) { | |||||||
|     furi_check(thread->task_handle); |     furi_check(thread->task_handle); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void furi_thread_cleanup_tcb_event(TaskHandle_t task) { | ||||||
|  |     FuriThread* thread = pvTaskGetThreadLocalStoragePointer(task, 0); | ||||||
|  |     if(thread) { | ||||||
|  |         // clear thread local storage
 | ||||||
|  |         vTaskSetThreadLocalStoragePointer(task, 0, NULL); | ||||||
|  | 
 | ||||||
|  |         thread->task_handle = NULL; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool furi_thread_join(FuriThread* thread) { | bool furi_thread_join(FuriThread* thread) { | ||||||
|     furi_assert(thread); |     furi_assert(thread); | ||||||
| 
 | 
 | ||||||
|     furi_check(furi_thread_get_current() != thread); |     furi_check(furi_thread_get_current() != thread); | ||||||
| 
 | 
 | ||||||
|     // Wait for thread to stop
 |     // !!! IMPORTANT NOTICE !!!
 | ||||||
|  |     //
 | ||||||
|  |     // If your thread exited, but your app stuck here: some other thread uses
 | ||||||
|  |     // all cpu time, which delays kernel from releasing task handle
 | ||||||
|     while(thread->task_handle) { |     while(thread->task_handle) { | ||||||
|         furi_delay_ms(10); |         furi_delay_ms(10); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -75,6 +75,8 @@ FuriThread* furi_thread_alloc_ex( | |||||||
|     void* context); |     void* context); | ||||||
| 
 | 
 | ||||||
| /** Release FuriThread
 | /** Release FuriThread
 | ||||||
|  |  * | ||||||
|  |  * @warning    see furi_thread_join | ||||||
|  * |  * | ||||||
|  * @param      thread  FuriThread instance |  * @param      thread  FuriThread instance | ||||||
|  */ |  */ | ||||||
| @ -173,6 +175,9 @@ FuriThreadState furi_thread_get_state(FuriThread* thread); | |||||||
| void furi_thread_start(FuriThread* thread); | void furi_thread_start(FuriThread* thread); | ||||||
| 
 | 
 | ||||||
| /** Join FuriThread
 | /** Join FuriThread
 | ||||||
|  |  * | ||||||
|  |  * @warning    Use this method only when CPU is not busy(Idle task receives | ||||||
|  |  *             control), otherwise it will wait forever. | ||||||
|  * |  * | ||||||
|  * @param      thread  FuriThread instance |  * @param      thread  FuriThread instance | ||||||
|  * |  * | ||||||
|  | |||||||
| @ -54,8 +54,8 @@ void vApplicationGetIdleTaskMemory( | |||||||
|     StackType_t** stack_ptr, |     StackType_t** stack_ptr, | ||||||
|     uint32_t* stack_size) { |     uint32_t* stack_size) { | ||||||
|     *tcb_ptr = memmgr_alloc_from_pool(sizeof(StaticTask_t)); |     *tcb_ptr = memmgr_alloc_from_pool(sizeof(StaticTask_t)); | ||||||
|     *stack_ptr = memmgr_alloc_from_pool(sizeof(StackType_t) * configMINIMAL_STACK_SIZE); |     *stack_ptr = memmgr_alloc_from_pool(sizeof(StackType_t) * configIDLE_TASK_STACK_DEPTH); | ||||||
|     *stack_size = configMINIMAL_STACK_SIZE; |     *stack_size = configIDLE_TASK_STACK_DEPTH; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void vApplicationGetTimerTaskMemory( | void vApplicationGetTimerTaskMemory( | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Sergey Gavrilov
						Sergey Gavrilov