Development Guidelines

Available APIs

Table 1 APIs of the mutex module

Category

API

Description

Creating or deleting a mutex

LOS_MuxCreate

Creates a mutex.

LOS_MuxDelete

Deletes the specified mutex.

Requesting or releasing a mutex

LOS_MuxPend

Requests the specified mutex.

LOS_MuxPost

Releases the specified mutex.

How to Develop

The typical mutex development process is as follows:

  1. Call LOS_MuxCreate to create a mutex.

  2. Call LOS_MuxPend to request a mutex.

    The following modes are available:

    • Non-block mode: A task acquires the mutex if the requested mutex is not held by any task or the task holding the mutex is the same as the task requesting the mutex.
    • Permanent block mode: A task acquires the mutex if the requested mutex is not occupied. If the mutex is occupied, the task will be blocked and the task with the highest priority in the ready queue will be executed. The blocked task can be unlocked and executed only when the mutex is released.
    • Scheduled block mode: A task acquires the mutex if the requested mutex is not occupied. If the mutex is occupied, the task will be blocked and the task with the highest priority in the ready queue will be executed. The blocked task can be executed only when the mutex is released within the specified timeout period or when the specified timeout period expires.
  3. Call LOS_MuxPost to release a mutex.

    • If tasks are blocked by the specified mutex, the task with a higher priority will be unblocked when the mutex is released. The unblocked task changes to the Ready state and is scheduled.
    • If no task is blocked by the specified mutex, the mutex is released successfully.
  4. Call LOS_MuxDelete to delete a mutex.

NOTE:

  • Two tasks cannot lock the same mutex. If a task attempts to lock a mutex held by another task, the task will be blocked until the mutex is unclocked.
  • Mutexes cannot be used in the interrupt service program.
  • When using the LiteOS-M kernel, OpenHarmony must ensure real-time task scheduling and avoid long-time task blocking. Therefore, a mutex must be released as soon as possible after use.
  • When a mutex is held by a task, the task priority cannot be changed by using APIs such as LOS_TaskPriSet.

Development Example

Example Description

This example implements the following:

  1. Create the Example_TaskEntry task. In this task, create a mutex, lock task scheduling, create two tasks Example_MutexTask1 (with a lower priority) and Example_MutexTask2 (with a higher priority), and unlock task scheduling.
  2. When being scheduled, Example_MutexTask2 requests a mutex in permanent block mode. After acquiring the mutex, Example_MutexTask2 enters the sleep mode for 100 ticks. Example_MutexTask2 is suspended, and Example_MutexTask1 is woken up.
  3. Example_MutexTask1 requests a mutex in scheduled block mode, and waits for 10 ticks. Because the mutex is still held by Example_MutexTask2, Example_MutexTask1 is suspended. After 10 ticks, Example_MutexTask1 is woken up and attempts to request a mutex in permanent block mode. Example_MutexTask1 is suspended because the mutex is still held by Example_MutexTask2.
  4. After 100 ticks, Example_MutexTask2 is woken up and releases the mutex, and then Example_MutexTask1 is woken up. Example_MutexTask1 acquires the mutex and then releases the mutex. At last, the mutex is deleted.

Sample Code

The sample code is as follows:

#include <string.h>
#include "los_mux.h"

/* Mutex handler ID*/
UINT32 g_testMux;
/* Task ID*/
UINT32 g_testTaskId01;
UINT32 g_testTaskId02;

VOID Example_MutexTask1(VOID)
{
    UINT32 ret;

    printf("task1 try to get  mutex, wait 10 ticks.\n");
    /* Request a mutex.*/
    ret = LOS_MuxPend(g_testMux, 10);

    if (ret == LOS_OK) {
        printf("task1 get mutex g_testMux.\n");
         /*Release the mutex.*/
        LOS_MuxPost(g_testMux);
        return;
    } 
    if (ret == LOS_ERRNO_MUX_TIMEOUT ) {
            printf("task1 timeout and try to get mutex, wait forever.\n");
            /* Request a mutex.*/
            ret = LOS_MuxPend(g_testMux, LOS_WAIT_FOREVER);
            if (ret == LOS_OK) {
                printf("task1 wait forever, get mutex g_testMux.\n");
                /*Release the mutex.*/
                LOS_MuxPost(g_testMux);
                /* Delete the mutex. */
                LOS_MuxDelete(g_testMux);
                printf("task1 post and delete mutex g_testMux.\n");
                return;
            }
    }
    return;
}

VOID Example_MutexTask2(VOID)
{
    printf("task2 try to get  mutex, wait forever.\n");
    /* Request a mutex.*/
    (VOID)LOS_MuxPend(g_testMux, LOS_WAIT_FOREVER);

    printf("task2 get mutex g_testMux and suspend 100 ticks.\n");

     /* Enable the task to enter sleep mode for 100 ticks.*/
    LOS_TaskDelay(100);

    printf("task2 resumed and post the g_testMux\n");
    /* Release the mutex.*/
    LOS_MuxPost(g_testMux);
    return;
}

UINT32 Example_TaskEntry(VOID)
{
    UINT32 ret;
    TSK_INIT_PARAM_S task1;
    TSK_INIT_PARAM_S task2;

    /* Create a mutex.*/
    LOS_MuxCreate(&g_testMux);

    /* Lock task scheduling.*/
    LOS_TaskLock();

    /* Create task 1.*/
    memset(&task1, 0, sizeof(TSK_INIT_PARAM_S));
    task1.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_MutexTask1;
    task1.pcName       = "MutexTsk1";
    task1.uwStackSize  = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
    task1.usTaskPrio   = 5;
    ret = LOS_TaskCreate(&g_testTaskId01, &task1);
    if (ret != LOS_OK) {
        printf("task1 create failed.\n");
        return LOS_NOK;
    }

    /* Create task 2.*/
    memset(&task2, 0, sizeof(TSK_INIT_PARAM_S));
    task2.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_MutexTask2;
    task2.pcName       = "MutexTsk2";
    task2.uwStackSize  = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
    task2.usTaskPrio   = 4;
    ret = LOS_TaskCreate(&g_testTaskId02, &task2);
    if (ret != LOS_OK) {
        printf("task2 create failed.\n");
        return LOS_NOK;
    }

    /* Unlock task scheduling.*/
    LOS_TaskUnlock();

    return LOS_OK;
}

Verification

The development is successful if the return result is as follows:

task2 try to get  mutex, wait forever.
task2 get mutex g_testMux and suspend 100 ticks.
task1 try to get  mutex, wait 10 ticks.
task1 timeout and try to get mutex, wait forever.
task2 resumed and post the g_testMux
task1 wait forever, get mutex g_testMux.
task1 post and delete mutex g_testMux.