同步操作将从 OpenHarmony/docs 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
Semaphore is a mechanism for implementing inter-task communication. It implements synchronization between tasks or exclusive access to shared resources.
In the data structure of a semaphore, there is a value indicating the number of shared resources available. The value can be:
The semaphore for exclusive access is different from the semaphore for synchronization:
Semaphore Control Block
/**
* Data structure of the semaphore control block
*/
typedef struct {
UINT16 semStat; /* Semaphore status */
UINT16 semType; /* Semaphore type*/
UINT16 semCount; /* Semaphore count*/
UINT16 semId; /* Semaphore index*/
LOS_DL_LIST semList; /* Mount the task blocked by the semaphore.*/
} LosSemCB;
Working Principles
Semaphore allows only a specified number of tasks to access a shared resource at a time. When the number of tasks accessing the resource reaches the limit, other tasks will be blocked until the semaphore is released.
Semaphore initialization
The system allocates memory for the semaphores configured (you can configure the number of semaphores using the LOSCFG_BASE_IPC_SEM_LIMIT macro), initializes all semaphores to be unused semaphores, and adds them to a linked list for the system to use.
Semaphore creation
The system obtains a semaphore from the linked list of unused semaphores and assigns an initial value to the semaphore.
Semaphore request
If the counter value is greater than 0, the system allocates a semaphore, decreases the value by 1, and returns a success message. Otherwise, the system blocks the task and moves the task to the end of a task queue waiting for semaphores. The wait timeout period can be set.
Semaphore release
When a semaphore is released, if there is no task waiting for it, the counter value is increased by 1. Otherwise, the first task in the wait queue is woken up.
Semaphore deletion
The system sets a semaphore in use to unused state and inserts it to the linked list of unused semaphores.
The following figure illustrates the semaphore working mechanism.
Figure 1 Semaphore working mechanism for small systems
Table 1 Semaphore module APIs
NOTE: As interrupts cannot be blocked, semaphores cannot be requested in block mode for interrupts.
This example implements the following:
The sample code is as follows:
#include "los_sem.h"
#include "securec.h"
/* Task ID*/
static UINT32 g_testTaskId01;
static UINT32 g_testTaskId02;
/* Task priority */
#define TASK_PRIO_TEST 5
/* Semaphore structure ID*/
static UINT32 g_semId;
VOID ExampleSemTask1(VOID)
{
UINT32 ret;
printf("ExampleSemTask1 try get sem g_semId, timeout 10 ticks.\n");
/* Request the semaphore in scheduled block mode, with a wait timeout period of 10 ticks.*/
ret = LOS_SemPend(g_semId, 10);
/* The semaphore is acquired.*/
if (ret == LOS_OK) {
LOS_SemPost(g_semId);
return;
}
/* The semaphore is not acquired when the timeout period has expired.*/
if (ret == LOS_ERRNO_SEM_TIMEOUT) {
printf("ExampleSemTask1 timeout and try get sem g_semId wait forever.\n");
/* Request the semaphore in permanent block mode.*/
ret = LOS_SemPend(g_semId, LOS_WAIT_FOREVER);
printf("ExampleSemTask1 wait_forever and get sem g_semId.\n");
if (ret == LOS_OK) {
LOS_SemPost(g_semId);
return;
}
}
}
VOID ExampleSemTask2(VOID)
{
UINT32 ret;
printf("ExampleSemTask2 try get sem g_semId wait forever.\n");
/* Request the semaphore in permanent block mode.*/
ret = LOS_SemPend(g_semId, LOS_WAIT_FOREVER);
if (ret == LOS_OK) {
printf("ExampleSemTask2 get sem g_semId and then delay 20 ticks.\n");
}
/* Enable the task to enter sleep mode for 20 ticks.*/
LOS_TaskDelay(20);
printf("ExampleSemTask2 post sem g_semId.\n");
/* Release the semaphore.*/
LOS_SemPost(g_semId);
return;
}
UINT32 ExampleSem(VOID)
{
UINT32 ret;
TSK_INIT_PARAM_S task1;
TSK_INIT_PARAM_S task2;
/* Create a semaphore.*/
LOS_SemCreate(0, &g_semId);
/* Lock task scheduling.*/
LOS_TaskLock();
/* Create task 1.*/
(VOID)memset_s(&task1, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));
task1.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleSemTask1;
task1.pcName = "TestTask1";
task1.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
task1.usTaskPrio = TASK_PRIO_TEST;
ret = LOS_TaskCreate(&g_testTaskId01, &task1);
if (ret != LOS_OK) {
printf("task1 create failed .\n");
return LOS_NOK;
}
/* Create task 2.*/
(VOID)memset_s(&task2, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));
task2.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleSemTask2;
task2.pcName = "TestTask2";
task2.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
task2.usTaskPrio = (TASK_PRIO_TEST - 1);
ret = LOS_TaskCreate(&g_testTaskId02, &task2);
if (ret != LOS_OK) {
printf("task2 create failed.\n");
return LOS_NOK;
}
/* Unlock task scheduling.*/
LOS_TaskUnlock();
ret = LOS_SemPost(g_semId);
/* Enable the task to enter sleep mode for 400 ticks.*/
LOS_TaskDelay(400);
/* Delete the semaphore. */
LOS_SemDelete(g_semId);
return LOS_OK;
}
The development is successful if the return result is as follows:
ExampleSemTask2 try get sem g_semId wait forever.
ExampleSemTask2 get sem g_semId and then delay 20 ticks.
ExampleSemTask1 try get sem g_semId, timeout 10 ticks.
ExampleSemTask1 timeout and try get sem g_semId wait forever.
ExampleSemTask2 post sem g_semId.
ExampleSemTask1 wait_forever and get sem g_semId.
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。