~ubuntu-branches/debian/squeeze/ntp/squeeze-201010051545

« back to all changes in this revision

Viewing changes to libntp/adjtime.c

  • Committer: Bazaar Package Importer
  • Author(s): Matt Zimmerman
  • Date: 2004-10-11 16:10:27 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20041011161027-icyjbji8ujym633o
Tags: 1:4.2.0a-10ubuntu2
Use ntp.ubuntulinux.org instead of pool.ntp.org

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#ifdef HAVE_CONFIG_H
2
 
#include <config.h>
 
2
# include <config.h>
3
3
#endif
4
4
 
 
5
#ifdef MPE 
 
6
/*
 
7
 * MPE lacks adjtime(), so we define our own.  But note that time slewing has
 
8
 * a sub-second accuracy bug documented in SR 5003462838 which prevents ntpd
 
9
 * from being able to maintain clock synch.  Because of the bug, this adjtime()
 
10
 * implementation as used by ntpd has a side-effect of screwing up the hardware
 
11
 * PDC clock, which will need to be reset with a reboot.
 
12
 *
 
13
 * This problem affects all versions of MPE at the time of this writing (when
 
14
 * MPE/iX 7.0 is the most current).  It only causes bad things to happen when
 
15
 * doing continuous clock synchronization with ntpd; note that you CAN run ntpd
 
16
 * with "disable ntp" in ntp.conf if you wish to provide a time server.
 
17
 *
 
18
 * The one-time clock adjustment functionality of ntpdate and ntp_timeset can
 
19
 * be used without screwing up the PDC clock.
 
20
 * 
 
21
 */
 
22
#include <time.h>
 
23
 
 
24
int adjtime(struct timeval *delta, struct timeval *olddelta);
 
25
 
 
26
int adjtime(struct timeval *delta, struct timeval *olddelta)
 
27
 
 
28
{
 
29
/* Documented, supported MPE system intrinsics. */
 
30
 
 
31
extern void GETPRIVMODE(void);
 
32
extern void GETUSERMODE(void);
 
33
 
 
34
/* Undocumented, unsupported MPE internal functions. */
 
35
 
 
36
extern long long current_correction_usecs(void);
 
37
extern long long get_time(void);
 
38
extern void get_time_change_info(long long *, char *, char *);
 
39
extern long long pdc_time(int *);
 
40
extern void set_time_correction(long long, int, int);
 
41
extern long long ticks_to_micro(long long);
 
42
 
 
43
long long big_sec, big_usec, new_correction = 0LL;
 
44
long long prev_correction;
 
45
 
 
46
if (delta != NULL) {
 
47
  /* Adjustment required.  Convert delta to 64-bit microseconds. */
 
48
  big_sec = (long)delta->tv_sec;
 
49
  big_usec = delta->tv_usec;
 
50
  new_correction = (big_sec * 1000000LL) + big_usec;
 
51
}
 
52
 
 
53
GETPRIVMODE();
 
54
 
 
55
/* Determine how much of a previous correction (if any) we're interrupting. */
 
56
prev_correction = current_correction_usecs();
 
57
 
 
58
if (delta != NULL) {
 
59
  /* Adjustment required. */
 
60
 
 
61
#if 0
 
62
  /* Speculative code disabled until bug SR 5003462838 is fixed.  This bug
 
63
     prevents accurate time slewing, and indeed renders ntpd inoperable. */
 
64
 
 
65
  if (prev_correction != 0LL) {
 
66
    /* A previous adjustment did not complete.  Since the PDC UTC clock was
 
67
    immediately jumped at the start of the previous adjustment, we must
 
68
    explicitly reset it to the value of the MPE local time clock minus the
 
69
    time zone offset. */
 
70
 
 
71
    char pwf_since_boot, recover_pwf_time;
 
72
    long long offset_ticks, offset_usecs, pdc_usecs_current, pdc_usecs_wanted;
 
73
    int hpe_status;
 
74
 
 
75
    get_time_change_info(&offset_ticks, &pwf_since_boot, &recover_pwf_time);
 
76
    offset_usecs = ticks_to_micro(offset_ticks);
 
77
    pdc_usecs_wanted = get_time() - offset_usecs;
 
78
    pdc_usecs_current = pdc_time(&hpe_status);
 
79
    if (hpe_status == 0) 
 
80
      /* Force new PDC time by starting an extra correction. */
 
81
      set_time_correction(pdc_usecs_wanted - pdc_usecs_current,0,1);
 
82
  }
 
83
#endif /* 0 */
 
84
    
 
85
  /* Immediately jump the PDC time to the new value, and then initiate a 
 
86
     gradual MPE time correction slew. */
 
87
  set_time_correction(new_correction,0,1);
 
88
}
 
89
 
 
90
GETUSERMODE();
 
91
 
 
92
if (olddelta != NULL) {
 
93
  /* Caller wants to know remaining amount of previous correction. */
 
94
  (long)olddelta->tv_sec = prev_correction / 1000000LL;
 
95
  olddelta->tv_usec = prev_correction % 1000000LL;
 
96
}
 
97
 
 
98
return 0;
 
99
}
 
100
#endif /* MPE */
 
101
 
5
102
#ifdef NEED_HPUX_ADJTIME
6
103
/*************************************************************************/
7
104
/* (c) Copyright Tai Jin, 1988.  All Rights Reserved.                    */
147
244
        return (0);
148
245
}
149
246
 
150
 
#else /* not NEED_HPUX_ADJTIME */
 
247
#else
 
248
# if NEED_QNX_ADJTIME
 
249
/*
 
250
 * Emulate adjtime() using QNX ClockAdjust().
 
251
 * Chris Burghart <burghart@atd.ucar.edu>, 11/2001
 
252
 *
 
253
 * This is a *very* simple implementation of adjtime() for QNX.  
 
254
 * ClockAdjust() is used to tweak the system clock by about +- 1/10 
 
255
 * of its current clock period per tick until the desired delta is 
 
256
 * achieved.
 
257
 */
 
258
# include <math.h>
 
259
# include <stdio.h>
 
260
# include <sys/neutrino.h>
 
261
# include <sys/time.h>
 
262
 
 
263
# include <ntp_stdlib.h>
 
264
 
 
265
int 
 
266
adjtime (struct timeval *delta, struct timeval *olddelta)
 
267
{
 
268
    double delta_nsec;
 
269
    double delta_nsec_old;
 
270
    struct _clockadjust adj;
 
271
    struct _clockadjust oldadj;
 
272
    /*
 
273
     * How many nanoseconds are we adjusting?
 
274
     */
 
275
    delta_nsec = delta->tv_sec * 1e9 + delta->tv_usec * 1000;
 
276
    /*
 
277
     * Build the adjust structure and call ClockAdjust()
 
278
     */
 
279
    if (delta_nsec != 0)
 
280
    {
 
281
        struct _clockperiod period;
 
282
        long count;
 
283
        long increment;
 
284
 
 
285
        /*
 
286
         * Get the current clock period (nanoseconds)
 
287
         */
 
288
        if (ClockPeriod (CLOCK_REALTIME, 0, &period, 0) < 0)
 
289
            return -1;
 
290
 
 
291
        /*
 
292
         * Set the adjust increment to approximately 1/10 timer period per 
 
293
         * clock tick.
 
294
         */
 
295
        count = 1 + (long)(fabs(10 * delta_nsec / period.nsec));
 
296
        increment = (long)(delta_nsec / count);
 
297
 
 
298
        adj.tick_nsec_inc = increment;
 
299
        adj.tick_count = count;
 
300
    }
 
301
    else
 
302
    {
 
303
        adj.tick_nsec_inc = 0;
 
304
        adj.tick_count = 0;
 
305
    }
 
306
 
 
307
    if (ClockAdjust (CLOCK_REALTIME, &adj, &oldadj) < 0)
 
308
        return -1;
 
309
 
 
310
    /*
 
311
     * Build olddelta
 
312
     */
 
313
    delta_nsec_old = oldadj.tick_count * oldadj.tick_nsec_inc;
 
314
    olddelta->tv_sec = (int)(delta_nsec_old / 1e9);
 
315
    olddelta->tv_usec = (int)((delta_nsec_old - 1.0e9 * olddelta->tv_sec) / 
 
316
                              1000);
 
317
            
 
318
    return 0;
 
319
}
 
320
# else /* no special adjtime() needed */
151
321
int adjtime_bs;
152
 
#endif /* not NEED_HPUX_ADJTIME */
 
322
# endif
 
323
#endif