]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: LGPL-2.1-or-later |
74971473 JG |
2 | /* |
3 | * This file is part of the PCEPlib, a PCEP protocol library. | |
4 | * | |
5 | * Copyright (C) 2020 Volta Networks https://voltanet.io/ | |
6 | * | |
74971473 JG |
7 | * Author : Brady Johnson <brady@voltanet.io> |
8 | * | |
9 | */ | |
10 | ||
11 | ||
1f8031f7 DL |
12 | #ifdef HAVE_CONFIG_H |
13 | #include "config.h" | |
14 | #endif | |
15 | ||
74971473 JG |
16 | #include <errno.h> |
17 | #include <stddef.h> | |
18 | #include <stdbool.h> | |
19 | #include <stdio.h> | |
20 | #include <sys/select.h> | |
21 | ||
22 | #include "pcep_timers_event_loop.h" | |
23 | #include "pcep_timer_internals.h" | |
24 | #include "pcep_utils_ordered_list.h" | |
25 | #include "pcep_utils_logging.h" | |
26 | #include "pcep_utils_memory.h" | |
27 | ||
28 | /* For each expired timer: remove the timer from the list, call the | |
29 | * expire_handler, and free the timer. */ | |
30 | void walk_and_process_timers(pcep_timers_context *timers_context) | |
31 | { | |
32 | pthread_mutex_lock(&timers_context->timer_list_lock); | |
33 | ||
34 | bool keep_walking = true; | |
35 | ordered_list_node *timer_node = timers_context->timer_list->head; | |
36 | time_t now = time(NULL); | |
37 | pcep_timer *timer_data; | |
38 | ||
39 | /* the timers are sorted by expire_time, so we will only | |
40 | * remove the top node each time through the loop */ | |
41 | while (timer_node != NULL && keep_walking) { | |
42 | timer_data = (pcep_timer *)timer_node->data; | |
43 | if (timer_data->expire_time <= now) { | |
44 | timer_node = timer_node->next_node; | |
45 | ordered_list_remove_first_node( | |
46 | timers_context->timer_list); | |
47 | /* call the timer expired handler */ | |
48 | timers_context->expire_handler(timer_data->data, | |
49 | timer_data->timer_id); | |
50 | pceplib_free(PCEPLIB_INFRA, timer_data); | |
51 | } else { | |
52 | keep_walking = false; | |
53 | } | |
54 | } | |
55 | ||
56 | pthread_mutex_unlock(&timers_context->timer_list_lock); | |
57 | } | |
58 | ||
59 | ||
60 | /* pcep_timers::initialize() will create a thread and invoke this method */ | |
61 | void *event_loop(void *context) | |
62 | { | |
63 | if (context == NULL) { | |
64 | pcep_log( | |
65 | LOG_WARNING, | |
66 | "%s: pcep_timers_event_loop cannot start event_loop with NULL data", | |
67 | __func__); | |
68 | return NULL; | |
69 | } | |
70 | ||
71 | pcep_log(LOG_NOTICE, "%s: [%ld-%ld] Starting timers_event_loop thread", | |
72 | __func__, time(NULL), pthread_self()); | |
73 | ||
74 | pcep_timers_context *timers_context = (pcep_timers_context *)context; | |
75 | struct timeval timer; | |
76 | int retval; | |
77 | ||
78 | while (timers_context->active) { | |
79 | /* check the timers every half second */ | |
80 | timer.tv_sec = 0; | |
81 | timer.tv_usec = 500000; | |
82 | ||
83 | do { | |
84 | /* if the select() call gets interrupted, select() will | |
85 | * set the remaining time in timer, so we need to call | |
86 | * it again. | |
87 | */ | |
88 | retval = select(0, NULL, NULL, NULL, &timer); | |
89 | } while (retval != 0 && errno == EINTR); | |
90 | ||
91 | walk_and_process_timers(timers_context); | |
92 | } | |
93 | ||
94 | pcep_log(LOG_WARNING, "%s: [%ld-%ld] Finished timers_event_loop thread", | |
95 | __func__, time(NULL), pthread_self()); | |
96 | ||
97 | return NULL; | |
98 | } |