source: qutecom-coip/libs/timer/src/clock_gettime/impl_timer.c @ 125:d648f4cb122f

Last change on this file since 125:d648f4cb122f was 125:d648f4cb122f, checked in by laurent, 3 years ago

wengo => qutecom

File size: 4.1 KB
Line 
1/*
2 * QuteCom, a voice over Internet phone
3 * Copyright (C) 2010 Mbdsys
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20/*
21 * @author David Ferlier
22 *
23 * Timer implementation for POSIX systems. It uses pthreads + clock_gettime
24 *
25 */
26
27#include <wtimer.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <pthread.h>
31#include <signal.h>
32#include <time.h>
33#include <unistd.h>
34#include <assert.h>
35#include <string.h>
36
37//#define TIMER_DEBUG
38
39#define CLOCKS_PER_NANOSEC      (CLOCKS_PER_SEC / 1000000000.)
40
41struct clock_gettime_metadata {
42    struct sigaction sa;
43    struct timespec ts;
44    int running;
45    pthread_t w_timer_thread;
46    pthread_mutex_t w_timer_mutex;
47};
48
49w_timer_t *cgt_timer_create () {
50    w_timer_t *ti;
51
52    ti = (w_timer_t *) malloc (sizeof(w_timer_t));
53    memset(ti, 0, sizeof(w_timer_t));
54    ti->impl_data = malloc (sizeof(struct clock_gettime_metadata));
55
56    return ti;
57}
58
59void cgt_timer_set_delay(w_timer_t *ti, timer_delay_t delay) {
60    struct clock_gettime_metadata *ptm = (struct clock_gettime_metadata *)
61                                       ti->impl_data;
62
63    ptm->ts.tv_sec = 0;
64    ptm->ts.tv_nsec = delay * 1000 * 1000;
65}
66
67void cgt_timer_set_callback(w_timer_t *ti, void (*callback)(void *)) {
68    assert(ti != 0);
69    ti->callback = callback;
70}
71
72void ts_sub(register struct timespec *out, register struct timespec *in) {
73    out->tv_nsec -= in->tv_nsec;
74
75    while (out->tv_nsec < 0) {
76        --out->tv_sec;
77        out->tv_nsec += 1000 * 1000 * 1000;
78    }
79
80    out->tv_sec -= in->tv_sec;
81}
82
83void * cgt_timer_thread(void *parg) {
84    w_timer_t *ti = (w_timer_t *) parg;
85    struct clock_gettime_metadata *ptm = (struct clock_gettime_metadata *)
86                                       ti->impl_data;
87
88    struct timespec ts_start;
89    struct timespec ts_end;
90    struct timespec ts_tosleep;
91
92        while (ptm->running) {
93                ts_start.tv_nsec = clock() / CLOCKS_PER_NANOSEC;
94
95        if (ti->callback) {
96            ti->callback(ti->userdata);
97                }
98       
99                ts_end.tv_nsec = clock() / CLOCKS_PER_NANOSEC;
100
101        ts_tosleep.tv_nsec = ptm->ts.tv_nsec;
102        ts_tosleep.tv_nsec -= (ts_end.tv_nsec - ts_start.tv_nsec);
103
104        if (ts_tosleep.tv_nsec <= 0) {
105            ts_tosleep.tv_nsec = 0;
106        }
107
108        if (ts_tosleep.tv_nsec > ptm->ts.tv_nsec) {
109            ts_tosleep.tv_nsec = ptm->ts.tv_nsec;
110        }
111
112        nanosleep(&ts_tosleep, NULL);
113
114#ifdef TIMER_DEBUG
115        printf("Timer: user %d, effective %d\n",
116            ptm->ts.tv_nsec / 1000 / 1000, (ts_tosleep.tv_nsec) / 1000 / 1000);
117#endif
118    }
119    return 0;
120}
121
122int cgt_timer_start(w_timer_t *ti) {
123    struct clock_gettime_metadata *ptm = (struct clock_gettime_metadata *)
124                                       ti->impl_data;
125
126    ptm->running = 1;
127    pthread_create(&ptm->w_timer_thread, NULL, cgt_timer_thread, ti);
128    return 0;
129}
130
131int cgt_timer_stop(w_timer_t *ti) {
132    struct clock_gettime_metadata *ptm = (struct clock_gettime_metadata *)
133                                       ti->impl_data;
134    ptm->running = 0;
135    //pthread_join(&ptm->w_timer_thread, NULL);
136        usleep(2*ptm->ts.tv_nsec / 1000);
137        return 0;
138}
139
140void cgt_timer_set_userdata(w_timer_t *ti, void *userdata) {
141    ti->userdata = userdata;
142}
143
144void cgt_timer_destroy(w_timer_t *ti) {
145    free(ti->impl_data);
146}
147
148struct timer_impl clock_gettime_impl = {
149    "clock_gettime",
150    cgt_timer_create,
151    cgt_timer_set_delay,
152    cgt_timer_set_callback,
153    cgt_timer_set_userdata,
154    cgt_timer_start,
155    cgt_timer_stop,
156    cgt_timer_destroy,
157};
158
Note: See TracBrowser for help on using the repository browser.