Skip to content
  • Heiko Carstens's avatar
    f8d8977a
    s390/time: convert tod_clock_base to union · f8d8977a
    Heiko Carstens authored
    
    
    Convert tod_clock_base to union tod_clock. This simplifies quite a bit
    of code and also fixes a bug in read_persistent_clock64();
    
    void read_persistent_clock64(struct timespec64 *ts)
    {
            __u64 delta;
    
            delta = initial_leap_seconds + TOD_UNIX_EPOCH;
            get_tod_clock_ext(clk);
            *(__u64 *) &clk[1] -= delta;
            if (*(__u64 *) &clk[1] > delta)
                    clk[0]--;
            ext_to_timespec64(clk, ts);
    }
    
    Assume &clk[1] == 3 and delta == 2; then after the substraction the if
    condition becomes true and the epoch part of the clock is decremented
    by one because of an assumed overflow, even though there is none.
    
    Fix this by using 128 bit arithmetics and let the compiler do the
    right thing:
    
    void read_persistent_clock64(struct timespec64 *ts)
    {
            union tod_clock clk;
            u64 delta;
    
            delta = initial_leap_seconds + TOD_UNIX_EPOCH;
            store_tod_clock_ext(&clk);
            clk.eitod -= delta;
            ext_to_timespec64(&clk, ts);
    }
    
    Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
    Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
    f8d8977a
    s390/time: convert tod_clock_base to union
    Heiko Carstens authored
    
    
    Convert tod_clock_base to union tod_clock. This simplifies quite a bit
    of code and also fixes a bug in read_persistent_clock64();
    
    void read_persistent_clock64(struct timespec64 *ts)
    {
            __u64 delta;
    
            delta = initial_leap_seconds + TOD_UNIX_EPOCH;
            get_tod_clock_ext(clk);
            *(__u64 *) &clk[1] -= delta;
            if (*(__u64 *) &clk[1] > delta)
                    clk[0]--;
            ext_to_timespec64(clk, ts);
    }
    
    Assume &clk[1] == 3 and delta == 2; then after the substraction the if
    condition becomes true and the epoch part of the clock is decremented
    by one because of an assumed overflow, even though there is none.
    
    Fix this by using 128 bit arithmetics and let the compiler do the
    right thing:
    
    void read_persistent_clock64(struct timespec64 *ts)
    {
            union tod_clock clk;
            u64 delta;
    
            delta = initial_leap_seconds + TOD_UNIX_EPOCH;
            store_tod_clock_ext(&clk);
            clk.eitod -= delta;
            ext_to_timespec64(&clk, ts);
    }
    
    Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
    Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
Loading