You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 26, 2025. It is now read-only.
First, in order to pass the tests on both the x86 and aarch architectures, it is necessary to add TLS-related processing in ArceOS and use new_task.ctx_mut().set_tls(axhal::arch::read_thread_pointer().into()); in Starry's clone_task to set the TLS:
tls function:
/// Gets the TLS area.pubfntls(&self) -> VirtAddr{VirtAddr::from(self.fs_base)}
The function is used to obtain the virtual address of the TLS area of the current task. It retrieves the stored address value of the TLS area from the fs_base field of the TaskContext structure and converts it to the VirtAddr type for return. The fs_base field is used to store the base address of the TLS area, and this function provides a way to access this address.
set_tls function:
/// Sets the TLS area.pubfnset_tls(&mutself,tls_area:VirtAddr){self.fs_base = tls_area.as_usize();}
This function is used to set the address of the TLS area of the current task. It takes a parameter tls_area of type VirtAddr, which represents the virtual address of the TLS area to be set. Then it converts this address to the usize type and stores it in the fs_base field of the TaskContext structure.
Role in the TaskContext structure:
The TaskContext structure is used to save the hardware state of a task, including the kernel stack top address (kstack_top), stack pointer (rsp), and the base address of the TLS area (fs_base). The tls and set_tls functions are closely related to the fs_base field, providing read and write operations for the address of the TLS area, which facilitates the handling of TLS-related information when managing the task context.
Role in context switching:
In the switch_to function, when performing task context switching, the handling of the TLS area is involved:
Here, the fs_base of the current task is first saved (by reading the TLS pointer of the current thread through the read_thread_pointer function), and then the fs_base of the next task is written (by setting the TLS pointer of the thread through the write_thread_pointer function). The tls and set_tls functions provide the basis for saving and restoring the TLS area, ensuring that the TLS area information of each task can be correctly transferred and restored during the context switching process.
Relationship with other modules and functions:
The TLS area is usually used to store thread-specific data, such as thread-local variables and caches. These two functions may have potential associations with structures such as UspaceContext and TrapFrame, as well as functions like enter_uspace. For example, when entering user space (in the enter_uspace function), it may be necessary to correctly set and use the TLS area. The tls and set_tls functions provide interfaces for operating the address of the TLS area, which helps maintain the TLS-related state during the switching of different tasks and spaces.
In summary, the tls and set_tls functions in the entire framework are mainly responsible for managing the address of the task's TLS area, providing read and write functions for the TLS area for context switching and other operations related to task states, ensuring that the thread-local storage-related information can be correctly handled during task execution and switching.
Analysis of Wingrew's code modifications:
After completing the above adaptations for x86 and aarch, Wingrew mainly adapted the main function part of src/main.rs for the competition evaluation, that is, the following part:
#[unsafe(no_mangle)]fnmain(){println!("#### OS COMP TEST GROUP START basic-glibc ####");println!("#### OS COMP TEST GROUP START basic-musl ####");let testcases = option_env!("AX_TESTCASES_LIST").unwrap_or_else(|| "Please specify the testcases list by making user_apps").split(',').filter(|&x| !x.is_empty());letmut i = 0;for testcase in testcases {let args = testcase
.split_ascii_whitespace().map(ToString::to_string).collect::<Vec<_>>();let exit_code = run_user_app(&args,&[]);info!("User task {} exited with code: {:?}", testcase, exit_code);
i += 1;if i == 32{println!("#### OS COMP TEST GROUP END basic-musl ####");println!("#### OS COMP TEST GROUP END basic-glibc ####");println!("#### OS COMP TEST GROUP START libctest-glibc ####");println!("#### OS COMP TEST GROUP START libctest-musl ####");}elseif i == 161{println!("#### OS COMP TEST GROUP END libctest-musl ####");println!("#### OS COMP TEST GROUP END libctest-glibc ####");}}}
Print the start information of the test groups.
Obtain the test case list from the environment variable AX_TESTCASES_LIST, split it, and filter out empty strings.
Iterate through the test case list, parse the parameters of each test case into a vector of strings, call the run_user_app function to run the user task, and record the exit code of the task.
According to the serial number of the test case, print the start and end information of different test groups.
In this way, the test outputs for 32 basic test cases and 131 libc test cases can be completed.
In addition, before reading Wingrew's modifications, I first referred to BattiestStone4's testing method. In oscomp, BattiestStone4 created testcase_list_musl_libctest and testcase_list_glibc_libctest by imitating testcase_list and added relevant definitions in the Makefile for testing. In this way, there is no need to count in the main function, and the libc tests can be carried out by repeating the operations for the basic tests:
fnmain(){println!("#### OS COMP TEST GROUP START basic-glibc ####");println!("#### OS COMP TEST GROUP START basic-musl ####");let testcases = option_env!("AX_TESTCASES_LIST").unwrap_or_else(|| "Please specify the testcases list by making user_apps").split(',').filter(|&x| !x.is_empty());for testcase in testcases {let args = testcase
.split_ascii_whitespace().map(ToString::to_string).collect::<Vec<_>>();let exit_code = run_user_app(&args,&[]);info!("User task {} exited with code: {:?}", testcase, exit_code);}println!("#### OS COMP TEST GROUP END basic-musl ####");println!("#### OS COMP TEST GROUP END basic-glibc ####");println!("#### OS COMP TEST GROUP START libctest-glibc ####");println!("#### OS COMP TEST GROUP START libctest-musl ####");let testcases = option_env!("AX_MUSL_LIBCTEST_TESTCASES_LIST").unwrap_or_else(|| "Please specify the testcases list by making user_apps").split(',').filter(|&x| !x.is_empty());for testcase in testcases {let args = testcase
.split_ascii_whitespace().map(ToString::to_string).collect::<Vec<_>>();let exit_code = run_user_app(&args,&[]);info!("User task {} exited with code: {:?}", testcase, exit_code);}println!("#### OS COMP TEST GROUP END libctest-musl ####");println!("#### OS COMP TEST GROUP END libctest-glibc ####");}
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
First, in order to pass the tests on both the x86 and aarch architectures, it is necessary to add TLS-related processing in ArceOS and use
new_task.ctx_mut().set_tls(axhal::arch::read_thread_pointer().into());in Starry'sclone_taskto set the TLS:tls function:
The function is used to obtain the virtual address of the TLS area of the current task. It retrieves the stored address value of the TLS area from the
fs_basefield of theTaskContextstructure and converts it to theVirtAddrtype for return. Thefs_basefield is used to store the base address of the TLS area, and this function provides a way to access this address.set_tls function:
This function is used to set the address of the TLS area of the current task. It takes a parameter
tls_areaof typeVirtAddr, which represents the virtual address of the TLS area to be set. Then it converts this address to theusizetype and stores it in thefs_basefield of theTaskContextstructure.Role in the TaskContext structure:
The
TaskContextstructure is used to save the hardware state of a task, including the kernel stack top address (kstack_top), stack pointer (rsp), and the base address of the TLS area (fs_base). Thetlsandset_tlsfunctions are closely related to thefs_basefield, providing read and write operations for the address of the TLS area, which facilitates the handling of TLS-related information when managing the task context.Role in context switching:
In the
switch_tofunction, when performing task context switching, the handling of the TLS area is involved:Here, the
fs_baseof the current task is first saved (by reading the TLS pointer of the current thread through theread_thread_pointerfunction), and then thefs_baseof the next task is written (by setting the TLS pointer of the thread through thewrite_thread_pointerfunction). Thetlsandset_tlsfunctions provide the basis for saving and restoring the TLS area, ensuring that the TLS area information of each task can be correctly transferred and restored during the context switching process.Relationship with other modules and functions:
The TLS area is usually used to store thread-specific data, such as thread-local variables and caches. These two functions may have potential associations with structures such as
UspaceContextandTrapFrame, as well as functions likeenter_uspace. For example, when entering user space (in theenter_uspacefunction), it may be necessary to correctly set and use the TLS area. Thetlsandset_tlsfunctions provide interfaces for operating the address of the TLS area, which helps maintain the TLS-related state during the switching of different tasks and spaces.In summary, the
tlsandset_tlsfunctions in the entire framework are mainly responsible for managing the address of the task's TLS area, providing read and write functions for the TLS area for context switching and other operations related to task states, ensuring that the thread-local storage-related information can be correctly handled during task execution and switching.Analysis of Wingrew's code modifications:
After completing the above adaptations for x86 and aarch, Wingrew mainly adapted the main function part of
src/main.rsfor the competition evaluation, that is, the following part:AX_TESTCASES_LIST, split it, and filter out empty strings.run_user_appfunction to run the user task, and record the exit code of the task.In this way, the test outputs for 32 basic test cases and 131 libc test cases can be completed.
In addition, before reading Wingrew's modifications, I first referred to BattiestStone4's testing method. In oscomp, BattiestStone4 created
testcase_list_musl_libctestandtestcase_list_glibc_libctestby imitatingtestcase_listand added relevant definitions in the Makefile for testing. In this way, there is no need to count in themainfunction, and the libc tests can be carried out by repeating the operations for the basic tests:For Chinese version, see this.
Beta Was this translation helpful? Give feedback.
All reactions