~ubuntu-branches/ubuntu/saucy/libqb/saucy

« back to all changes in this revision

Viewing changes to .pc/aarch64_no_coarse_clock.patch/lib/util.c

  • Committer: Package Import Robot
  • Author(s): William Grant
  • Date: 2013-10-12 19:07:55 UTC
  • Revision ID: package-import@ubuntu.com-20131012190755-b0oabl3dix2m3hby
Tags: 0.16.0.real-1ubuntu2
debian/patches/aarch64_no_coarse_clock.patch: Avoid
CLOCK_REALTIME_COARSE on aarch64 due to a kernel bug.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2010 Red Hat, Inc.
 
3
 *
 
4
 * All rights reserved.
 
5
 *
 
6
 * Author: Angus Salkeld <asalkeld@redhat.com>
 
7
 *
 
8
 * libqb is free software: you can redistribute it and/or modify
 
9
 * it under the terms of the GNU Lesser General Public License as published by
 
10
 * the Free Software Foundation, either version 2.1 of the License, or
 
11
 * (at your option) any later version.
 
12
 *
 
13
 * libqb is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 * GNU Lesser General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU Lesser General Public License
 
19
 * along with libqb.  If not, see <http://www.gnu.org/licenses/>.
 
20
 */
 
21
#include "os_base.h"
 
22
 
 
23
#include "util_int.h"
 
24
#include <pthread.h>
 
25
#include <sys/stat.h>
 
26
#include <qb/qbdefs.h>
 
27
#include <qb/qbutil.h>
 
28
 
 
29
struct qb_thread_lock_s {
 
30
        qb_thread_lock_type_t type;
 
31
#ifdef HAVE_PTHREAD_SHARED_SPIN_LOCK
 
32
        pthread_spinlock_t spinlock;
 
33
#endif /* HAVE_PTHREAD_SHARED_SPIN_LOCK */
 
34
        pthread_mutex_t mutex;
 
35
};
 
36
 
 
37
qb_thread_lock_t *
 
38
qb_thread_lock_create(qb_thread_lock_type_t type)
 
39
{
 
40
        struct qb_thread_lock_s *tl = malloc(sizeof(struct qb_thread_lock_s));
 
41
        int32_t res;
 
42
 
 
43
        if (tl == NULL) {
 
44
                return NULL;
 
45
        }
 
46
#ifdef HAVE_PTHREAD_SHARED_SPIN_LOCK
 
47
        if (type == QB_THREAD_LOCK_SHORT) {
 
48
                tl->type = QB_THREAD_LOCK_SHORT;
 
49
                res = pthread_spin_init(&tl->spinlock, 1);
 
50
        } else
 
51
#endif /* HAVE_PTHREAD_SHARED_SPIN_LOCK */
 
52
        {
 
53
                tl->type = QB_THREAD_LOCK_LONG;
 
54
                res = pthread_mutex_init(&tl->mutex, NULL);
 
55
        }
 
56
        if (res == 0) {
 
57
                return tl;
 
58
        } else {
 
59
                free(tl);
 
60
                return NULL;
 
61
        }
 
62
}
 
63
 
 
64
int32_t
 
65
qb_thread_lock(qb_thread_lock_t * tl)
 
66
{
 
67
        int32_t res;
 
68
#ifdef HAVE_PTHREAD_SHARED_SPIN_LOCK
 
69
        if (tl->type == QB_THREAD_LOCK_SHORT) {
 
70
                res = -pthread_spin_lock(&tl->spinlock);
 
71
        } else
 
72
#endif /* HAVE_PTHREAD_SHARED_SPIN_LOCK */
 
73
        {
 
74
                res = -pthread_mutex_lock(&tl->mutex);
 
75
        }
 
76
        return res;
 
77
}
 
78
 
 
79
int32_t
 
80
qb_thread_unlock(qb_thread_lock_t * tl)
 
81
{
 
82
        int32_t res;
 
83
#ifdef HAVE_PTHREAD_SHARED_SPIN_LOCK
 
84
        if (tl->type == QB_THREAD_LOCK_SHORT) {
 
85
                res = -pthread_spin_unlock(&tl->spinlock);
 
86
        } else
 
87
#endif
 
88
        {
 
89
                res = -pthread_mutex_unlock(&tl->mutex);
 
90
        }
 
91
        return res;
 
92
}
 
93
 
 
94
int32_t
 
95
qb_thread_trylock(qb_thread_lock_t * tl)
 
96
{
 
97
        int32_t res;
 
98
#ifdef HAVE_PTHREAD_SHARED_SPIN_LOCK
 
99
        if (tl->type == QB_THREAD_LOCK_SHORT) {
 
100
                res = -pthread_spin_trylock(&tl->spinlock);
 
101
        } else
 
102
#endif
 
103
        {
 
104
                res = -pthread_mutex_trylock(&tl->mutex);
 
105
        }
 
106
        return res;
 
107
}
 
108
 
 
109
int32_t
 
110
qb_thread_lock_destroy(qb_thread_lock_t * tl)
 
111
{
 
112
        int32_t res;
 
113
#ifdef HAVE_PTHREAD_SHARED_SPIN_LOCK
 
114
        if (tl->type == QB_THREAD_LOCK_SHORT) {
 
115
                res = -pthread_spin_destroy(&tl->spinlock);
 
116
        } else
 
117
#endif
 
118
        {
 
119
                res = -pthread_mutex_destroy(&tl->mutex);
 
120
        }
 
121
        free(tl);
 
122
        return res;
 
123
}
 
124
 
 
125
void
 
126
qb_timespec_add_ms(struct timespec *ts, int32_t ms)
 
127
{
 
128
#ifndef S_SPLINT_S
 
129
        ts->tv_sec += ms / 1000;
 
130
        ts->tv_nsec += (ms % 1000) * QB_TIME_NS_IN_MSEC;
 
131
        if (ts->tv_nsec >= 1000000000L) {
 
132
                ts->tv_sec++;
 
133
                ts->tv_nsec = ts->tv_nsec - 1000000000L;
 
134
        }
 
135
#endif /* S_SPLINT_S */
 
136
}
 
137
 
 
138
#ifdef HAVE_MONOTONIC_CLOCK
 
139
uint64_t
 
140
qb_util_nano_current_get(void)
 
141
{
 
142
        uint64_t nano_monotonic;
 
143
        struct timespec ts;
 
144
 
 
145
        clock_gettime(CLOCK_MONOTONIC, &ts);
 
146
        nano_monotonic =
 
147
            (ts.tv_sec * QB_TIME_NS_IN_SEC) + (uint64_t) ts.tv_nsec;
 
148
        return (nano_monotonic);
 
149
}
 
150
 
 
151
uint64_t
 
152
qb_util_nano_from_epoch_get(void)
 
153
{
 
154
        uint64_t nano_monotonic;
 
155
        struct timespec ts;
 
156
#ifdef CLOCK_REALTIME_COARSE
 
157
        clock_gettime(CLOCK_REALTIME_COARSE, &ts);
 
158
#else
 
159
        clock_gettime(CLOCK_REALTIME, &ts);
 
160
#endif
 
161
        nano_monotonic =
 
162
            (ts.tv_sec * QB_TIME_NS_IN_SEC) + (uint64_t) ts.tv_nsec;
 
163
        return (nano_monotonic);
 
164
}
 
165
 
 
166
uint64_t
 
167
qb_util_nano_monotonic_hz(void)
 
168
{
 
169
        uint64_t nano_monotonic_hz;
 
170
        struct timespec ts;
 
171
 
 
172
        clock_getres(CLOCK_MONOTONIC, &ts);
 
173
 
 
174
        nano_monotonic_hz =
 
175
            QB_TIME_NS_IN_SEC / ((ts.tv_sec * QB_TIME_NS_IN_SEC) + ts.tv_nsec);
 
176
 
 
177
        return (nano_monotonic_hz);
 
178
}
 
179
 
 
180
void
 
181
qb_util_timespec_from_epoch_get(struct timespec *ts)
 
182
{
 
183
#ifdef CLOCK_REALTIME_COARSE
 
184
        clock_gettime(CLOCK_REALTIME_COARSE, ts);
 
185
#else
 
186
        clock_gettime(CLOCK_REALTIME, ts);
 
187
#endif
 
188
}
 
189
 
 
190
#else
 
191
uint64_t
 
192
qb_util_nano_current_get(void)
 
193
{
 
194
        return qb_util_nano_from_epoch_get();
 
195
}
 
196
 
 
197
uint64_t
 
198
qb_util_nano_monotonic_hz(void)
 
199
{
 
200
        return sysconf(_SC_CLK_TCK);
 
201
}
 
202
 
 
203
void
 
204
qb_util_timespec_from_epoch_get(struct timespec *ts)
 
205
{
 
206
        struct timeval time_from_epoch;
 
207
        gettimeofday(&time_from_epoch, 0);
 
208
 
 
209
#ifndef S_SPLINT_S
 
210
        ts->tv_sec = time_from_epoch.tv_sec;
 
211
        ts->tv_nsec = time_from_epoch.tv_usec * QB_TIME_NS_IN_USEC;
 
212
#endif /* S_SPLINT_S */
 
213
}
 
214
 
 
215
uint64_t
 
216
qb_util_nano_from_epoch_get(void)
 
217
{
 
218
        uint64_t nano_from_epoch;
 
219
        struct timeval time_from_epoch;
 
220
        gettimeofday(&time_from_epoch, 0);
 
221
 
 
222
        nano_from_epoch = ((time_from_epoch.tv_sec * QB_TIME_NS_IN_SEC) +
 
223
                           (time_from_epoch.tv_usec * QB_TIME_NS_IN_USEC));
 
224
 
 
225
        return (nano_from_epoch);
 
226
}
 
227
#endif /* HAVE_MONOTONIC_CLOCK */
 
228
 
 
229
struct qb_util_stopwatch {
 
230
        uint64_t started;
 
231
        uint64_t stopped;
 
232
        uint32_t split_options;
 
233
        uint32_t split_size;
 
234
        uint32_t split_entries;
 
235
        uint64_t *split_entry_list;
 
236
};
 
237
 
 
238
qb_util_stopwatch_t *
 
239
qb_util_stopwatch_create(void)
 
240
{
 
241
        struct qb_util_stopwatch *sw;
 
242
        sw = (struct qb_util_stopwatch *)calloc(1, sizeof(struct qb_util_stopwatch));
 
243
        return sw;
 
244
}
 
245
 
 
246
void
 
247
qb_util_stopwatch_free(qb_util_stopwatch_t * sw)
 
248
{
 
249
        free(sw->split_entry_list);
 
250
        free(sw);
 
251
}
 
252
 
 
253
void
 
254
qb_util_stopwatch_start(qb_util_stopwatch_t * sw)
 
255
{
 
256
        sw->started = qb_util_nano_current_get();
 
257
        sw->stopped = 0;
 
258
        sw->split_entries = 0;
 
259
}
 
260
 
 
261
void
 
262
qb_util_stopwatch_stop(qb_util_stopwatch_t * sw)
 
263
{
 
264
        sw->stopped = qb_util_nano_current_get();
 
265
}
 
266
 
 
267
uint64_t
 
268
qb_util_stopwatch_us_elapsed_get(qb_util_stopwatch_t * sw)
 
269
{
 
270
        if (sw->stopped == 0 || sw->started == 0) {
 
271
                return 0;
 
272
        }
 
273
        return ((sw->stopped - sw->started) / QB_TIME_NS_IN_USEC);
 
274
}
 
275
 
 
276
float
 
277
qb_util_stopwatch_sec_elapsed_get(qb_util_stopwatch_t * sw)
 
278
{
 
279
        uint64_t e6;
 
280
        if (sw->stopped == 0 || sw->started == 0) {
 
281
                return 0;
 
282
        }
 
283
        e6 = qb_util_stopwatch_us_elapsed_get(sw);
 
284
        return ((float)e6 / (float)QB_TIME_US_IN_SEC);
 
285
}
 
286
 
 
287
int32_t
 
288
qb_util_stopwatch_split_ctl(qb_util_stopwatch_t *sw,
 
289
        uint32_t max_splits, uint32_t options)
 
290
{
 
291
        sw->split_size = max_splits;
 
292
        sw->split_options = options;
 
293
        sw->split_entry_list = (uint64_t *)calloc(1, sizeof (uint64_t) * max_splits);
 
294
        if (sw->split_entry_list == NULL) {
 
295
                return -errno;
 
296
        }
 
297
        return 0;
 
298
}
 
299
 
 
300
uint64_t
 
301
qb_util_stopwatch_split(qb_util_stopwatch_t *sw)
 
302
{
 
303
        uint32_t new_entry_pos;
 
304
        uint64_t time_start;
 
305
        uint64_t time_end;
 
306
 
 
307
        if (sw->split_size == 0) {
 
308
                return 0;
 
309
        }
 
310
        if (!(sw->split_options & QB_UTIL_SW_OVERWRITE) &&
 
311
            sw->split_entries == sw->split_size) {
 
312
                return 0;
 
313
        }
 
314
        if (sw->started == 0) {
 
315
                qb_util_stopwatch_start(sw);
 
316
        }
 
317
        new_entry_pos = sw->split_entries % (sw->split_size);
 
318
        sw->split_entry_list[new_entry_pos] = qb_util_nano_current_get();
 
319
        sw->split_entries++;
 
320
 
 
321
        time_start = sw->split_entry_list[new_entry_pos];
 
322
        if (sw->split_entries == 1) {
 
323
                /* first entry */
 
324
                time_end = sw->started;
 
325
        } else if (new_entry_pos == 0) {
 
326
                /* wrap around */
 
327
                time_end = sw->split_entry_list[sw->split_size - 1];
 
328
        } else {
 
329
                time_end = sw->split_entry_list[(new_entry_pos - 1) % sw->split_size];
 
330
        }
 
331
        return (time_start - time_end) / QB_TIME_NS_IN_USEC;
 
332
}
 
333
 
 
334
uint32_t
 
335
qb_util_stopwatch_split_last(qb_util_stopwatch_t *sw)
 
336
{
 
337
        if (sw->split_entries) {
 
338
                return sw->split_entries - 1;
 
339
        }
 
340
        return sw->split_entries;
 
341
}
 
342
 
 
343
uint64_t
 
344
qb_util_stopwatch_time_split_get(qb_util_stopwatch_t *sw,
 
345
                                 uint32_t receint, uint32_t older)
 
346
{
 
347
        uint64_t time_start;
 
348
        uint64_t time_end;
 
349
 
 
350
        if (sw->started == 0 ||
 
351
            receint >= sw->split_entries ||
 
352
            older >= sw->split_entries ||
 
353
            receint < older) {
 
354
                return 0;
 
355
        }
 
356
        if (sw->split_options & QB_UTIL_SW_OVERWRITE &&
 
357
            (receint < (sw->split_entries - sw->split_size) ||
 
358
             older < (sw->split_entries - sw->split_size))) {
 
359
                return 0;
 
360
        }
 
361
 
 
362
        time_start = sw->split_entry_list[receint % (sw->split_size)];
 
363
        if (older == receint) {
 
364
                time_end = sw->started;
 
365
        } else {
 
366
                time_end = sw->split_entry_list[older % (sw->split_size)];
 
367
        }
 
368
        return (time_start - time_end) / QB_TIME_NS_IN_USEC;
 
369
}