Coverage Report

Created: 2025-08-08 07:04

/src/rtpproxy/external/libelperiodic/src/periodic.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2016-2018, sobomax
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * * Redistributions of source code must retain the above copyright notice, this
9
 *   list of conditions and the following disclaimer.
10
 *
11
 * * Redistributions in binary form must reproduce the above copyright notice,
12
 *   this list of conditions and the following disclaimer in the documentation
13
 *   and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
27
#include <sys/time.h>
28
#include <assert.h>
29
#include <math.h>
30
#include <signal.h>
31
#include <stdlib.h>
32
#include <string.h>
33
#include <time.h>
34
35
#include "elperiodic.h"
36
#include "prdic_math.h"
37
#include "prdic_timespecops.h"
38
#include "prdic_fd.h"
39
#include "prdic_pfd.h"
40
#include "prdic_main_fd.h"
41
#include "prdic_main_pfd.h"
42
#include "prdic_recfilter.h"
43
#include "prdic_types.h"
44
#include "prdic_procchain.h"
45
#include "prdic_shmtrig.h"
46
#include "prdic_band.h"
47
#include "prdic_inst.h"
48
#include "prdic_time.h"
49
#include "prdic_sign.h"
50
51
static void
52
band_init(struct prdic_band *bp, enum prdic_det_type dt,
53
  double freq_hz)
54
8
{
55
56
8
    bp->det_type = dt;
57
8
    bp->freq_hz = freq_hz;
58
8
    bp->period = 1.0 / freq_hz;
59
8
    dtime2timespec(bp->period, &bp->tperiod);
60
8
    dtime2timespec(freq_hz, &bp->tfreq_hz);
61
8
    _prdic_recfilter_init(&bp->loop_error, 0.96, 1.0);
62
8
    _prdic_shmtrig_init(&bp->le_shmtrig, 1, 0.3, 0.7);
63
8
    bp->loop_error.procchain[0] = &(bp->le_shmtrig.link);
64
8
    _prdic_recfilter_init(&bp->add_delay_fltrd, 0.96, 1.0);
65
8
    _prdic_recfilter_init(&bp->sysload_fltrd, 0.997, 0.0);
66
8
    switch (dt) {
67
8
    case PRDIC_DET_FREQ:
68
8
        _prdic_FD_init(&bp->detector.freq);
69
8
        break;
70
0
    case PRDIC_DET_PHASE:
71
0
        _prdic_PFD_init(&bp->detector.phase);
72
0
        break;
73
0
    default:
74
0
        abort();
75
8
    }
76
77
8
}
78
79
void *
80
prdic_init(double freq_hz, double off_from_now)
81
8
{
82
8
    struct prdic_inst *pip;
83
84
8
    pip = malloc(sizeof(struct prdic_inst));
85
8
    if (pip == NULL) {
86
0
        goto e0;
87
0
    }
88
8
    memset(pip, '\0', sizeof(struct prdic_inst));
89
8
    pip->root_band = malloc(sizeof(struct prdic_band));
90
8
    if (pip->root_band == NULL) {
91
0
        goto e1;
92
0
    }
93
8
    memset(pip->root_band, '\0', sizeof(struct prdic_band));
94
8
    pip->ab = pip->root_band;
95
8
    if (getttime(&pip->ab->epoch, 0) != 0) {
96
0
        goto e2;
97
0
    }
98
8
    tplusdtime(&pip->ab->epoch, off_from_now);
99
8
    band_init(pip->ab, PRDIC_DET_FREQ, freq_hz);
100
8
    return ((void *)pip);
101
0
e2:
102
0
    free(pip->root_band);
103
0
e1:
104
0
    free(pip);
105
0
e0:
106
0
    return (NULL);
107
0
}
108
109
int
110
prdic_CFT_enable(void *prdic_inst, int signum)
111
0
{
112
0
    struct prdic_inst *pip = (struct prdic_inst *)prdic_inst;
113
114
0
    assert(pip->sip == NULL);
115
0
    pip->sip = prdic_sign_setup(signum);
116
0
    if (pip->sip == NULL)
117
0
        return (-1);
118
0
    return (0);
119
0
}
120
121
int
122
prdic_addband(void *prdic_inst, double freq_hz)
123
0
{
124
0
    struct prdic_inst *pip;
125
0
    struct prdic_band *bp, *tbp;
126
0
    int i;
127
128
0
    pip = (struct prdic_inst *)prdic_inst;
129
130
0
    bp = malloc(sizeof(struct prdic_band));
131
0
    if (bp == NULL)
132
0
        return (-1);
133
0
    memset(bp, '\0', sizeof(struct prdic_band));
134
0
    bp->epoch = pip->root_band->epoch;
135
0
    band_init(bp, pip->root_band->det_type, freq_hz);
136
0
    for (tbp = pip->root_band; tbp->next != NULL; tbp = tbp->next)
137
0
        continue;
138
0
    bp->id = tbp->id + 1;
139
0
    assert(tbp->next == NULL);
140
0
    tbp->next = bp;
141
0
    return (bp->id);
142
0
}
143
144
static void
145
band_set_epoch(struct prdic_band *bp, struct timespec *epoch)
146
0
{
147
148
0
    bp->epoch = *epoch;
149
0
    switch (bp->det_type) {
150
0
    case PRDIC_DET_FREQ:
151
0
        _prdic_FD_reset(&bp->detector.freq);
152
0
        break;
153
0
    case PRDIC_DET_PHASE:
154
0
        _prdic_PFD_reset(&bp->detector.phase);
155
0
        break;
156
0
    default:
157
0
        abort();
158
0
    }
159
0
}
160
161
static struct prdic_band *
162
prdic_findband(struct prdic_inst *pip, int bnum)
163
0
{
164
0
    struct prdic_band *rbp;
165
166
0
    for (rbp = pip->root_band; rbp != NULL; rbp = rbp->next) {
167
0
        if (rbp->id == bnum)
168
0
            break;
169
0
    }
170
0
    return (rbp);
171
0
}
172
173
void
174
prdic_useband(void *prdic_inst, int bnum)
175
0
{
176
0
    struct prdic_inst *pip;
177
0
    struct prdic_band *bp, *tbp;
178
0
    int i;
179
0
    struct timespec nepoch, tepoch;
180
181
0
    pip = (struct prdic_inst *)prdic_inst;
182
183
0
    if (bnum == pip->ab->id)
184
0
        return;
185
186
0
    tbp = prdic_findband(pip, bnum);
187
0
    assert(tbp != NULL); /* prdic_useband() requested band is not found */
188
0
    SEC(&tepoch) = SEC(&pip->ab->last_tclk);
189
0
    NSEC(&tepoch) = 0;
190
0
    timespecmul(&nepoch, &tepoch, &pip->ab->tperiod);
191
0
    timespecadd(&nepoch, &pip->ab->epoch);
192
0
    band_set_epoch(tbp, &nepoch);
193
0
    pip->ab = tbp;
194
0
}
195
196
enum prdic_det_type
197
prdic_set_det_type(void *prdic_inst, int bnum, enum prdic_det_type ndt)
198
0
{
199
0
    struct prdic_inst *pip;
200
0
    enum prdic_det_type odt;
201
0
    struct prdic_band *bp;
202
203
0
    pip = (struct prdic_inst *)prdic_inst;
204
0
    bp = prdic_findband(pip, bnum);
205
0
    assert(bp != NULL);
206
207
0
    odt = bp->det_type;
208
0
    if (odt == ndt)
209
0
        goto done;
210
0
    switch (ndt) {
211
0
    case PRDIC_DET_FREQ:
212
0
        _prdic_FD_init(&bp->detector.freq);
213
0
        break;
214
0
    case PRDIC_DET_PHASE:
215
0
        _prdic_PFD_init(&bp->detector.phase);
216
0
        break;
217
0
    default:
218
0
        abort();
219
0
    }
220
0
    bp->det_type = ndt;
221
0
done:
222
0
    return (odt);
223
0
}
224
225
int
226
prdic_procrastinate(void *prdic_inst)
227
1.76k
{
228
1.76k
    struct prdic_inst *pip;
229
230
1.76k
    pip = (struct prdic_inst *)prdic_inst;
231
1.76k
    switch (pip->ab->det_type) {
232
1.76k
    case PRDIC_DET_FREQ:
233
1.76k
        return (_prdic_procrastinate_FD(pip));
234
0
    case PRDIC_DET_PHASE:
235
0
        return (_prdic_procrastinate_PFD(pip));
236
0
    default:
237
0
        abort();
238
1.76k
    }
239
1.76k
}
240
241
void
242
prdic_set_fparams(void *prdic_inst, double fcoef)
243
0
{
244
0
    struct prdic_inst *pip;
245
246
0
    pip = (struct prdic_inst *)prdic_inst;
247
0
    assert(pip->ab->loop_error.lastval == 1.0);
248
0
    _prdic_recfilter_adjust(&pip->ab->loop_error, fcoef);
249
0
}
250
251
void
252
prdic_set_epoch(void *prdic_inst, struct timespec *tp)
253
0
{
254
0
    struct prdic_inst *pip;
255
256
0
    pip = (struct prdic_inst *)prdic_inst;
257
0
    band_set_epoch(pip->ab, tp);
258
0
}
259
260
time_t
261
prdic_getncycles_ref(void *prdic_inst)
262
0
{
263
0
    struct prdic_inst *pip;
264
265
0
    pip = (struct prdic_inst *)prdic_inst;
266
0
    return (SEC(&pip->ab->last_tclk));
267
0
}
268
269
double
270
prdic_getload(void *prdic_inst)
271
0
{
272
0
    struct prdic_inst *pip;
273
274
0
    pip = (struct prdic_inst *)prdic_inst;
275
0
    return (pip->ab->sysload_fltrd.lastval);
276
0
}
277
278
int
279
prdic_islocked(void *prdic_inst)
280
0
{
281
0
    struct prdic_inst *pip;
282
283
0
    pip = (struct prdic_inst *)prdic_inst;
284
0
    return (pip->ab->le_shmtrig.currval == 0);
285
0
}
286
287
void
288
prdic_free(void *prdic_inst)
289
8
{
290
8
    struct prdic_inst *pip;
291
8
    struct prdic_band *tbp, *fbp;
292
293
8
    pip = (struct prdic_inst *)prdic_inst;
294
16
    for (tbp = pip->root_band; tbp != NULL;) {
295
8
        fbp = tbp;
296
8
        tbp = tbp->next;
297
8
        free(fbp);
298
8
    }
299
8
    if (pip->sip != NULL) {
300
0
        prdic_sign_dtor(pip->sip);
301
0
    }
302
8
    free(prdic_inst);
303
8
}