[En-Nut-Discussion] Feature Request 1572837: mutex API nesting level info

Nathan Moore nategoose at gmail.com
Fri Jul 18 19:22:30 CEST 2008


> Sure, when you write alone 100% of the application code and stay as the
> only maintainer and you write extensive documentation in the code you
> may use recursive mutexes and have not much problem, however if your
> work is shared or if someone (even yourself!) comes some time later to
> perform changes on the code, then recursive mutexes may appear as black
> magic.
>

>
> An excellent explanation about why to avoid recursive mutexes by someone
> that knows what he writes about:
>
> http://www.zaval.org/resources/library/butenhof1.html

Exactly the opposite because NutOs doesn't have preemptable threading.
That was all about using mutexes to protect memory-type resources, not IO
that can block.
In NutOs you protect memory resources with critical sections (turning off
interrupts) which
are the widest form of mutex (and sadly are recursive, which I will argue
against until I'm blue
in the face).   The only thing that can step on your memory resource usage
is an ISR unless
you throw NutThreadYields (directly or indirectly) into the middle of them.
His (from the link) arguments about holding mutexes for the shortest
possible time isn't as valid
on a system that doesn't have thread preemption since you effectively have
an "I'm the running
thread" mutex until you call the yield function anyway.

Recursive mutexes are very very good for IO routines, which do have
NutThreadYields in the
middle of them.
Say I have the code:

void print_record(FILE * f, struct record * r) {
  NutMutexLock(&(f->o_lock));
  fprintf(f, "%s : %i\t%f\n", r->name, r->count, r->percent);
  NutMutexUnlock(&(f->o_lock));
}

void print_status(FILE *f) {
  struct record * r;
  NutMutexLock(&(f->o_lock));
  fprintf(f, "Current status:\n");
  for (r = record_list; r; r = r->next) {
    print_record(f, r);
  }
  NutMutexUnlock(&(f->o_lock));
}

void print_record_named(char *n) {
   struct record *r;
   for (r = record_list, r, r = r->next) {
           if (0 == strcmp(n, r->name) ) {
              print_record(f, r);
           }
    }
}

Without the recursive mutex (which isn't actually in nut's FILE struct)
running code that uses these
(or any fprintf(f, ...) for that matter) could not guarentee that all of
their output was contiguous.
A higher priority thread could pop in there and write it's junk in the
middle of this output.
With the recursive mutex you can reuse component print functions and also
lock at the higher level
when you need to print other stuff together with those.

Nathan



More information about the En-Nut-Discussion mailing list