In case of one-shot timer i can use semaphore to wait for timer callback completion. But if timer was fired several times it doesn't help. Consider the following code:
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#define N 10
void timer_threaded_function(sigval_t si)
{
uint8_t *shared_resource = si.sival_ptr;
sleep(rand() % 7);
/* ... manipulate with shared_resource */
return;
}
int main()
{
struct sigevent sig_ev = {0};
uint8_t *shared_resource = malloc(123);
timer_t timer_id;
int i;
sig_ev.sigev_notify = SIGEV_THREAD;
sig_ev.sigev_value.sival_ptr = shared_resource;
sig_ev.sigev_notify_function = timer_threaded_function;
sig_ev.sigev_notify_attributes = NULL;
timer_create(CLOCK_REALTIME, &sig_ev, &timer_id);
for (i = 0; i < N; i++) {
/* arm timer for 1 nanosecond */
timer_settime(timer_id, 0,
&(struct itimerspec){{0,0},{0,1}}, NULL);
/* sleep a little bit, so timer will be fired */
usleep(1);
}
/* only disarms timer, but timer callbacks still can be running */
timer_delete(timer_id);
/*
* TODO: safe wait for all callbacks to end, so shared resource
* can be freed without races.
*/
...
free(shared_resource);
return 0;
}
timer_delete() only disarms timer (if it is was armed) and frees assocoated with timer resources. But timer callbacks still can be running. So we cannot free shared_resource, otherwise race condition may occur. Is there any method to cope with this situation?
I thougth about reference counting, but it doesn't help, because we doesn't know how much threads actually will try to access shared resource (cause of timer overruns).