mjd-lists-plug on 7 Jan 2004 23:30:03 -0000


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: [PLUG] History is 1/2 over on Saturday


I said:
> It should be manifestly clear that the original Unix clock
> implementation was *not* only 16 bits, since if it were, it would have
> run out at 6:12 PM on January 1, 1970.  (65,536 sec < 19 hr)

I can't speak to the 'original' Unix clock implementation, because I
don't have the source code available.  But I checked with the 5th
Edition source code, which was the oldest I have available.  The 5th
Edition dates from about 1974, although the source code file I needed
to look at has a copyright date of 1973 on it.  (The 6th Edition was
the first to be widely distributed outside of Bell Labs, and the 4th
Edition was the first version in C.)

There are several relevant files.  First is the file
/usr/sys/ken/sys4.c, which is the last of four files that define the
kernel system call behavior.  The relevant function here is

        gtime()
        {

                u.u_ar0[R0] = time[0];
                u.u_ar0[R1] = time[1];
        }


The 'u' here is the 'user structure', which is the structure that
holds the current directory, open file table, process ID number, and
other per-process information for the current process.  The u_ar0
member holds copies of the process's register values at the time the
system call was made.  The C library linkage to 'gtime' copies the
register values into the u.u_ar0 area when the process makes the call,
and restores the values again afterwards; it's also responsible for
copying the system call's return value (the current time) into the
appropriate buffer at return time.

So the big question here is, how big is this time[] variable?
The declaration of 'time' is in /usr/sys/systm.h:

        int     time[2];

It's an array of two ints.  How big was an int?  Presumably two bytes,
and certainly more than one.  But we can check by looking at the
source code for the C compiler, this time in /usr/c/c03.c:

        length(acs)
        struct tnode *acs;
        {
                register t, n;
                register struct tnode *cs;

                cs = acs;
                t = cs->type;
                n = 1;
                while ((t&030) == ARRAY) {
                        t = decref(t);
                        n = dimtab[cs->ssp&0377];
                }
                if ((t&~07)==FUNC)
                        return(0);
                if (t>=PTR)
                        return(2*n);
                switch(t&07) {

                case INT:
                        return(2*n);

                case CHAR:
                        return(n);

                case FLOAT:
                        return(4*n);

                case DOUBLE:
                        return(8*n);

                case STRUCT:
                        return(n * dimtab[cs->lenp&0377]);

                case RSTRUCT:
                        error("Bad structure");
                        return(0);
                }
                error("Compiler error (length)");
        }



This function is used all over the compiler; for example, when a
pointer is incremented, this says how much to increment it by.  As you
can see, an INT is two bytes, so the int time[2] variable in the
kernel that holds the current time is four bytes.

___________________________________________________________________________
Philadelphia Linux Users Group         --        http://www.phillylinux.org
Announcements - http://lists.phillylinux.org/mailman/listinfo/plug-announce
General Discussion  --   http://lists.phillylinux.org/mailman/listinfo/plug