Possible to force os_thread_delay_until() to exit early by modifying system_tick variable

Hello!

I have a lot of code like this:

    ulong last_thread_time = 0;
    ulong interval = 10000;
    t = millis()
    if(t - last_thread_time >= interval)
    {
      do_thing();
      last_thread_time = t;
    }

For some of these events, I'm trying to use the threading features and minimize busy delays, and the os_thread_delay_until() function is suggested and works great.

For some threads, the delay may be quite long, 5-10 minutes; is there a way to force the os_thread_delay() function to return early? With my "normal" code I can manually reset last_thread_time = 0 from another function/thread and this will cause it to run do_thing(). I tried doing a similar behavior to the above and it's not behaving as I expect. Is this normal? Any way around it?

Simplified code for reference:

system_tick_t last_thread_time = 0;
ulong send_interval = 60000;

void setup()
{
    new Thread("upload_thread", uploader_thread_function);
    Particle.function("force_upload", force_upload);
}

void uploader_thread_function(void *param)
{
  while(true)
  {
    Log.info("Uploading");
    // functionality here
    Log.info("done uploading");
    os_thread_delay_until(&last_thread_time, send_interval);
  }
}

int force_upload(String data)
{
  last_thread_time = 0;
  return 1;
}

Thanks for any help!

I think the answer is probably no, but I also noticed something:

The threading explainer is wrong about the first parameter to os_thread_delay_until() which is a thin layer over vTaskDelayUntil(). It should not be zero on first invocation, but rather xTaskGetTickCount() according to the FreeRTOS docs. I think it works because on first invocation 0 will cause the wake time to be in the past in most cases, which causes it to not block but still set the last wake time, so your code will execute twice the first time but then function normally.

I suspect you can't just change the last wake time parameter and have the change take effect, and there does not appear to be call to terminate the wait.

However, I the overhead for swapping a thread to check for wait is so small that it's not really worth optimizing for, as long as you yield CPU using delay(1) or similar. This is probably the best solution if you have a variable wait.

So the following isn't "bad" with the busy wait? I was trying to replace with the os_thread_delay()

system_tick_t last_thread_time = 0;
ulong send_interval = 60000;

void setup()
{
    new Thread("upload_thread", uploader_thread_function);
}

void uploader_thread_function(void *param)
{
  while(true)
  {
    if(millis() - last_thread_time < send_interval_millis)
    {
      delay(1);
      continue;
    }
    last_thread_time = millis();
    Log.info("doing things");
    // do things
    Log.info("Done doing things";
  }
}

It's not that much overhead because you're just doing a test and a delay on each millisecond timeslice, 1000 times per second. Presumably you don't have that mans threads, so the overhead should be small.

However, presumably you don't need your send interval accurate to the nearest millisecond, so you could delay for a longer period, which would lower the overhead more, and still provide a way to wait until the send interval is complete, or force sending early. That's probably what I would do.

Another way to do it would be to halt the uploader_thread_function with a mutex. You then release the mutex either from the force function, or from some other timer. You could use a software timer to trigger the mutex to release, for example.