Revision c8994013 vl.c

b/vl.c
781 781
    struct QEMUTimer *next;
782 782
};
783 783

  
784
QEMUClock *rt_clock;
785
QEMUClock *vm_clock;
784
struct qemu_alarm_timer {
785
    char const *name;
786

  
787
    int (*start)(struct qemu_alarm_timer *t);
788
    void (*stop)(struct qemu_alarm_timer *t);
789
    void *priv;
790
};
791

  
792
static struct qemu_alarm_timer *alarm_timer;
786 793

  
787
static QEMUTimer *active_timers[2];
788 794
#ifdef _WIN32
789
static MMRESULT timerID;
790
static HANDLE host_alarm = NULL;
791
static unsigned int period = 1;
795

  
796
struct qemu_alarm_win32 {
797
    MMRESULT timerId;
798
    HANDLE host_alarm;
799
    unsigned int period;
800
} alarm_win32_data = {0, NULL, -1};
801

  
802
static int win32_start_timer(struct qemu_alarm_timer *t);
803
static void win32_stop_timer(struct qemu_alarm_timer *t);
804

  
792 805
#else
793
/* frequency of the times() clock tick */
794
static int timer_freq;
806

  
807
static int unix_start_timer(struct qemu_alarm_timer *t);
808
static void unix_stop_timer(struct qemu_alarm_timer *t);
809

  
810
#ifdef __linux__
811

  
812
static int rtc_start_timer(struct qemu_alarm_timer *t);
813
static void rtc_stop_timer(struct qemu_alarm_timer *t);
814

  
795 815
#endif
796 816

  
817
#endif /* _WIN32 */
818

  
819
static struct qemu_alarm_timer alarm_timers[] = {
820
#ifdef __linux__
821
    /* RTC - if available - is preferred */
822
    {"rtc", rtc_start_timer, rtc_stop_timer, NULL},
823
#endif
824
#ifndef _WIN32
825
    {"unix", unix_start_timer, unix_stop_timer, NULL},
826
#else
827
    {"win32", win32_start_timer, win32_stop_timer, &alarm_win32_data},
828
#endif
829
    {NULL, }
830
};
831

  
832
QEMUClock *rt_clock;
833
QEMUClock *vm_clock;
834

  
835
static QEMUTimer *active_timers[2];
836

  
797 837
QEMUClock *qemu_new_clock(int type)
798 838
{
799 839
    QEMUClock *clock;
......
1009 1049
        qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME],
1010 1050
                           qemu_get_clock(rt_clock))) {
1011 1051
#ifdef _WIN32
1012
        SetEvent(host_alarm);
1052
        struct qemu_alarm_win32 *data = ((struct qemu_alarm_timer*)dwUser)->priv;
1053
        SetEvent(data->host_alarm);
1013 1054
#endif
1014 1055
        CPUState *env = cpu_single_env;
1015 1056
        if (env) {
......
1030 1071

  
1031 1072
#define RTC_FREQ 1024
1032 1073

  
1033
static int rtc_fd;
1074
static void enable_sigio_timer(int fd)
1075
{
1076
    struct sigaction act;
1034 1077

  
1035
static int start_rtc_timer(void)
1078
    /* timer signal */
1079
    sigfillset(&act.sa_mask);
1080
    act.sa_flags = 0;
1081
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
1082
    act.sa_flags |= SA_ONSTACK;
1083
#endif
1084
    act.sa_handler = host_alarm_handler;
1085

  
1086
    sigaction(SIGIO, &act, NULL);
1087
    fcntl(fd, F_SETFL, O_ASYNC);
1088
    fcntl(fd, F_SETOWN, getpid());
1089
}
1090

  
1091
static int rtc_start_timer(struct qemu_alarm_timer *t)
1036 1092
{
1093
    int rtc_fd;
1094

  
1037 1095
    TFR(rtc_fd = open("/dev/rtc", O_RDONLY));
1038 1096
    if (rtc_fd < 0)
1039 1097
        return -1;
......
1048 1106
        close(rtc_fd);
1049 1107
        return -1;
1050 1108
    }
1051
    pit_min_timer_count = PIT_FREQ / RTC_FREQ;
1109

  
1110
    enable_sigio_timer(rtc_fd);
1111

  
1112
    t->priv = (void *)rtc_fd;
1113

  
1052 1114
    return 0;
1053 1115
}
1054 1116

  
1055
#else
1056

  
1057
static int start_rtc_timer(void)
1117
static void rtc_stop_timer(struct qemu_alarm_timer *t)
1058 1118
{
1059
    return -1;
1119
    int rtc_fd = (int)t->priv;
1120

  
1121
    close(rtc_fd);
1060 1122
}
1061 1123

  
1062 1124
#endif /* !defined(__linux__) */
1063 1125

  
1064
#endif /* !defined(_WIN32) */
1126
static int unix_start_timer(struct qemu_alarm_timer *t)
1127
{
1128
    struct sigaction act;
1129
    struct itimerval itv;
1130
    int err;
1065 1131

  
1066
static void init_timer_alarm(void)
1132
    /* timer signal */
1133
    sigfillset(&act.sa_mask);
1134
    act.sa_flags = 0;
1135
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
1136
    act.sa_flags |= SA_ONSTACK;
1137
#endif
1138
    act.sa_handler = host_alarm_handler;
1139

  
1140
    sigaction(SIGALRM, &act, NULL);
1141

  
1142
    itv.it_interval.tv_sec = 0;
1143
    /* for i386 kernel 2.6 to get 1 ms */
1144
    itv.it_interval.tv_usec = 999;
1145
    itv.it_value.tv_sec = 0;
1146
    itv.it_value.tv_usec = 10 * 1000;
1147

  
1148
    err = setitimer(ITIMER_REAL, &itv, NULL);
1149
    if (err)
1150
        return -1;
1151

  
1152
    return 0;
1153
}
1154

  
1155
static void unix_stop_timer(struct qemu_alarm_timer *t)
1067 1156
{
1157
    struct itimerval itv;
1158

  
1159
    memset(&itv, 0, sizeof(itv));
1160
    setitimer(ITIMER_REAL, &itv, NULL);
1161
}
1162

  
1163
#endif /* !defined(_WIN32) */
1164

  
1068 1165
#ifdef _WIN32
1069
    {
1070
        int count=0;
1071
        TIMECAPS tc;
1072

  
1073
        ZeroMemory(&tc, sizeof(TIMECAPS));
1074
        timeGetDevCaps(&tc, sizeof(TIMECAPS));
1075
        if (period < tc.wPeriodMin)
1076
            period = tc.wPeriodMin;
1077
        timeBeginPeriod(period);
1078
        timerID = timeSetEvent(1,     // interval (ms)
1079
                               period,     // resolution
1080
                               host_alarm_handler, // function
1081
                               (DWORD)&count,  // user parameter
1082
                               TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1083
 	if( !timerID ) {
1084
            perror("failed timer alarm");
1085
            exit(1);
1086
 	}
1087
        host_alarm = CreateEvent(NULL, FALSE, FALSE, NULL);
1088
        if (!host_alarm) {
1089
            perror("failed CreateEvent");
1090
            exit(1);
1091
        }
1092
        qemu_add_wait_object(host_alarm, NULL, NULL);
1166

  
1167
static int win32_start_timer(struct qemu_alarm_timer *t)
1168
{
1169
    TIMECAPS tc;
1170
    struct qemu_alarm_win32 *data = t->priv;
1171

  
1172
    data->host_alarm = CreateEvent(NULL, FALSE, FALSE, NULL);
1173
    if (!data->host_alarm) {
1174
        perror("Failed CreateEvent");
1175
        return -1
1093 1176
    }
1094
    pit_min_timer_count = ((uint64_t)10000 * PIT_FREQ) / 1000000;
1095
#else
1096
    {
1097
        struct sigaction act;
1098
        struct itimerval itv;
1099
        
1100
        /* get times() syscall frequency */
1101
        timer_freq = sysconf(_SC_CLK_TCK);
1102
        
1103
        /* timer signal */
1104
        sigfillset(&act.sa_mask);
1105
       act.sa_flags = 0;
1106
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
1107
        act.sa_flags |= SA_ONSTACK;
1108
#endif
1109
        act.sa_handler = host_alarm_handler;
1110
        sigaction(SIGALRM, &act, NULL);
1111 1177

  
1112
        itv.it_interval.tv_sec = 0;
1113
        itv.it_interval.tv_usec = 999; /* for i386 kernel 2.6 to get 1 ms */
1114
        itv.it_value.tv_sec = 0;
1115
        itv.it_value.tv_usec = 10 * 1000;
1116
        setitimer(ITIMER_REAL, &itv, NULL);
1117
        /* we probe the tick duration of the kernel to inform the user if
1118
           the emulated kernel requested a too high timer frequency */
1119
        getitimer(ITIMER_REAL, &itv);
1178
    memset(&tc, 0, sizeof(tc));
1179
    timeGetDevCaps(&tc, sizeof(tc));
1120 1180

  
1121
#if defined(__linux__)
1122
        /* XXX: force /dev/rtc usage because even 2.6 kernels may not
1123
           have timers with 1 ms resolution. The correct solution will
1124
           be to use the POSIX real time timers available in recent
1125
           2.6 kernels */
1126
        if (itv.it_interval.tv_usec > 1000 || 1) {
1127
            /* try to use /dev/rtc to have a faster timer */
1128
            if (start_rtc_timer() < 0)
1129
                goto use_itimer;
1130
            /* disable itimer */
1131
            itv.it_interval.tv_sec = 0;
1132
            itv.it_interval.tv_usec = 0;
1133
            itv.it_value.tv_sec = 0;
1134
            itv.it_value.tv_usec = 0;
1135
            setitimer(ITIMER_REAL, &itv, NULL);
1136

  
1137
            /* use the RTC */
1138
            sigaction(SIGIO, &act, NULL);
1139
            fcntl(rtc_fd, F_SETFL, O_ASYNC);
1140
            fcntl(rtc_fd, F_SETOWN, getpid());
1141
        } else 
1142
#endif /* defined(__linux__) */
1143
        {
1144
        use_itimer:
1145
            pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * 
1146
                                   PIT_FREQ) / 1000000;
1147
        }
1181
    if (data->period < tc.wPeriodMin)
1182
        data->period = tc.wPeriodMin;
1183

  
1184
    timeBeginPeriod(data->period);
1185

  
1186
    data->timerId = timeSetEvent(1,         // interval (ms)
1187
                        data->period,       // resolution
1188
                        host_alarm_handler, // function
1189
                        (DWORD)t,           // parameter
1190
                        TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1191

  
1192
    if (!data->timerId) {
1193
        perror("Failed to initialize win32 alarm timer");
1194

  
1195
        timeEndPeriod(data->period);
1196
        CloseHandle(data->host_alarm);
1197
        return -1;
1148 1198
    }
1149
#endif
1199

  
1200
    qemu_add_wait_object(data->host_alarm, NULL, NULL);
1201

  
1202
    return 0;
1150 1203
}
1151 1204

  
1152
void quit_timers(void)
1205
static void win32_stop_timer(struct qemu_alarm_timer *t)
1153 1206
{
1154
#ifdef _WIN32
1155
    timeKillEvent(timerID);
1156
    timeEndPeriod(period);
1157
    if (host_alarm) {
1158
        CloseHandle(host_alarm);
1159
        host_alarm = NULL;
1207
    struct qemu_alarm_win32 *data = t->priv;
1208

  
1209
    timeKillEvent(data->timerId);
1210
    timeEndPeriod(data->period);
1211

  
1212
    CloseHandle(data->host_alarm);
1213
}
1214

  
1215
#endif /* _WIN32 */
1216

  
1217
static void init_timer_alarm(void)
1218
{
1219
    struct qemu_alarm_timer *t;
1220
    int i, err = -1;
1221

  
1222
    for (i = 0; alarm_timers[i].name; i++) {
1223
        t = &alarm_timers[i];
1224

  
1225
        printf("trying %s...\n", t->name);
1226

  
1227
        err = t->start(t);
1228
        if (!err)
1229
            break;
1160 1230
    }
1161
#endif
1231

  
1232
    if (err) {
1233
        fprintf(stderr, "Unable to find any suitable alarm timer.\n");
1234
        fprintf(stderr, "Terminating\n");
1235
        exit(1);
1236
    }
1237

  
1238
    alarm_timer = t;
1239
}
1240

  
1241
void quit_timers(void)
1242
{
1243
    alarm_timer->stop(alarm_timer);
1244
    alarm_timer = NULL;
1162 1245
}
1163 1246

  
1164 1247
/***********************************************************/

Also available in: Unified diff