This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

How to implement a mutex or 'critical section' of code within z-stack app?

Other Parts Discussed in Thread: Z-STACK

I've got a shared resource that I want to protect from collisions by separate tasks, and I don't see any mutex type feature implemented within the z-stack code. 

I don't want to disable interrupts, as the resource is actually the SPI interface, but I do want to avoid a second task attempting to use that interface at the same time a transaction is in progress with another peripheral. 

Has anyone found a good approach to implementing something along the lines of a "critical section" such that the OSAL won't swap a task while I am checking / changing a variable?   If I can just be sure that 2-3 statements will execute atomically, I'll be able to accomplish this with just a boolean variable. 

  • Hi Ben,

    In general:

    The type of Operating System (OSAL) used in Zstack uses a "round robin" concept to switch between

    the registered tasks, however, it does not allocates x time slot for every task and takes control from the

    task in the end of the x time slot, no matter what. Try it by inserting while(1); expression somewhere in

    the code and you'll see that nothing works as supposed to and the code execution stuck on the while(1)

    endless loop.

     

    From here, I'll be dividing my answer into two parts:

    1. You'r accessing directly to the SPI data buffer by some funtion (not through DMA mechanism
      or constant polling). In this case, the SPI access function is probably a blocking one. So, you
      really don't have to worry about OSAL switching  tasks in the middle of access to SPI data buffer. 
      By dismissing the event you currently in, you'll be dismissing the current task, therefore the
      OSAL will switch to the next pending event in other task.
    2. The DMA or a polling mechanism reads data from the SPI data buffer and writes to a global
      buffer (or you'r writing to the SPI data buffer by transferring data from some global buffer).
      In this case, you probably want to protect the global buffer/s and not the SPI acces. So, here
      you can use a boolean variable for protection... which, of course, you should be protecting too. :)

    Hope this helps.

    Igor

  • There isn't any direct method within C to do this as there are no atomic guaranteed read-modify-write operations in the C language.  This is partly why the "critical section" code macros were created as disabling interrupts is the only viable approach entirely within C and even then we are usually playing with some intrinsics to achieve enabling/disabling interrupts.

    However, all is not lost as you can create a small function in assembly to accomplish what you want.  It depends on the platform of course.  If you are on the 8051 processor, you can utilize the XCH instruction to do an atomic swap of a memory location and the accumulator.  If you are on the MSP430 processor, there is a SWAPB instruction which you can use to swap two adjacent bytes in memory so you can update one, swap them and then test the swapped out value.

    The process works just like you would expect a mutex to work.  You create a value which indicates the resource is currently acquired, swap that value with the semaphore indicating resource acquisition, and test the result to see if it was free before you swapped the bytes.  If it was free, then you have successfully acquired the resource, if it was not free you simply replaced the acquired flag with the same value and have not violated the system.

    If you are uncomfortable interfacing assembly with C, you can accomplish a similar thing utilizing a separate thread for the resource and allow it to manage itself with respect to allocating it to another thread.  In this manner, each thread which wishes to obtain access to the resource will create a variable that only it is allowed to write to.  The resource thread will do the same.  Then each thread will simply set it's variable to a value indicating it wants to acquire the resource and pend its operation.  When the resource thread runs it will look at all threads which can request it and set the resources variable to a value which indicates which thread is allowed access and pend operation.  In this way, since only the resource thread can write the variable indicating who currently has acquisition of it, there are not conflicts due to multiple access.  This approach works but it is significantly slower than a general mutex operation as you have to wait for context changes between threads and poll for the response.  You can get even more creative and create call backs to signal a thread it is currently active with respect to the resource but that gets even more complicated.

    Jim Noxon