I have a few spots in my code where I am doing something, and I'm just now
realizing I'm not explicitly sure if it's supported or not.

Here is my question:

Can work_queue be called from within a worker function that uses the same
work_s struct?
Yes.
The documentation only says that if there is existing work, it will be
replaced. But what happens if there is existing work, AND it's currently
running?

I have a few areas where I'm doing it, and it does seem to be working, but
I'm not sure if there are any race conditions or other considerations that
I'm not aware of.

That would be clearer if that read "pending" or "queued" work instead of "existing" work.  The data in the work queue structures is decanted when the work starts:

   128           /* Remove the ready-to-execute work from the list */
   129
   130           dq_rem((struct dq_entry_s *)work, &wqueue->q);
   131
   132           /* Extract the work description from the entry (in
   case the work
   133            * instance by the re-used after it has been de-queued).
   134            */
   135
   136           worker = work->worker;
   137
   138           /* Check for a race condition where the work may be
   nullified
   139            * before it is removed from the queue.
   140            */
   141
   142           if (worker != NULL)
   143             {
   144               /* Extract the work argument (before re-enabling
   interrupts) */
   145
   146               arg = work->arg;
   147
   148               /* Mark the work as no longer being queued */
   149
   150               work->worker = NULL;
   151
   152               /* Do the work.  Re-enable interrupts while the
   work is being
   153                * performed... we don't have any idea how long
   this will take!
   154                */
   155
   156               leave_critical_section(flags);
   157               worker(arg);
   158
   159               /* Now, unfortunately, since we re-enabled
   interrupts we don't
   160                * know the state of the work list and we will
   have to start
   161                * back at the head of the list.
   162                */
   163
   164               flags = enter_critical_section();
   165               work  = (FAR struct work_s *)wqueue->q.head;
   166             }

So the work is no longer queued with the worker function executes.

Greg


Reply via email to