Asterisk - The Open Source Telephony Project GIT-master-2de1a68
Data Structures | Macros | Enumerations | Functions | Variables
res_timing_pthread.c File Reference

pthread timing interface More...

#include "asterisk.h"
#include <stdbool.h>
#include <math.h>
#include <unistd.h>
#include <fcntl.h>
#include "asterisk/module.h"
#include "asterisk/timing.h"
#include "asterisk/utils.h"
#include "asterisk/astobj2.h"
#include "asterisk/time.h"
#include "asterisk/lock.h"
Include dependency graph for res_timing_pthread.c:

Go to the source code of this file.

Data Structures

struct  pthread_timer
 

Macros

#define MAX_RATE   100
 
#define PTHREAD_TIMER_BUCKETS   563
 

Enumerations

enum  { PIPE_READ = 0 , PIPE_WRITE = 1 }
 
enum  pthread_timer_state { TIMER_STATE_IDLE , TIMER_STATE_TICKING }
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static void ack_ticks (struct pthread_timer *timer, unsigned int num)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int check_timer (struct pthread_timer *timer)
 
static void * do_timing (void *arg)
 
static int init_timing_thread (void)
 
static int load_module (void)
 
static int pthread_timer_ack (void *data, unsigned int quantity)
 
static void pthread_timer_close (void *data)
 
static int pthread_timer_cmp (void *obj, void *arg, int flags)
 
static void pthread_timer_destructor (void *obj)
 
static int pthread_timer_disable_continuous (void *data)
 
static int pthread_timer_enable_continuous (void *data)
 
static int pthread_timer_fd (void *data)
 
static enum ast_timer_event pthread_timer_get_event (void *data)
 
static unsigned int pthread_timer_get_max_rate (void *data)
 
static int pthread_timer_hash (const void *obj, const int flags)
 
static void * pthread_timer_open (void)
 
static int pthread_timer_set_rate (void *data, unsigned int rate)
 
static int run_timer (void *obj, void *arg, int flags)
 
static void signal_pipe (struct pthread_timer *timer)
 
static int unload_module (void)
 
static void unsignal_pipe (struct pthread_timer *timer)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "pthread Timing Interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_TIMING, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ao2_containerpthread_timers
 
static struct ast_timing_interface pthread_timing
 
static void * timing_funcs_handle
 
struct {
   ast_cond_t   cond
 
   ast_mutex_t   lock
 
   unsigned int   stop:1
 
   pthread_t   thread
 
timing_thread
 Data for the timing thread. More...
 

Detailed Description

pthread timing interface

Author
Russell Bryant russe.nosp@m.ll@d.nosp@m.igium.nosp@m..com

Definition in file res_timing_pthread.c.

Macro Definition Documentation

◆ MAX_RATE

#define MAX_RATE   100

Definition at line 71 of file res_timing_pthread.c.

◆ PTHREAD_TIMER_BUCKETS

#define PTHREAD_TIMER_BUCKETS   563

Definition at line 74 of file res_timing_pthread.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
PIPE_READ 
PIPE_WRITE 

Definition at line 76 of file res_timing_pthread.c.

76 {
77 PIPE_READ = 0,
78 PIPE_WRITE = 1
79};
@ PIPE_WRITE
@ PIPE_READ

◆ pthread_timer_state

Enumerator
TIMER_STATE_IDLE 
TIMER_STATE_TICKING 

Definition at line 81 of file res_timing_pthread.c.

81 {
84};
@ TIMER_STATE_TICKING
@ TIMER_STATE_IDLE

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 476 of file res_timing_pthread.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 476 of file res_timing_pthread.c.

◆ ack_ticks()

static void ack_ticks ( struct pthread_timer timer,
unsigned int  num 
)
static

Definition at line 312 of file res_timing_pthread.c.

313{
314 int pending_ticks = timer->pending_ticks;
315
316 ast_assert(quantity);
317
318 if (quantity > pending_ticks) {
319 quantity = pending_ticks;
320 }
321
322 if (!quantity) {
323 return;
324 }
325
326 timer->pending_ticks -= quantity;
327
328 if ((0 == timer->pending_ticks) && !timer->continuous) {
330 }
331}
static struct ast_timer * timer
Definition: chan_iax2.c:367
static void unsignal_pipe(struct pthread_timer *timer)
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, timer, and unsignal_pipe().

Referenced by pthread_timer_ack().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 476 of file res_timing_pthread.c.

◆ check_timer()

static int check_timer ( struct pthread_timer timer)
static
Return values
0no timer tick needed
non-zerowrite to the timing pipe needed

Definition at line 286 of file res_timing_pthread.c.

287{
288 struct timeval now;
289
290 if (timer->state == TIMER_STATE_IDLE) {
291 return 0;
292 }
293
294 now = ast_tvnow();
295
296 if (timer->tick_count < (ast_tvdiff_ms(now, timer->start) / timer->interval)) {
297 timer->tick_count++;
298 if (!timer->tick_count) {
299 /* Handle overflow. */
300 timer->start = now;
301 }
302 return 1;
303 }
304
305 return 0;
306}
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159

References ast_tvdiff_ms(), ast_tvnow(), timer, and TIMER_STATE_IDLE.

Referenced by run_timer().

◆ do_timing()

static void * do_timing ( void *  arg)
static

Definition at line 395 of file res_timing_pthread.c.

396{
397 struct timeval next_wakeup = ast_tvnow();
398
399 while (!timing_thread.stop) {
400 struct timespec ts = { 0, };
401
403
404 next_wakeup = ast_tvadd(next_wakeup, ast_tv(0, 5000));
405
406 ts.tv_sec = next_wakeup.tv_sec;
407 ts.tv_nsec = next_wakeup.tv_usec * 1000;
408
410 if (!timing_thread.stop) {
413 } else {
415 }
416 }
418 }
419
420 return NULL;
421}
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
@ OBJ_NODATA
Definition: astobj2.h:1044
#define ast_cond_wait(cond, mutex)
Definition: lock.h:205
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:206
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_lock(a)
Definition: lock.h:189
static int run_timer(void *obj, void *arg, int flags)
static struct @483 timing_thread
Data for the timing thread.
static struct ao2_container * pthread_timers
#define NULL
Definition: resample.c:96
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2282
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:235

References ao2_callback, ao2_container_count(), ast_cond_timedwait, ast_cond_wait, ast_mutex_lock, ast_mutex_unlock, ast_tv(), ast_tvadd(), ast_tvnow(), NULL, OBJ_NODATA, pthread_timers, run_timer(), and timing_thread.

Referenced by init_timing_thread().

◆ init_timing_thread()

static int init_timing_thread ( void  )
static

Definition at line 423 of file res_timing_pthread.c.

424{
427
429 ast_log(LOG_ERROR, "Unable to start timing thread.\n");
430 return -1;
431 }
432
433 return 0;
434}
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
#define ast_cond_init(cond, attr)
Definition: lock.h:201
#define ast_mutex_init(pmutex)
Definition: lock.h:186
static void * do_timing(void *arg)
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:592

References ast_cond_init, ast_log, ast_mutex_init, ast_pthread_create_background, do_timing(), LOG_ERROR, NULL, and timing_thread.

Referenced by load_module().

◆ load_module()

static int load_module ( void  )
static

Definition at line 436 of file res_timing_pthread.c.

437{
440 if (!pthread_timers) {
442 }
443
444 if (init_timing_thread()) {
448 }
449
452}
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static int pthread_timer_hash(const void *obj, const int flags)
static int init_timing_thread(void)
#define PTHREAD_TIMER_BUCKETS
static void * timing_funcs_handle
static struct ast_timing_interface pthread_timing
static int pthread_timer_cmp(void *obj, void *arg, int flags)
#define ast_register_timing_interface(i)
Register a set of timing functions.
Definition: timing.h:95

References AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, ao2_ref, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_register_timing_interface, init_timing_thread(), NULL, PTHREAD_TIMER_BUCKETS, pthread_timer_cmp(), pthread_timer_hash(), pthread_timers, pthread_timing, and timing_funcs_handle.

◆ pthread_timer_ack()

static int pthread_timer_ack ( void *  data,
unsigned int  quantity 
)
static

Definition at line 180 of file res_timing_pthread.c.

181{
182 struct pthread_timer *timer = data;
183
184 ast_assert(quantity > 0);
185
187 ack_ticks(timer, quantity);
189
190 return 0;
191}
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
static void ack_ticks(struct pthread_timer *timer, unsigned int num)

References ack_ticks(), ao2_lock, ao2_unlock, ast_assert, and timer.

◆ pthread_timer_close()

static void pthread_timer_close ( void *  data)
static

Definition at line 143 of file res_timing_pthread.c.

144{
145 struct pthread_timer *timer = data;
146
148 ao2_ref(timer, -1);
149}
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578

References ao2_ref, ao2_unlink, pthread_timers, and timer.

◆ pthread_timer_cmp()

static int pthread_timer_cmp ( void *  obj,
void *  arg,
int  flags 
)
static
Note
only PIPE_READ is guaranteed valid

Definition at line 275 of file res_timing_pthread.c.

276{
277 struct pthread_timer *timer1 = obj, *timer2 = arg;
278
279 return (timer1->pipe[PIPE_READ] == timer2->pipe[PIPE_READ]) ? CMP_MATCH | CMP_STOP : 0;
280}
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028

References CMP_MATCH, CMP_STOP, pthread_timer::pipe, and PIPE_READ.

Referenced by load_module().

◆ pthread_timer_destructor()

static void pthread_timer_destructor ( void *  obj)
static

Definition at line 247 of file res_timing_pthread.c.

248{
249 struct pthread_timer *timer = obj;
250
251 if (timer->pipe[PIPE_READ] > -1) {
252 close(timer->pipe[PIPE_READ]);
253 timer->pipe[PIPE_READ] = -1;
254 }
255
256 if (timer->pipe[PIPE_WRITE] > -1) {
257 close(timer->pipe[PIPE_WRITE]);
258 timer->pipe[PIPE_WRITE] = -1;
259 }
260}

References PIPE_READ, PIPE_WRITE, and timer.

Referenced by pthread_timer_open().

◆ pthread_timer_disable_continuous()

static int pthread_timer_disable_continuous ( void *  data)
static

Definition at line 207 of file res_timing_pthread.c.

208{
209 struct pthread_timer *timer = data;
210
212 if (timer->continuous) {
213 timer->continuous = false;
215 }
217
218 return 0;
219}

References ao2_lock, ao2_unlock, timer, and unsignal_pipe().

◆ pthread_timer_enable_continuous()

static int pthread_timer_enable_continuous ( void *  data)
static

Definition at line 193 of file res_timing_pthread.c.

194{
195 struct pthread_timer *timer = data;
196
198 if (!timer->continuous) {
199 timer->continuous = true;
201 }
203
204 return 0;
205}
static void signal_pipe(struct pthread_timer *timer)

References ao2_lock, ao2_unlock, signal_pipe(), and timer.

◆ pthread_timer_fd()

static int pthread_timer_fd ( void *  data)
static

Definition at line 240 of file res_timing_pthread.c.

241{
242 struct pthread_timer *timer = data;
243
244 return timer->pipe[PIPE_READ];
245}

References PIPE_READ, and timer.

◆ pthread_timer_get_event()

static enum ast_timer_event pthread_timer_get_event ( void *  data)
static

Definition at line 221 of file res_timing_pthread.c.

222{
223 struct pthread_timer *timer = data;
225
227 if (timer->continuous) {
229 }
231
232 return res;
233}
ast_timer_event
Definition: timing.h:57
@ AST_TIMING_EVENT_CONTINUOUS
Definition: timing.h:59
@ AST_TIMING_EVENT_EXPIRED
Definition: timing.h:58

References ao2_lock, ao2_unlock, AST_TIMING_EVENT_CONTINUOUS, AST_TIMING_EVENT_EXPIRED, and timer.

◆ pthread_timer_get_max_rate()

static unsigned int pthread_timer_get_max_rate ( void *  data)
static

Definition at line 235 of file res_timing_pthread.c.

236{
237 return MAX_RATE;
238}
#define MAX_RATE

References MAX_RATE.

◆ pthread_timer_hash()

static int pthread_timer_hash ( const void *  obj,
const int  flags 
)
static
Note
only PIPE_READ is guaranteed valid

Definition at line 265 of file res_timing_pthread.c.

266{
267 const struct pthread_timer *timer = obj;
268
269 return timer->pipe[PIPE_READ];
270}

References PIPE_READ, and timer.

Referenced by load_module().

◆ pthread_timer_open()

static void * pthread_timer_open ( void  )
static

Definition at line 114 of file res_timing_pthread.c.

115{
116 struct pthread_timer *timer;
117
118 if (!(timer = ao2_alloc(sizeof(*timer), pthread_timer_destructor))) {
119 errno = ENOMEM;
120 return NULL;
121 }
122
123 timer->pipe[PIPE_READ] = timer->pipe[PIPE_WRITE] = -1;
124 timer->state = TIMER_STATE_IDLE;
125
126 if (ast_pipe_nonblock(timer->pipe)) {
127 ao2_ref(timer, -1);
128 return NULL;
129 }
130
136 }
139
140 return timer;
141}
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
Definition: astobj2.h:1554
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
#define ast_cond_signal(cond)
Definition: lock.h:203
int errno
static void pthread_timer_destructor(void *obj)
#define ast_pipe_nonblock(filedes)
Create a non-blocking pipe.
Definition: utils.h:1090

References ao2_alloc, ao2_container_count(), ao2_link_flags, ao2_lock, ao2_ref, ao2_unlock, ast_cond_signal, ast_mutex_lock, ast_mutex_unlock, ast_pipe_nonblock, errno, NULL, OBJ_NOLOCK, PIPE_READ, PIPE_WRITE, pthread_timer_destructor(), pthread_timers, timer, TIMER_STATE_IDLE, and timing_thread.

◆ pthread_timer_set_rate()

static int pthread_timer_set_rate ( void *  data,
unsigned int  rate 
)
static

Definition at line 151 of file res_timing_pthread.c.

152{
153 struct pthread_timer *timer = data;
154
155 if (rate > MAX_RATE) {
156 ast_log(LOG_ERROR, "res_timing_pthread only supports timers at a "
157 "max rate of %d / sec\n", MAX_RATE);
158 errno = EINVAL;
159 return -1;
160 }
161
163
164 if ((timer->rate = rate)) {
165 timer->interval = roundf(1000.0 / ((float) rate));
166 timer->start = ast_tvnow();
167 timer->state = TIMER_STATE_TICKING;
168 } else {
169 timer->interval = 0;
170 timer->start = ast_tv(0, 0);
171 timer->state = TIMER_STATE_IDLE;
172 }
173 timer->tick_count = 0;
174
176
177 return 0;
178}
float roundf(float x)
unsigned int rate

References ao2_lock, ao2_unlock, ast_log, ast_tv(), ast_tvnow(), errno, LOG_ERROR, MAX_RATE, pthread_timer::rate, roundf(), timer, TIMER_STATE_IDLE, and TIMER_STATE_TICKING.

◆ run_timer()

static int run_timer ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 377 of file res_timing_pthread.c.

378{
379 struct pthread_timer *timer = obj;
380
381 if (timer->state == TIMER_STATE_IDLE) {
382 return 0;
383 }
384
386 if (check_timer(timer)) {
387 timer->pending_ticks++;
389 }
391
392 return 0;
393}
static int check_timer(struct pthread_timer *timer)

References ao2_lock, ao2_unlock, check_timer(), signal_pipe(), timer, and TIMER_STATE_IDLE.

Referenced by do_timing().

◆ signal_pipe()

static void signal_pipe ( struct pthread_timer timer)
static

Definition at line 337 of file res_timing_pthread.c.

338{
339 ssize_t res;
340 unsigned char x = 42;
341
342 if (timer->pipe_signaled) {
343 return;
344 }
345
346 res = write(timer->pipe[PIPE_WRITE], &x, 1);
347 if (-1 == res) {
348 ast_log(LOG_ERROR, "Error writing to timing pipe: %s\n",
349 strerror(errno));
350 } else {
351 timer->pipe_signaled = true;
352 }
353}

References ast_log, errno, LOG_ERROR, PIPE_WRITE, and timer.

Referenced by pthread_timer_enable_continuous(), and run_timer().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 454 of file res_timing_pthread.c.

455{
456 int res;
457
459 timing_thread.stop = 1;
462 pthread_join(timing_thread.thread, NULL);
463
467 }
468
469 return res;
470}
int ast_unregister_timing_interface(void *handle)
Unregister a previously registered timing interface.
Definition: timing.c:104

References ao2_ref, ast_cond_signal, ast_mutex_lock, ast_mutex_unlock, ast_unregister_timing_interface(), NULL, pthread_timers, timing_funcs_handle, and timing_thread.

◆ unsignal_pipe()

static void unsignal_pipe ( struct pthread_timer timer)
static

Definition at line 359 of file res_timing_pthread.c.

360{
361 ssize_t res;
362 unsigned long buffer;
363
364 if (!timer->pipe_signaled) {
365 return;
366 }
367
368 res = read(timer->pipe[PIPE_READ], &buffer, sizeof(buffer));
369 if (-1 == res) {
370 ast_log(LOG_ERROR, "Error reading from pipe: %s\n",
371 strerror(errno));
372 } else {
373 timer->pipe_signaled = false;
374 }
375}

References ast_log, errno, LOG_ERROR, PIPE_READ, and timer.

Referenced by ack_ticks(), and pthread_timer_disable_continuous().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "pthread Timing Interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_TIMING, }
static

Definition at line 476 of file res_timing_pthread.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 476 of file res_timing_pthread.c.

◆ cond

ast_cond_t cond

Definition at line 110 of file res_timing_pthread.c.

◆ lock

Definition at line 109 of file res_timing_pthread.c.

◆ pthread_timers

struct ao2_container* pthread_timers
static

◆ pthread_timing

struct ast_timing_interface pthread_timing
static

Definition at line 56 of file res_timing_pthread.c.

Referenced by load_module().

◆ stop

unsigned int stop

Definition at line 111 of file res_timing_pthread.c.

◆ thread

pthread_t thread

Definition at line 108 of file res_timing_pthread.c.

◆ timing_funcs_handle

void* timing_funcs_handle
static

Definition at line 44 of file res_timing_pthread.c.

Referenced by load_module(), and unload_module().

◆ 

struct { ... } timing_thread

Data for the timing thread.

Referenced by do_timing(), init_timing_thread(), pthread_timer_open(), and unload_module().