Monday, 3 January 2022

Nichestack OS tutorial 2 - NET Resource method and Critical Section

There are two types of mutexes present in the Nichestack OS. They are: 

     1. NET Resource Method: This allows the programmer to obtain and release a mutex for accessing the shared resources. The API's used to obtain and release the mutexes are LOCK_NET_RESOURCE() and UNLOCK_NET_RESOURCE() respectively

In-order to use this mutex for a project we must create it first. Usually, the mutexes are created during the OS initialization phase by calling the mutex create API. All the mutexes used in a project will be available in the ipport.h file. Based on the maximum mutex number ID the mutexes will be created during the OS initialization phase.

The nichestack OS also has the TRY_NET_RESOURCE () and UNLOCK_NET_RESOURCE() locking mechanism. The difference between LOCK_NET_RESOURCE and TRY_NET_RESOURCE is the former will wait until we acquire the mutex, but the latter checks if we can get the mutex or not else skip.

Few mandatory mutexes present in the Nichestack OS are NET_RESID, RXQ_RESID and FREEQ_RESID. The NET_RESID must be obtained by the higher-level application while accessing the Sockets, TCP, UDP and the IP layers of the stack. RXQ_RESID must be obtained while accessing the data queue structure (getq() and putq()). FREEQ_RESID must be obtained while accessing the free packet buffer queue structure (PK_ALLOC() and PK_FREE()).

Points to consider while porting, if one task is obtained the NET_RESID mutex then the other task needs to wait till the first task release it. There won’t be any effect between different mutexes that means if one task is locking the NET_RESID then other task can obtain other mutexes except the NET_RESID mutex. If there is a case in which a task needs both the NET_RESID and FREE_RESID then NET_RESID should be locked first followed by FREE_RESID and for releasing FREE_RESID followed by NET_RESID mutex. Same will be applicable in the case of RX_RESID and FREE_RESID

The porting engineer can add a new mutex, if they want to protect the shared resources. One use case scenario for this, consider there are multiple client instances accessing the shared memory variables, then it must be protected using a mutex.

Never try to do nesting on same mutex calls. For example:

Task1()

{

LOCK_NET_RESOURCE(NET_RESID);

          ……………

          LOCK_NET_RESOURCE(NET_RESID);

}

Here we are trying to access the same           mutex twice in the task function.

Use case Scenario of NET Resource       method implementation:

Consider there are 2 tasks, FTP

Task and Telnet Task and the FTP task needs to get the received data on a blocking socket. The FTP task locked the NET_RESID mutex and because it is configured as blocking socket, it will wait till the data arrives, but the data is delaying for a long time, now inside the lower TCP layer the tcp_sleep() function will be automatically called and tcp_sleep() will release the NET_RESID lock from the FTP task and change the state to suspended. Also tcp_sleep() function will wait for the receive signal(SIGWAIT).
Now NET_RESID is free and the TELNET task needs to access the socket for getting its received data. If the telnet data is already available then read the data and does the processing and release the NET_RESID mutex, if not telnet task needs to follow the same steps like mentioned in the FTP case and release the mutex.

2. Critical Section Method: The difference between the Net resource method and      critical section is the latter will be used in the lower layers of the OS like getting and  putting the queue and also other task related functions(tk_XXX)

The API's used for the entering and exiting the critical sections are: ENTER_CRIT_SECTION() and EXIT_CRIT_SECTION() respectively While entering the critical section, all the interrupts will be disabled and enable it back while exiting the critical section.

The Nichestack OS and TCP/IP stack can run on top of a RTOS or directly on the hardware. If there is no RTOS and the ISR will not access any shared resource, then the Enter and Exit critical section API's were no-ops. If the ISR is accessing the shared resource, then the Critical section method should be used.

In the case of hard real time system projects care should be taken that the ISR will not access any shared resources. So while entering the critical section only other tasks needs to be waited not the ISR.

The entering and exiting process sometimes can be nested. For example:     

Func1()

{

          ENTER_CRIT_SECTION()

          …………

          EXIT_CRIT_SECTION ()

}

Func2()                                       

{

          ENTER_CRIT_SECTION()

          Func1();

          ……….

          EXIT_CRIT_SECTION ()

}


The main difference between the critical section and mutex is the former will completely disables all the interrupts but the latter only block other tasks to access the shared resource. The critical section method is mostly used in the low levels and due to the reason that it is disabling the interrupts, the execution should not delay too much.


Please check out this project to get more details about the implementation.

https://github.com/songwenshuai/NICHESTACK

No comments:

Post a Comment