Skip to content

Instantly share code, notes, and snippets.

@cirocosta
Created August 29, 2015 18:27
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save cirocosta/ab2b73b2e1bb34b83f52 to your computer and use it in GitHub Desktop.
Save cirocosta/ab2b73b2e1bb34b83f52 to your computer and use it in GitHub Desktop.
Posix Interval Timer example w/ threads
/*
* ORIGINAL HEADER
*
* sigev_thread.c
*
* Demonstrate use of the SIGEV_THREAD signal mode to handle
* signals by creating a new thread.
*
* Special notes: This program will not compile on Solaris 2.5.
* It will compile on Digital UNIX 4.0 but will not work.
* Digital UNIX 4.0c fixes SIGEV_THREAD, and sources inform me
* that Solaris 2.6 will also fix SIGEV_THREAD. To try this on
* Solaris 2.5, remove the "#ifdef sun" conditionals in main.
*
* Original:
* http://ptgmedia.pearsoncmg.com/images/0201633922/sourcecode/sigev_thread.c
*/
/**
* CIRO's Header
* This is a slightly modified version of the original one so that
* i can create multiple timers and trigger then in a more
* handy way for my project.
*/
#include <pthread.h>
#include <sys/signal.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <semaphore.h>
#define MILLION 1000000
void err_abort(int status, char* message)
{
fprintf(stderr, "%s\n", message);
exit(status);
}
void errno_abort(char* message)
{
perror(message);
exit(EXIT_FAILURE);
}
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int counter = 0;
/*
* Thread start routine to notify the application when the
* timer expires. This routine is run "as if" it were a new
* thread, each time the timer expires.
*
* When the timer has expired 5 times, the main thread will
* be awakened, and will terminate the program.
*/
void timer_thread(union sigval arg)
{
int status;
status = pthread_mutex_lock(&mutex);
if (status != 0)
err_abort(status, "Lock mutex");
if (++counter >= 5) {
status = pthread_cond_signal(&cond);
if (status != 0)
err_abort(status, "Signal condition");
}
status = pthread_mutex_unlock(&mutex);
if (status != 0)
err_abort(status, "Unlock mutex");
printf("Timer %d\n", counter);
}
void create_timer(unsigned i)
{
timer_t timer_id;
int status;
struct itimerspec ts;
struct sigevent se;
long long nanosecs = MILLION * 100 * i * i;
/*
* Set the sigevent structure to cause the signal to be
* delivered by creating a new thread.
*/
se.sigev_notify = SIGEV_THREAD;
se.sigev_value.sival_ptr = &timer_id;
se.sigev_notify_function = timer_thread;
se.sigev_notify_attributes = NULL;
ts.it_value.tv_sec = nanosecs / 1000000000;
ts.it_value.tv_nsec = nanosecs % 1000000000;
ts.it_interval.tv_sec = 0;
ts.it_interval.tv_nsec = 0;
status = timer_create(CLOCK_REALTIME, &se, &timer_id);
if (status == -1)
errno_abort("Create timer");
// TODO maybe we'll need to have an array of itimerspec
status = timer_settime(timer_id, 0, &ts, 0);
if (status == -1)
errno_abort("Set timer");
}
int main()
{
int status;
unsigned i = 1;
for (; i < 6; i++)
create_timer(i);
status = pthread_mutex_lock(&mutex);
if (status != 0)
err_abort(status, "Lock mutex");
while (counter < 5) {
printf("\tBlocked!\n");
status = pthread_cond_wait(&cond, &mutex);
if (status != 0)
err_abort(status, "Wait on condition");
printf("\tUnblocked!\n");
}
status = pthread_mutex_unlock(&mutex);
if (status != 0)
err_abort(status, "Unlock mutex");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment