Analysis of SylixOS thread stack size

 

1. SylixOS thread, thread stack introduction

    SylixOS is a multi-threaded operating system. The system can create multiple threads at the same time. The specific maximum number of threads depends on the size of the system memory and the relevant configuration when compiling the SylixOS operating system. The default maximum number of threads for SylixOS threads is determined by the macro LW_CFG_MAX_THREADS. The macro definition can be Found in file <config/kernel/kernel_cfg.h>.

1.1 Introduction to threads

    A thread is sometimes called a Lightweight Process (LWP), and in SylixOS, a thread is also called a task. It is a single sequential instruction stream and the smallest unit of operating system scheduling, and each thread has its own priority. A thread usually consists of four parts: thread handle (or ID), current instruction (PC), CPU register set, and thread stack.

1.2 Introduction to thread stack

    Each thread has its own independent stack area, and each thread control block saves the start position, end position, and stack guard point (for stack overflow checking) of the stack area. When task scheduling occurs, the thread stack area will save the thread's current context (for context recovery). Therefore, the setting of the thread stack must be reasonable. If it is too large, it will waste memory space, and if it is too small, it may cause stack overflow. All threads in SylixOS are in the same page table. In order to meet real-time requirements, there is no address protection mechanism between threads, so stack overflow may lead to unpredictable results such as system crash.

 

2. SylixOS thread stack size allocation

    Each SylixOS thread has its own properties, mainly including priority, stack information, thread parameters, etc. When the thread is created, SylixOS provides a function Lw_ThreadAttr_GetDefault to quickly get the default attribute block of the system. The return value of this function is the thread attribute block, and the default thread size is 4K (when the program is normally run through the shell command, the program inherits the stack of the shell). SylixOS can use related API functions to make corresponding modifications to the thread stack. Table 2-1 shows some API functions related to the thread stack.

Table 2-1 API functions related to thread stack

API interface

Function description

pthread_attr_init

Initialize the thread property block

pthread_attr_destroy

Destroys a thread property block

pthread_attr_setstack

Set the relevant parameters of the stack

pthread_attr_getstack

Get the relevant parameters of the stack

pthread_attr_setguardsize

Sets the stack guard size of a thread property block

pthread_attr_getguardsize

Get the stack guard size of a thread attribute block

pthread_attr_setstacksize

Sets the stack size of a thread property block

pthread_attr_getstacksize

Get the stack size of a thread attribute block

pthread_attr_setstackaddr

Specifies the stack address of a thread attribute block

pthread_attr_getstackaddr

Get the stack address of a thread property block

pthread_attr_setstackfilled

Set thread property block stack fill property

pthread_attr_getstackfilled

Get thread property block stack fill property

……

……

 

2.1 Setting of thread and thread stack related properties

SylixOS provides the following set of functions to set the thread's property block parameters, as shown in Listing 2-1:

Listing 2-1 Thread property block

/*********************************************************************************************************

thread property block

*********************************************************************************************************/

typedefstruct {

PLW_STACK THREADATTR_pstkLowAddr ; /* Low memory start address of all stack areas */

size_t THREADATTR_stGuardSize ; /* Stack guard area size */

size_t THREADATTR_stStackByteSize ; /* All stack area size (bytes) */

UINT8 THREADATTR_ucPriority ; /* Thread priority */

ULONG THREADATTR_ulOption ; /* task option */

PVOID THREADATTR_pvArg ; /* Thread parameters */

PVOID THREADATTR_pvExt ; /* Extended data segment pointer */

} LW_CLASS_THREADATTR;

typedefLW_CLASS_THREADATTR *PLW_CLASS_THREADATTR;

2.2线程栈大小

栈大小的设置没有可以套用的公式,通常根据开发者经验设置一个较大的值,用存储空间换取可靠性。在正常进程启动情况下,会继承内核线程栈大小。如果创建线程是不设置线程栈属性,将会继承内核Shell线程的栈大小。如程序清单 2-2所示:

程序清单 2-2 堆栈大小

intpthread_attr_setstacksize (pthread_attr_t *pattr, size_tstSize)

通过shell指令ss可以查看栈的大小,如图 2-1所示:

图 2-1 shell指令查看栈大小

 

2.3线程堆栈警戒区

因为我们无法确定所需使用栈区的实际大小,我们通过设置堆栈警戒区的方式来防止堆栈溢出,系统设置默认的警戒区大小为1k,当出现堆栈溢出的状况时,系统会预警,如程序清单 2-3所示:

程序清单 2-3 堆栈警戒区函数

intpthread_attr_setguardsize (pthread_attr_t *pattr, size_tstGuard)

该函数对线程属性块的警戒区大小进行修改,参数stGuard指定新的栈警戒区栈大小。我们通过程序清单 2-3做一个详细了解:

程序清单 2-3 堆栈溢出示例程序

#include<stdio.h>

#include<pthread.h>

#include<time.h>

void *routine(void *arg) {

fprintf(stdout, "pthread running...\n");

while(1);

return (NULL);

}

 

intmain(intargc, char *argv[]) {

pthread_ttid;

pthread_attr_tattr;

intret;

ret = pthread_attr_init(&attr);

if (ret != 0) {

fprintf(stderr, "pthreadattrinit failed.\n");

return (-1);

}

ret = pthread_create(&tid, &attr, routine, NULL);

if (ret != 0) {

fprintf(stderr, "pthread create failed.\n");

return (-1);

}

pthread_join(tid, NULL);

pthread_attr_destroy(&attr);

return (0);

}

 

 

 

 

 

通过shell指令shstack(显示或者设置shell    任务堆栈大小)设置堆栈大小,再查看是否修改成功,然后运行程序,如图 2-2所示线程kl栈溢出:

图 2-2 shell任务堆栈大小

    再通过ss 查看系统中所有线程与中断系统堆栈使用情况,如图 2-3所示:

图 2-3 系统中所有线程与中断系统堆栈使用情况

 

    我们SylixOS的每个线程都有自己独立的栈区,对应的线程控制块保存了该栈区的起始位置、终止位置、以及栈警戒点(用于栈溢出检查)。在系统提供默认的属性块中,栈大小为4k,警戒区大小为1k,用户也可以根据自己的需求,通过相关的API函数来对栈的大小进行设置。

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325943106&siteId=291194637