cmutexatomiccontikicontiki-process

Mutual exclusion within a function Contiki


Because the in built list provided by Contiki doesn't fit my needs (uses too much memory) I have implemented my own list version that has been optimized for how I intend to use it.

At any one time there will be a single one of these lists that will be operated on (i.e. add/remove elements) by multiple processes/protothreads. However, additions/removals do not occur within a process/protothread block, but instead are called within a function that is called through a series of function calls initiated by a process/protothread.

For example,

void funct2()
{
    // add or remove element from shared list
}

void func1()
{
    // some stuff
    func2();
    // more stuff
}

PROCESS_THREAD(temp1, ev, data)
{
    PROCESS_BEGIN();
    func1();
    PROCESS_END();
}

PROCESS_THREAD(temp2, ev, data)
{
    PROCESS_BEGIN();
    func1();
    PROCESS_END();
}

As a result, I can't use Contiki's in built mechanisms to create a mutex (via using pt-sem.h) since it must appear within a process/protothread block. This is because while I could create a lock within the actual process block (see below), this will result in blocking processes for much longer than is necessary

PROCESS_THREAD(temp2, ev, data)
{
    PROCESS_BEGIN();
    // get lock
    func1();
    // release lock
    PROCESS_END();
}

This is very problematic since adding and removing elements from my list is not atomic; if an interrupt occurs while removing or adding an element to the list things will not behave properly. Is it possible to easily do what I want; namely atomically add and remove elements from a list within a function call as opposed to within a process/protothread block?


Solution

  • You seem to be confused about what protothreads do. The protothread approach is a form of cooperative scheduling. A protothread can only yield at specific points, when asked to yield by the execution flow. An interrupt can never switch the execution flow to another protothread.

    So, there are two distinct options:

    1) If your list is accessed both from protothread and from interrupt handler contexts, you need to do all modifications in the list with interrupts disabled. So your lock/unlock code is disable/enable interrupts, respectively.

    2) If your list is only accessed from protothreads, you don't need any locking. This is the recommended design.

    Indeed, the main advantage of using protothreads is that in 99% of cases locks are not needed.