Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

The principle of TencentOS tiny semaphore and the method of creating, destroying and obtaining semaphore

2025-03-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces "the principle of TencentOS tiny semaphores and the methods of creating, destroying and obtaining semaphores". In daily operation, I believe that many people have doubts about the principle of TencentOS tiny semaphores and the methods of creating, destroying and obtaining semaphores. The editor consulted all kinds of materials and sorted out simple and useful operation methods. I hope it will be helpful to answer your doubts about the principle of TencentOS tiny semaphores and the methods of creating, destroying and obtaining semaphores. Next, please follow the editor to study!

Semaphore

In the operating system, semaphores (sem) is a mechanism to realize synchronization between tasks and tasks, tasks and interrupts or critical resource mutual exclusion protection. In multitasking systems, tasks often need to be synchronized or mutually exclusive, and semaphores can provide users with this support.

Abstractly, the semaphore is a non-negative integer, which is reduced by one whenever the semaphore is obtained (pend). When the value of the integer is 0, the semaphore is in an invalid state and cannot be obtained again, and all tasks that try to get it will enter the blocking state. Usually a semaphore has a count value, and its count value can be used for system resource counting (statistics).

Generally speaking, there are two values of semaphores:

0: indicates that there is no accumulated post semaphore operation, and there may be tasks blocking this semaphore.

Positive value: indicates that there are one or more post semaphore operations.

Generally speaking, semaphores are mostly used for synchronization rather than mutual exclusion, because another mutex mechanism (mutex) is provided in the operating system, and the mutex function is more perfect: mutexes have a priority inheritance mechanism, while semaphores do not have this mechanism. in addition, mutexes also have owner attributes, which we will explain later.

Semaphores, like queues, have blocking mechanisms. The task needs to wait for an interrupt to occur before performing the corresponding processing, then the task can wait for the semaphore in the blocking state, and the task will not be awakened to perform the corresponding processing until the semaphore is released after the interrupt occurs. When you post the semaphore, you can immediately turn the waiting task into a ready state. If the priority of the task is the highest among the ready tasks, the task can be run immediately. This is the "real-time response, real-time processing" in the operating system. The use of semaphores in the operating system can improve the efficiency of processing.

Data structure of semaphore semaphore control block

TencentOS tiny operates the semaphore through the semaphore control block, and its data type is k_sem_t. The semaphore control block is composed of several elements, mainly pend_obj of pend_obj_t type and count of k_sem_cnt_t type. Pend_obj, on the other hand, is somewhat similar to object-oriented inheritance, inheriting properties that describe the types of kernel resources (such as semaphores, queues, mutexes, etc., as well as a waiting list list). Count is a simple variable (it is a 16-bit unsigned integer) that represents the value of the semaphore.

Typedef struct k_sem_st {pend_obj_t pend_obj; k_sem_cnt_t count;} kquantum semaphore; macro definitions related to semaphores

In tos_config.h, the macro definition of an enable semaphore is TOS_CFG_SEM_EN

# define TOS_CFG_SEM_EN 1u semaphore implementation

The implementation of semaphores in TencentOS tiny is very simple, with only 125 lines of core code, which can be said to be very small.

Create semaphore

Each semaphore in the system has a corresponding semaphore control block, and the semaphore control block contains all the information about the semaphore, such as its waiting list, its resource type, and its semaphore value. Can you imagine that the essence of creating a semaphore is to initialize the semaphore control block? That's obviously what it looks like. Because the subsequent operation of the semaphore is operated through the semaphore control block, if the control block has no information, how can it be operated?

The semaphore function is tos_sem_create (), which is passed in two parameters, one is the pointer of the semaphore control block * sem, and the other is the initial value of the semaphore, init_count, which is a non-negative integer, but cannot exceed 65535.

You actually initialize the sem- > pend_obj member variable in the semaphore control block by calling the pend_object_init () function, whose resource type is identified as PEND_TYPE_SEM. Then set the sem- > count member variable to the initial value init_count of the semaphore passed in.

_ _ API__ k_err_t tos_sem_create (k_sem_t * sem, k_sem_cnt_t init_count) {TOS_PTR_SANITY_CHECK (sem); pend_object_init (& sem- > pend_obj, PEND_TYPE_SEM); sem- > count = init_count; return knot;} destroy semaphore

The semaphore destruction function is destroyed directly according to the semaphore control block. After the semaphore is destroyed, all the information of the semaphore will be cleared, and the semaphore cannot be used again. When the semaphore is destroyed, there are tasks in the waiting list. It is necessary for the system to wake up these waiting tasks and inform the task semaphore that the PEND_STATE_DESTROY has been destroyed. A task schedule is then generated to switch to the highest priority task execution.

The processing flow for semaphore destruction by TencentOS tiny is as follows:

Call the pend_is_nopending () function to determine whether there is a task waiting for the semaphore

If so, the pend_wakeup_all () function is called to wake up these tasks and tell them that the wait task semaphore has been destroyed (that is, set the wait state member variable pend_state in the task control block to PEND_STATE_DESTROY).

Call the pend_object_deinit () function to clear the contents of the semaphore control block, the most important thing is to set the resource type in the control block to PEND_TYPE_NONE, so that the semaphore cannot be used.

Perform task scheduling knl_sched ()

Note: if the RAM of the semaphore control block is statically allocated by the compiler, this memory cannot be freed even if the semaphore is destroyed. Of course, you can also use dynamic memory to allocate memory for semaphore control blocks, but release the memory after destruction to avoid memory leaks.

_ _ API__ k_err_t tos_sem_destroy (k_sem_t * sem) {TOS_CPU_CPSR_ALLOC (); TOS_PTR_SANITY_CHECK (sem); # if TOS_CFG_OBJECT_VERIFY_EN > 0u if (! pend_object_verify (& sem- > pend_obj, PEND_TYPE_SEM)) {return Knowled OBJINVALID;} # endif TOS_CPU_INT_DISABLE () If (! pend_is_nopending (& sem- > pend_obj)) {pend_wakeup_all (& sem- > pend_obj, PEND_STATE_DESTROY);} pend_object_deinit (& sem- > pend_obj); TOS_CPU_INT_ENABLE (); knl_sched (); return Knowerr until now;} get semaphore

The tos_sem_pend () function is used to get the semaphore, and the task can only get the semaphore when the semaphore is valid. When a task acquires a semaphore, the available number of the semaphore is reduced by one. When it is 0, the task of obtaining the semaphore will enter the blocking state, and the blocking time timeout is specified by the user. When the semaphore cannot be obtained at the specified time, the timeout will be sent, and the waiting task will automatically return to the ready state.

The process of getting the semaphore is as follows:

First check whether the passed parameters are correct.

Determine whether the count member variable in the semaphore control block is greater than 0, which means that there is an available semaphore, subtract the value of the count member variable by 1, and return K_ERR_NONE after the task is successfully obtained.

If there is no semaphore, the currently acquired task may be blocked to see if the blocking time specified by the user timeout is not blocking TOS_TIME_NOWAIT, and if it is not blocked, the K_ERR_PEND_NOWAIT error code is returned directly.

If the scheduler is locked knl_is_sched_locked (), the wait operation cannot be performed and the error code K_ERR_PEND_SCHED_LOCKED is returned. After all, the task needs to be switched, and the scheduler cannot switch tasks if the scheduler is locked.

Call the pend_task_block () function to block the task, which actually removes the task from the ready list and inserts it into the waiting list object- > list. If the waiting time is not permanent waiting for TOS_TIME_FOREVER, it inserts the task into the time list k_tick_list with a blocking time of timeout, and then makes a task scheduling knl_sched ().

When the program can reach pend_state2errno (), it means that the task has obtained the semaphore, or the wait timeout has occurred, then call the pend_state2errno () function to get the wait status of the task, see which situation causes the task to resume running, and return the result to the task that called to get the semaphore.

Note: when the task of getting the semaphore can resume running from the blocking, it may not necessarily get the semaphore, or it may be a timeout, so it is necessary to judge the status of the acquired semaphore when writing the program. If it is K_ERR_NONE, it means it is successful!

_ _ API__ k_err_t tos_sem_pend (k_sem_t * sem, k_tick_t timeout) {TOS_CPU_CPSR_ALLOC (); TOS_PTR_SANITY_CHECK (sem); TOS_IN_IRQ_CHECK (); # if TOS_CFG_OBJECT_VERIFY_EN > 0u if (! pend_object_verify (& sem- > pend_obj, PEND_TYPE_SEM)) {return K_ERR_OBJ_INVALID } # endif TOS_CPU_INT_DISABLE (); if (sem- > count > (k_sem_cnt_t) 0u) {--sem- > count; TOS_CPU_INT_ENABLE (); return if (timeout = = TOS_TIME_NOWAIT) {/ / no wait, return immediately TOS_CPU_INT_ENABLE (); return K_ERR_PEND_NOWAIT } if (knl_is_sched_locked ()) {TOS_CPU_INT_ENABLE (); return Knowerr é PENDSCHEDLock;} pend_task_block (k_curr_task, & sem- > pend_obj, timeout); TOS_CPU_INT_ENABLE (); knl_sched (); return pend_state2errno (kicking currents task-> pend_state);} release semaphore

Either the task or the interrupt service program can release the semaphore (post). The essence of releasing the semaphore is to add 1 to the value of the count member variable of the semaphore control block, indicating that the semaphore is valid. However, if a task is waiting for this semaphore, the value of the count member variable of the semaphore control block will not change, because to wake up the waiting task, the essence of waking up waiting task is to wait for the task to obtain the semaphore. The value of the count member variable of the semaphore control block is reduced by 1, and the value of the count member variable of the semaphore control block does not change.

In TencentOS tiny, only one waiting task can get the semaphore, or all waiting tasks can get the semaphore. The corresponding API are tos_sem_post () and tos_sem_post_all (), respectively. By the way, the design pattern of tos_sem_post_all () is actually the observer pattern, and when an object of observation changes, then all observers will know that it has changed, as shown in the book "lie Design pattern".

The good design of TencentOS tiny is simplicity and low coupling. These two api interfaces essentially call the sem_do_post () function to release semaphores, but choose different processing methods through different opt parameters.

The processing in the sem_do_post () function is also very simple and straightforward, and its execution ideas are as follows:

First of all, determine whether the semaphore overflowed, because an integer will always overflow, you can't always release the semaphore to add 1 to the value of the count member variable, so you must judge whether it is overflowed. If the value of sem- > count is (k_sem_cnt_t)-1, it means it has overflowed and cannot continue to release the semaphore and return the error code K_ERR_SEM_OVERFLOW.

Call the pend_is_nopending () function to determine whether there is a task waiting for the semaphore. If not, add the value of the count member variable to 1, and return K_ERR_NONE to indicate that the semaphore is released successfully, because if there is no wake-up task, there is no need for task scheduling and can be returned directly.

If there is a task waiting for the semaphore, the value of the count member variable does not need to be increased by 1. You can directly call pend_wakeup to wake up the corresponding task. The wake-up task wakes up according to the opt parameter, which can wake up one or all of the waiting tasks.

Perform a task scheduling knl_sched ().

_ _ API__ k_err_t tos_sem_post (k_sem_t * sem) {TOS_PTR_SANITY_CHECK (sem); return sem_do_post (sem, OPT_POST_ONE);} _ API__ k_err_t tos_sem_post_all (k_sem_t * sem) {TOS_PTR_SANITY_CHECK (sem); return sem_do_post (sem, OPT_POST_ALL) } _ _ STATIC__ k_err_t sem_do_post (k_sem_t * sem, opt_post_t opt) {TOS_CPU_CPSR_ALLOC (); # if TOS_CFG_OBJECT_VERIFY_EN > 0u if (! pend_object_verify (& sem- > pend_obj, PEND_TYPE_SEM)) {return Knowled OBJINVALID;} # endif TOS_CPU_INT_DISABLE () If (sem- > count = = (k_sem_cnt_t)-1) {TOS_CPU_INT_ENABLE (); return KnowledgeSEMFLOW;} if (pend_is_nopending (& sem- > pend_obj)) {+ + sem- > count; TOS_CPU_INT_ENABLE (); return Knowled NONEE;} pend_wakeup (& sem- > pend_obj, PEND_STATE_POST, opt) TOS_CPU_INT_ENABLE (); knl_sched (); return kilometer NONEN;}

Why do you judge that sem- > count is (k_sem_cnt_t)-1 represents an overflow? I give a simple example in C language:

# include int main () {unsigned int a = ~ 0; if (a = = (unsigned int) 0XFFFFFFFF) {printf ("OK\ n");} if (a = = (unsigned int)-1) {printf ("OK\ n");} printf ("unsigned int a =% d\ n", a); return 0 Output: OKOKunsigned int a =-1 at this point, the study of "the principle of TencentOS tiny semaphores and the methods of creating, destroying and obtaining semaphores" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report