Skip to content

Commit dfbe09b

Browse files
authored
Migrate vmm_callout -> OSX libdispatch (#112)
* Migrate vmm_callout to libdispatch * Some cleanup in dispatch code * Callout precision with libdispatch code * Make callout_drain cleanup correctly dispatch_sources * use dispatch_groups instead of busy-waiting for completion * Place dispatch_group_leave after c->queued=0 to prevent possible concurrency bug. The bug may occur in callout_stop_safe when queued is still not 0 and we call dispatch_suspend on a released object, can happen only during draining.
1 parent 0d6ab42 commit dfbe09b

File tree

4 files changed

+99
-265
lines changed

4 files changed

+99
-265
lines changed

include/xhyve/vmm/vmm_callout.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#pragma once
22

33
#include <stdint.h>
4-
#include <pthread.h>
54
#include <time.h>
65
#include <sys/time.h>
6+
#include <dispatch/dispatch.h>
77

88
#define SBT_1S ((sbintime_t)1 << 32)
99
#define SBT_1M (SBT_1S * 60)
@@ -70,6 +70,7 @@ static inline void bintime_sub(struct bintime *_bt, const struct bintime *_bt2)
7070
((a)->frac cmp (b)->frac) : \
7171
((a)->sec cmp (b)->sec))
7272

73+
extern int tc_precexp;
7374

7475
void binuptime(struct bintime *bt);
7576
void getmicrotime(struct timeval *tv);
@@ -82,10 +83,10 @@ static inline sbintime_t sbinuptime(void) {
8283
}
8384

8485
struct callout {
85-
pthread_cond_t wait;
86-
struct callout *prev;
87-
struct callout *next;
86+
dispatch_group_t group;
87+
dispatch_source_t timer;
8888
uint64_t timeout;
89+
uint64_t precision;
8990
void *argument;
9091
void (*callout)(void *);
9192
int flags;
@@ -95,7 +96,6 @@ struct callout {
9596
#define C_ABSOLUTE 0x0200 /* event time is absolute */
9697
#define CALLOUT_ACTIVE 0x0002 /* callout is currently active */
9798
#define CALLOUT_PENDING 0x0004 /* callout is waiting for timeout */
98-
#define CALLOUT_MPSAFE 0x0008 /* callout handler is mp safe */
9999
#define CALLOUT_RETURNUNLOCKED 0x0010 /* handler returns with mtx unlocked */
100100
#define CALLOUT_COMPLETED 0x0020 /* callout thread finished */
101101
#define CALLOUT_WAITING 0x0040 /* thread waiting for callout to finish */

src/vmm/io/vatpit.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,12 @@ static void
155155
pit_timer_start_cntr0(struct vatpit *vatpit)
156156
{
157157
struct channel *c;
158-
sbintime_t now, delta;
158+
sbintime_t now, delta, precision;
159159

160160
c = &vatpit->channel[0];
161161
if (c->initial != 0) {
162162
delta = c->initial * vatpit->freq_sbt;
163+
precision = delta >> tc_precexp;
163164
c->callout_sbt = c->callout_sbt + delta;
164165

165166
/*
@@ -172,7 +173,7 @@ pit_timer_start_cntr0(struct vatpit *vatpit)
172173
c->callout_sbt = now + delta;
173174

174175
callout_reset_sbt(&c->callout, c->callout_sbt,
175-
0, vatpit_callout_handler, &c->callout_arg,
176+
precision, vatpit_callout_handler, &c->callout_arg,
176177
C_ABSOLUTE);
177178
}
178179
}
@@ -429,7 +430,7 @@ vatpit_init(struct vm *vm)
429430
vatpit->freq_sbt = bttosbt(bt);
430431

431432
for (i = 0; i < 3; i++) {
432-
callout_init(&vatpit->channel[i].callout, true);
433+
callout_init(&vatpit->channel[i].callout, 1);
433434
arg = &vatpit->channel[i].callout_arg;
434435
arg->vatpit = vatpit;
435436
arg->channel_num = i;

src/vmm/io/vhpet.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ vhpet_stop_timer(struct vhpet *vhpet, int n, sbintime_t now)
325325
static void
326326
vhpet_start_timer(struct vhpet *vhpet, int n, uint32_t counter, sbintime_t now)
327327
{
328-
sbintime_t delta;
328+
sbintime_t delta, precision;
329329

330330
if (vhpet->timer[n].comprate != 0)
331331
vhpet_adjust_compval(vhpet, n, counter);
@@ -339,9 +339,10 @@ vhpet_start_timer(struct vhpet *vhpet, int n, uint32_t counter, sbintime_t now)
339339
}
340340

341341
delta = (vhpet->timer[n].compval - counter) * vhpet->freq_sbt;
342+
precision = delta >> tc_precexp;
342343
vhpet->timer[n].callout_sbt = now + delta;
343344
callout_reset_sbt(&vhpet->timer[n].callout, vhpet->timer[n].callout_sbt,
344-
0, vhpet_handler, &vhpet->timer[n].arg, C_ABSOLUTE);
345+
precision, vhpet_handler, &vhpet->timer[n].arg, C_ABSOLUTE);
345346
}
346347

347348
static void

0 commit comments

Comments
 (0)