~james-page/ubuntu/saucy/openvswitch/1.12-snapshot

« back to all changes in this revision

Viewing changes to lib/timeval.c

  • Committer: James Page
  • Date: 2013-08-21 10:16:57 UTC
  • mfrom: (1.1.20)
  • Revision ID: james.page@canonical.com-20130821101657-3o0z0qeiv5zkwlzi
New upstream snapshot

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
#include "timeval.h"
19
19
#include <errno.h>
20
20
#include <poll.h>
 
21
#include <pthread.h>
21
22
#include <signal.h>
22
23
#include <stdlib.h>
23
24
#include <string.h>
30
31
#include "fatal-signal.h"
31
32
#include "hash.h"
32
33
#include "hmap.h"
 
34
#include "ovs-thread.h"
33
35
#include "signals.h"
34
36
#include "unixctl.h"
35
37
#include "util.h"
36
38
#include "vlog.h"
37
39
 
38
 
/* backtrace() from <execinfo.h> is really useful, but it is not signal safe
39
 
 * everywhere, such as on x86-64.  */
40
 
#if HAVE_EXECINFO_H && !defined __x86_64__
41
 
#  define USE_BACKTRACE 1
42
 
#  include <execinfo.h>
43
 
#else
44
 
#  define USE_BACKTRACE 0
45
 
#endif
46
 
 
47
40
VLOG_DEFINE_THIS_MODULE(timeval);
48
41
 
49
 
/* The clock to use for measuring time intervals.  This is CLOCK_MONOTONIC by
50
 
 * preference, but on systems that don't have a monotonic clock we fall back
51
 
 * to CLOCK_REALTIME. */
52
 
static clockid_t monotonic_clock;
53
 
 
54
 
/* Has a timer tick occurred? Only relevant if CACHE_TIME is true.
55
 
 *
56
 
 * We initialize these to true to force time_init() to get called on the first
57
 
 * call to time_msec() or another function that queries the current time. */
58
 
static volatile sig_atomic_t wall_tick = true;
59
 
static volatile sig_atomic_t monotonic_tick = true;
60
 
 
61
 
/* The current time, as of the last refresh. */
62
 
static struct timespec wall_time;
63
 
static struct timespec monotonic_time;
 
42
struct clock {
 
43
    clockid_t id;               /* CLOCK_MONOTONIC or CLOCK_REALTIME. */
 
44
    struct ovs_rwlock rwlock;   /* Mutual exclusion for 'cache'. */
 
45
 
 
46
    /* Features for use by unit tests.  Protected by 'rwlock'. */
 
47
    struct timespec warp;       /* Offset added for unit tests. */
 
48
    bool stopped;               /* Disables real-time updates if true.  */
 
49
 
 
50
    /* Relevant only if CACHE_TIME is true. */
 
51
    volatile sig_atomic_t tick; /* Has the timer ticked?  Set by signal. */
 
52
    struct timespec cache;      /* Last time read from kernel. */
 
53
};
 
54
 
 
55
/* Our clocks. */
 
56
static struct clock monotonic_clock; /* CLOCK_MONOTONIC, if available. */
 
57
static struct clock wall_clock;      /* CLOCK_REALTIME. */
64
58
 
65
59
/* The monotonic time at which the time module was initialized. */
66
60
static long long int boot_time;
67
61
 
68
 
/* features for use by unit tests. */
69
 
static struct timespec warp_offset; /* Offset added to monotonic_time. */
70
 
static bool time_stopped;           /* Disables real-time updates, if true. */
71
 
 
72
 
/* Time in milliseconds at which to die with SIGALRM (if not LLONG_MAX). */
 
62
/* Monotonic time in milliseconds at which to die with SIGALRM (if not
 
63
 * LLONG_MAX). */
73
64
static long long int deadline = LLONG_MAX;
74
65
 
75
 
struct trace {
76
 
    void *backtrace[32]; /* Populated by backtrace(). */
77
 
    size_t n_frames;     /* Number of frames in 'backtrace'. */
78
 
 
79
 
    /* format_backtraces() helper data. */
80
 
    struct hmap_node node;
81
 
    size_t count;
82
 
};
83
 
 
84
 
#define MAX_TRACES 50
85
 
static struct trace traces[MAX_TRACES];
86
 
static size_t trace_head = 0;
 
66
/* Monotonic time, in milliseconds, at which the last call to time_poll() woke
 
67
 * up. */
 
68
DEFINE_PER_THREAD_DATA(long long int, last_wakeup, 0);
87
69
 
88
70
static void set_up_timer(void);
89
71
static void set_up_signal(int flags);
90
72
static void sigalrm_handler(int);
91
 
static void refresh_wall_if_ticked(void);
92
 
static void refresh_monotonic_if_ticked(void);
93
73
static void block_sigalrm(sigset_t *);
94
74
static void unblock_sigalrm(const sigset_t *);
95
75
static void log_poll_interval(long long int last_wakeup);
97
77
static void refresh_rusage(void);
98
78
static void timespec_add(struct timespec *sum,
99
79
                         const struct timespec *a, const struct timespec *b);
100
 
static unixctl_cb_func backtrace_cb;
101
 
 
102
 
#if !USE_BACKTRACE
103
 
static int
104
 
backtrace(void **buffer OVS_UNUSED, int size OVS_UNUSED)
105
 
{
106
 
    NOT_REACHED();
107
 
}
108
 
 
109
 
static char **
110
 
backtrace_symbols(void *const *buffer OVS_UNUSED, int size OVS_UNUSED)
111
 
{
112
 
    NOT_REACHED();
113
 
}
114
 
#endif  /* !USE_BACKTRACE */
 
80
 
 
81
static void
 
82
init_clock(struct clock *c, clockid_t id)
 
83
{
 
84
    memset(c, 0, sizeof *c);
 
85
    c->id = id;
 
86
    ovs_rwlock_init(&c->rwlock);
 
87
    xclock_gettime(c->id, &c->cache);
 
88
}
 
89
 
 
90
static void
 
91
do_init_time(void)
 
92
{
 
93
    struct timespec ts;
 
94
 
 
95
    coverage_init();
 
96
 
 
97
    init_clock(&monotonic_clock, (!clock_gettime(CLOCK_MONOTONIC, &ts)
 
98
                                  ? CLOCK_MONOTONIC
 
99
                                  : CLOCK_REALTIME));
 
100
    init_clock(&wall_clock, CLOCK_REALTIME);
 
101
    boot_time = timespec_to_msec(&monotonic_clock.cache);
 
102
 
 
103
    set_up_signal(SA_RESTART);
 
104
    set_up_timer();
 
105
}
115
106
 
116
107
/* Initializes the timetracking module, if not already initialized. */
117
108
static void
118
109
time_init(void)
119
110
{
120
 
    static bool inited;
121
 
 
122
 
    if (inited) {
123
 
        return;
124
 
    }
125
 
    inited = true;
126
 
 
127
 
    /* The implementation of backtrace() in glibc does some one time
128
 
     * initialization which is not signal safe.  This can cause deadlocks if
129
 
     * run from the signal handler.  As a workaround, force the initialization
130
 
     * to happen here. */
131
 
    if (USE_BACKTRACE) {
132
 
        void *bt[1];
133
 
 
134
 
        backtrace(bt, ARRAY_SIZE(bt));
135
 
    }
136
 
 
137
 
    memset(traces, 0, sizeof traces);
138
 
 
139
 
    if (USE_BACKTRACE && CACHE_TIME) {
140
 
        unixctl_command_register("backtrace", "", 0, 0, backtrace_cb, NULL);
141
 
    }
142
 
 
143
 
    coverage_init();
144
 
 
145
 
    if (!clock_gettime(CLOCK_MONOTONIC, &monotonic_time)) {
146
 
        monotonic_clock = CLOCK_MONOTONIC;
147
 
    } else {
148
 
        monotonic_clock = CLOCK_REALTIME;
149
 
        VLOG_DBG("monotonic timer not available");
150
 
    }
151
 
 
152
 
    set_up_signal(SA_RESTART);
153
 
    set_up_timer();
154
 
 
155
 
    boot_time = time_msec();
 
111
    static pthread_once_t once = PTHREAD_ONCE_INIT;
 
112
    pthread_once(&once, do_init_time);
156
113
}
157
114
 
158
115
static void
167
124
    xsigaction(SIGALRM, &sa, NULL);
168
125
}
169
126
 
170
 
/* Remove SA_RESTART from the flags for SIGALRM, so that any system call that
171
 
 * is interrupted by the periodic timer interrupt will return EINTR instead of
172
 
 * continuing after the signal handler returns.
173
 
 *
174
 
 * time_disable_restart() and time_enable_restart() may be usefully wrapped
175
 
 * around function calls that might otherwise block forever unless interrupted
176
 
 * by a signal, e.g.:
177
 
 *
178
 
 *   time_disable_restart();
179
 
 *   fcntl(fd, F_SETLKW, &lock);
180
 
 *   time_enable_restart();
181
 
 */
182
 
void
183
 
time_disable_restart(void)
184
 
{
185
 
    time_init();
186
 
    set_up_signal(0);
187
 
}
188
 
 
189
 
/* Add SA_RESTART to the flags for SIGALRM, so that any system call that
190
 
 * is interrupted by the periodic timer interrupt will continue after the
191
 
 * signal handler returns instead of returning EINTR. */
192
 
void
193
 
time_enable_restart(void)
194
 
{
195
 
    time_init();
196
 
    set_up_signal(SA_RESTART);
197
 
}
198
 
 
199
127
static void
200
128
set_up_timer(void)
201
129
{
206
134
        return;
207
135
    }
208
136
 
209
 
    if (timer_create(monotonic_clock, NULL, &timer_id)) {
210
 
        VLOG_FATAL("timer_create failed (%s)", strerror(errno));
 
137
    if (timer_create(monotonic_clock.id, NULL, &timer_id)) {
 
138
        VLOG_FATAL("timer_create failed (%s)", ovs_strerror(errno));
211
139
    }
212
140
 
213
141
    itimer.it_interval.tv_sec = 0;
215
143
    itimer.it_value = itimer.it_interval;
216
144
 
217
145
    if (timer_settime(timer_id, 0, &itimer, NULL)) {
218
 
        VLOG_FATAL("timer_settime failed (%s)", strerror(errno));
 
146
        VLOG_FATAL("timer_settime failed (%s)", ovs_strerror(errno));
219
147
    }
220
148
}
221
149
 
227
155
void
228
156
time_postfork(void)
229
157
{
 
158
    assert_single_threaded();
230
159
    time_init();
231
160
    set_up_timer();
232
161
}
233
162
 
234
 
static void
235
 
refresh_wall(void)
236
 
{
237
 
    time_init();
238
 
    clock_gettime(CLOCK_REALTIME, &wall_time);
239
 
    wall_tick = false;
240
 
}
241
 
 
242
 
static void
243
 
refresh_monotonic(void)
244
 
{
245
 
    time_init();
246
 
 
247
 
    if (!time_stopped) {
248
 
        if (monotonic_clock == CLOCK_MONOTONIC) {
249
 
            clock_gettime(monotonic_clock, &monotonic_time);
250
 
        } else {
251
 
            refresh_wall_if_ticked();
252
 
            monotonic_time = wall_time;
253
 
        }
254
 
        timespec_add(&monotonic_time, &monotonic_time, &warp_offset);
255
 
 
256
 
        monotonic_tick = false;
257
 
    }
258
 
}
259
 
 
260
163
/* Forces a refresh of the current time from the kernel.  It is not usually
261
164
 * necessary to call this function, since the time will be refreshed
262
165
 * automatically at least every TIME_UPDATE_INTERVAL milliseconds.  If
265
168
void
266
169
time_refresh(void)
267
170
{
268
 
    wall_tick = monotonic_tick = true;
 
171
    monotonic_clock.tick = wall_clock.tick = true;
 
172
}
 
173
 
 
174
static void
 
175
time_timespec__(struct clock *c, struct timespec *ts)
 
176
{
 
177
    time_init();
 
178
    for (;;) {
 
179
        /* Use the cached time by preference, but fall through if there's been
 
180
         * a clock tick.  */
 
181
        ovs_rwlock_rdlock(&c->rwlock);
 
182
        if (c->stopped || !c->tick) {
 
183
            timespec_add(ts, &c->cache, &c->warp);
 
184
            ovs_rwlock_unlock(&c->rwlock);
 
185
            return;
 
186
        }
 
187
        ovs_rwlock_unlock(&c->rwlock);
 
188
 
 
189
        /* Refresh the cache. */
 
190
        ovs_rwlock_wrlock(&c->rwlock);
 
191
        if (c->tick) {
 
192
            c->tick = false;
 
193
            xclock_gettime(c->id, &c->cache);
 
194
        }
 
195
        ovs_rwlock_unlock(&c->rwlock);
 
196
    }
 
197
}
 
198
 
 
199
/* Stores a monotonic timer, accurate within TIME_UPDATE_INTERVAL ms, into
 
200
 * '*ts'. */
 
201
void
 
202
time_timespec(struct timespec *ts)
 
203
{
 
204
    time_timespec__(&monotonic_clock, ts);
 
205
}
 
206
 
 
207
/* Stores the current time, accurate within TIME_UPDATE_INTERVAL ms, into
 
208
 * '*ts'. */
 
209
void
 
210
time_wall_timespec(struct timespec *ts)
 
211
{
 
212
    time_timespec__(&wall_clock, ts);
 
213
}
 
214
 
 
215
static time_t
 
216
time_sec__(struct clock *c)
 
217
{
 
218
    struct timespec ts;
 
219
 
 
220
    time_timespec__(c, &ts);
 
221
    return ts.tv_sec;
269
222
}
270
223
 
271
224
/* Returns a monotonic timer, in seconds. */
272
225
time_t
273
226
time_now(void)
274
227
{
275
 
    refresh_monotonic_if_ticked();
276
 
    return monotonic_time.tv_sec;
 
228
    return time_sec__(&monotonic_clock);
277
229
}
278
230
 
279
231
/* Returns the current time, in seconds. */
280
232
time_t
281
233
time_wall(void)
282
234
{
283
 
    refresh_wall_if_ticked();
284
 
    return wall_time.tv_sec;
 
235
    return time_sec__(&wall_clock);
 
236
}
 
237
 
 
238
static long long int
 
239
time_msec__(struct clock *c)
 
240
{
 
241
    struct timespec ts;
 
242
 
 
243
    time_timespec__(c, &ts);
 
244
    return timespec_to_msec(&ts);
285
245
}
286
246
 
287
247
/* Returns a monotonic timer, in ms (within TIME_UPDATE_INTERVAL ms). */
288
248
long long int
289
249
time_msec(void)
290
250
{
291
 
    refresh_monotonic_if_ticked();
292
 
    return timespec_to_msec(&monotonic_time);
 
251
    return time_msec__(&monotonic_clock);
293
252
}
294
253
 
295
254
/* Returns the current time, in ms (within TIME_UPDATE_INTERVAL ms). */
296
255
long long int
297
256
time_wall_msec(void)
298
257
{
299
 
    refresh_wall_if_ticked();
300
 
    return timespec_to_msec(&wall_time);
301
 
}
302
 
 
303
 
/* Stores a monotonic timer, accurate within TIME_UPDATE_INTERVAL ms, into
304
 
 * '*ts'. */
305
 
void
306
 
time_timespec(struct timespec *ts)
307
 
{
308
 
    refresh_monotonic_if_ticked();
309
 
    *ts = monotonic_time;
310
 
}
311
 
 
312
 
/* Stores the current time, accurate within TIME_UPDATE_INTERVAL ms, into
313
 
 * '*ts'. */
314
 
void
315
 
time_wall_timespec(struct timespec *ts)
316
 
{
317
 
    refresh_wall_if_ticked();
318
 
    *ts = wall_time;
 
258
    return time_msec__(&wall_clock);
319
259
}
320
260
 
321
261
/* Configures the program to die with SIGALRM 'secs' seconds from now, if
326
266
    long long int now;
327
267
    long long int msecs;
328
268
 
329
 
    sigset_t oldsigs;
330
 
 
 
269
    assert_single_threaded();
331
270
    time_init();
332
271
    time_refresh();
333
272
 
334
273
    now = time_msec();
335
274
    msecs = secs * 1000LL;
336
 
 
337
 
    block_sigalrm(&oldsigs);
338
275
    deadline = now < LLONG_MAX - msecs ? now + msecs : LLONG_MAX;
339
 
    unblock_sigalrm(&oldsigs);
340
276
}
341
277
 
342
278
/* Like poll(), except:
357
293
time_poll(struct pollfd *pollfds, int n_pollfds, long long int timeout_when,
358
294
          int *elapsed)
359
295
{
360
 
    static long long int last_wakeup = 0;
 
296
    long long int *last_wakeup = last_wakeup_get();
361
297
    long long int start;
362
298
    sigset_t oldsigs;
363
299
    bool blocked;
364
300
    int retval;
365
301
 
 
302
    time_init();
366
303
    time_refresh();
367
 
    if (last_wakeup) {
368
 
        log_poll_interval(last_wakeup);
 
304
    if (*last_wakeup) {
 
305
        log_poll_interval(*last_wakeup);
369
306
    }
370
307
    coverage_clear();
371
308
    start = time_msec();
411
348
    if (blocked) {
412
349
        unblock_sigalrm(&oldsigs);
413
350
    }
414
 
    last_wakeup = time_msec();
 
351
    *last_wakeup = time_msec();
415
352
    refresh_rusage();
416
 
    *elapsed = last_wakeup - start;
 
353
    *elapsed = *last_wakeup - start;
417
354
    return retval;
418
355
}
419
356
 
420
357
static void
421
358
sigalrm_handler(int sig_nr OVS_UNUSED)
422
359
{
423
 
    wall_tick = true;
424
 
    monotonic_tick = true;
425
 
 
426
 
    if (USE_BACKTRACE && CACHE_TIME) {
427
 
        struct trace *trace = &traces[trace_head];
428
 
 
429
 
        trace->n_frames = backtrace(trace->backtrace,
430
 
                                    ARRAY_SIZE(trace->backtrace));
431
 
        trace_head = (trace_head + 1) % MAX_TRACES;
432
 
    }
433
 
}
434
 
 
435
 
static void
436
 
refresh_wall_if_ticked(void)
437
 
{
438
 
    if (!CACHE_TIME || wall_tick) {
439
 
        refresh_wall();
440
 
    }
441
 
}
442
 
 
443
 
static void
444
 
refresh_monotonic_if_ticked(void)
445
 
{
446
 
    if (!CACHE_TIME || monotonic_tick) {
447
 
        refresh_monotonic();
448
 
    }
 
360
    monotonic_clock.tick = wall_clock.tick = true;
449
361
}
450
362
 
451
363
static void
454
366
    sigset_t sigalrm;
455
367
    sigemptyset(&sigalrm);
456
368
    sigaddset(&sigalrm, SIGALRM);
457
 
    xsigprocmask(SIG_BLOCK, &sigalrm, oldsigs);
 
369
    xpthread_sigmask(SIG_BLOCK, &sigalrm, oldsigs);
458
370
}
459
371
 
460
372
static void
461
373
unblock_sigalrm(const sigset_t *oldsigs)
462
374
{
463
 
    xsigprocmask(SIG_SETMASK, oldsigs, NULL);
 
375
    xpthread_sigmask(SIG_SETMASK, oldsigs, NULL);
464
376
}
465
377
 
466
378
long long int
476
388
}
477
389
 
478
390
/* Returns the monotonic time at which the "time" module was initialized, in
479
 
 * milliseconds(). */
 
391
 * milliseconds. */
480
392
long long int
481
393
time_boot_msec(void)
482
394
{
488
400
xgettimeofday(struct timeval *tv)
489
401
{
490
402
    if (gettimeofday(tv, NULL) == -1) {
491
 
        VLOG_FATAL("gettimeofday failed (%s)", strerror(errno));
 
403
        VLOG_FATAL("gettimeofday failed (%s)", ovs_strerror(errno));
 
404
    }
 
405
}
 
406
 
 
407
void
 
408
xclock_gettime(clock_t id, struct timespec *ts)
 
409
{
 
410
    if (clock_gettime(id, ts) == -1) {
 
411
        /* It seems like a bad idea to try to use vlog here because it is
 
412
         * likely to try to check the current time. */
 
413
        ovs_abort(errno, "xclock_gettime() failed");
492
414
    }
493
415
}
494
416
 
520
442
{
521
443
    long long int interval = time_msec() - last_wakeup;
522
444
 
523
 
    if (interval >= 1000) {
 
445
    if (interval >= 1000
 
446
        && !monotonic_clock.warp.tv_sec
 
447
        && !monotonic_clock.warp.tv_nsec) {
524
448
        const struct rusage *last_rusage = get_recent_rusage();
525
449
        struct rusage rusage;
526
450
 
561
485
    unsigned long long int cpu; /* Total user+system CPU usage when sampled. */
562
486
};
563
487
 
564
 
static struct rusage recent_rusage;
565
 
static struct cpu_usage older = { LLONG_MIN, 0 };
566
 
static struct cpu_usage newer = { LLONG_MIN, 0 };
567
 
static int cpu_usage = -1;
 
488
struct cpu_tracker {
 
489
    struct cpu_usage older;
 
490
    struct cpu_usage newer;
 
491
    int cpu_usage;
 
492
 
 
493
    struct rusage recent_rusage;
 
494
};
 
495
DEFINE_PER_THREAD_MALLOCED_DATA(struct cpu_tracker *, cpu_tracker_var);
 
496
 
 
497
static struct cpu_tracker *
 
498
get_cpu_tracker(void)
 
499
{
 
500
    struct cpu_tracker *t = cpu_tracker_var_get();
 
501
    if (!t) {
 
502
        t = xzalloc(sizeof *t);
 
503
        t->older.when = LLONG_MIN;
 
504
        t->newer.when = LLONG_MIN;
 
505
        cpu_tracker_var_set_unsafe(t);
 
506
    }
 
507
    return t;
 
508
}
568
509
 
569
510
static struct rusage *
570
511
get_recent_rusage(void)
571
512
{
572
 
    return &recent_rusage;
 
513
    return &get_cpu_tracker()->recent_rusage;
 
514
}
 
515
 
 
516
static int
 
517
getrusage_thread(struct rusage *rusage OVS_UNUSED)
 
518
{
 
519
#ifdef RUSAGE_THREAD
 
520
    return getrusage(RUSAGE_THREAD, rusage);
 
521
#else
 
522
    errno = EINVAL;
 
523
    return -1;
 
524
#endif
573
525
}
574
526
 
575
527
static void
576
528
refresh_rusage(void)
577
529
{
578
 
    long long int now;
579
 
 
580
 
    now = time_msec();
581
 
    getrusage(RUSAGE_SELF, &recent_rusage);
582
 
 
583
 
    if (now >= newer.when + 3 * 1000) {
584
 
        older = newer;
585
 
        newer.when = now;
586
 
        newer.cpu = (timeval_to_msec(&recent_rusage.ru_utime) +
587
 
                     timeval_to_msec(&recent_rusage.ru_stime));
588
 
 
589
 
        if (older.when != LLONG_MIN && newer.cpu > older.cpu) {
590
 
            unsigned int dividend = newer.cpu - older.cpu;
591
 
            unsigned int divisor = (newer.when - older.when) / 100;
592
 
            cpu_usage = divisor > 0 ? dividend / divisor : -1;
593
 
        } else {
594
 
            cpu_usage = -1;
 
530
    struct cpu_tracker *t = get_cpu_tracker();
 
531
    struct rusage *recent_rusage = &t->recent_rusage;
 
532
 
 
533
    if (!getrusage_thread(recent_rusage)) {
 
534
        long long int now = time_msec();
 
535
        if (now >= t->newer.when + 3 * 1000) {
 
536
            t->older = t->newer;
 
537
            t->newer.when = now;
 
538
            t->newer.cpu = (timeval_to_msec(&recent_rusage->ru_utime) +
 
539
                            timeval_to_msec(&recent_rusage->ru_stime));
 
540
 
 
541
            if (t->older.when != LLONG_MIN && t->newer.cpu > t->older.cpu) {
 
542
                unsigned int dividend = t->newer.cpu - t->older.cpu;
 
543
                unsigned int divisor = (t->newer.when - t->older.when) / 100;
 
544
                t->cpu_usage = divisor > 0 ? dividend / divisor : -1;
 
545
            } else {
 
546
                t->cpu_usage = -1;
 
547
            }
595
548
        }
596
549
    }
597
550
}
603
556
int
604
557
get_cpu_usage(void)
605
558
{
606
 
    return cpu_usage;
607
 
}
608
 
 
609
 
static uint32_t
610
 
hash_trace(struct trace *trace)
611
 
{
612
 
    return hash_bytes(trace->backtrace,
613
 
                      trace->n_frames * sizeof *trace->backtrace, 0);
614
 
}
615
 
 
616
 
static struct trace *
617
 
trace_map_lookup(struct hmap *trace_map, struct trace *key)
618
 
{
619
 
    struct trace *value;
620
 
 
621
 
    HMAP_FOR_EACH_WITH_HASH (value, node, hash_trace(key), trace_map) {
622
 
        if (key->n_frames == value->n_frames
623
 
            && !memcmp(key->backtrace, value->backtrace,
624
 
                       key->n_frames * sizeof *key->backtrace)) {
625
 
            return value;
626
 
        }
627
 
    }
628
 
    return NULL;
629
 
}
630
 
 
631
 
/*  Appends a string to 'ds' representing backtraces recorded at regular
632
 
 *  intervals in the recent past.  This information can be used to get a sense
633
 
 *  of what the process has been spending the majority of time doing.  Will
634
 
 *  ommit any backtraces which have not occurred at least 'min_count' times. */
635
 
void
636
 
format_backtraces(struct ds *ds, size_t min_count)
637
 
{
638
 
    time_init();
639
 
 
640
 
    if (USE_BACKTRACE && CACHE_TIME) {
641
 
        struct hmap trace_map = HMAP_INITIALIZER(&trace_map);
642
 
        struct trace *trace, *next;
643
 
        sigset_t oldsigs;
644
 
        size_t i;
645
 
 
646
 
        block_sigalrm(&oldsigs);
647
 
 
648
 
        for (i = 0; i < MAX_TRACES; i++) {
649
 
            struct trace *trace = &traces[i];
650
 
            struct trace *map_trace;
651
 
 
652
 
            if (!trace->n_frames) {
653
 
                continue;
654
 
            }
655
 
 
656
 
            map_trace = trace_map_lookup(&trace_map, trace);
657
 
            if (map_trace) {
658
 
                map_trace->count++;
659
 
            } else {
660
 
                hmap_insert(&trace_map, &trace->node, hash_trace(trace));
661
 
                trace->count = 1;
662
 
            }
663
 
        }
664
 
 
665
 
        HMAP_FOR_EACH_SAFE (trace, next, node, &trace_map) {
666
 
            char **frame_strs;
667
 
            size_t j;
668
 
 
669
 
            hmap_remove(&trace_map, &trace->node);
670
 
 
671
 
            if (trace->count < min_count) {
672
 
                continue;
673
 
            }
674
 
 
675
 
            frame_strs = backtrace_symbols(trace->backtrace, trace->n_frames);
676
 
 
677
 
            ds_put_format(ds, "Count %zu\n", trace->count);
678
 
            for (j = 0; j < trace->n_frames; j++) {
679
 
                ds_put_format(ds, "%s\n", frame_strs[j]);
680
 
            }
681
 
            ds_put_cstr(ds, "\n");
682
 
 
683
 
            free(frame_strs);
684
 
        }
685
 
        hmap_destroy(&trace_map);
686
 
 
687
 
        ds_chomp(ds, '\n');
688
 
        unblock_sigalrm(&oldsigs);
689
 
    }
 
559
    return get_cpu_tracker()->cpu_usage;
690
560
}
691
561
 
692
562
/* Unixctl interface. */
698
568
                 int argc OVS_UNUSED, const char *argv[] OVS_UNUSED,
699
569
                 void *aux OVS_UNUSED)
700
570
{
701
 
    time_stopped = true;
 
571
    ovs_rwlock_wrlock(&monotonic_clock.rwlock);
 
572
    monotonic_clock.stopped = true;
 
573
    ovs_rwlock_unlock(&monotonic_clock.rwlock);
 
574
 
702
575
    unixctl_command_reply(conn, NULL);
703
576
}
704
577
 
722
595
 
723
596
    ts.tv_sec = msecs / 1000;
724
597
    ts.tv_nsec = (msecs % 1000) * 1000 * 1000;
725
 
    timespec_add(&warp_offset, &warp_offset, &ts);
726
 
    timespec_add(&monotonic_time, &monotonic_time, &ts);
 
598
 
 
599
    ovs_rwlock_wrlock(&monotonic_clock.rwlock);
 
600
    timespec_add(&monotonic_clock.warp, &monotonic_clock.warp, &ts);
 
601
    ovs_rwlock_unlock(&monotonic_clock.rwlock);
 
602
 
727
603
    unixctl_command_reply(conn, "warped");
728
604
}
729
605
 
730
 
static void
731
 
backtrace_cb(struct unixctl_conn *conn,
732
 
             int argc OVS_UNUSED, const char *argv[] OVS_UNUSED,
733
 
             void *aux OVS_UNUSED)
734
 
{
735
 
    struct ds ds = DS_EMPTY_INITIALIZER;
736
 
 
737
 
    ovs_assert(USE_BACKTRACE && CACHE_TIME);
738
 
    format_backtraces(&ds, 0);
739
 
    unixctl_command_reply(conn, ds_cstr(&ds));
740
 
    ds_destroy(&ds);
741
 
}
742
 
 
743
606
void
744
607
timeval_dummy_register(void)
745
608
{