Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to get 64-bit time_t in 32-bit programs in Linux?

On Windows I can call:

_time32(__time32_t); // to get 32-bit time_t
_time64(__time64_t); // to get 64-bit time_t

(both in 32 and 64-bit programs)

Is there any way do this in Linux (compiling with GCC)?

like image 621
chiyer Avatar asked Jan 16 '13 15:01

chiyer


People also ask

Can 32-bit programs run on 64-bit Linux?

While 64-bit apps couldn't work on 32-bit OS, 32-bit apps could work on 64-bit OS but they need some 32-bit libraries to run. Since Ubuntu 11.04 (Natty) and Debian 7.0 (Wheezy) there has been support for multiarch, when 32-bit and 64-bit libraries could live on the same OS.

How can I make 32-bit software 64-bit?

To run an application in Compatibility Mode, navigate to it in the file explorer and right-click it. Same as above, click on Properties from the menu. Under Properties, click on the Compatibility tab. Click the box that says “Run this program in compatibility mode for:” and select the Windows version you want to use.

Can I change from 32-bit to 64-bit Ubuntu?

If the answer is "width: 32 bits" neither replacing the hard drive or installing another operating system will transform your computer into a 64 bit machine. If the processor is 32 bit, you can't do what you're trying to do, otherwise it's absolutely possible.

Does Linux support x64?

Architecture: x86_64 – Linux kernel is 62 bit. CPU op-mode(s): 32-bit, 64-bit – Your CPU can run 32 or 64 bit instructions i.e. Linux kernel.


2 Answers

Apparently, no it's not possible. For starters, there is only one time() function in Linux, no time32() or time64().

After searching for a while, I can see that it's not libc's fault, but the culprit is actually the kernel.

In order for libc to fetch the current time, it need to execute a system call for it: (Source)

time_t time (t) time_t *t;
{
    // ...
    INTERNAL_SYSCALL_DECL (err);
    time_t res = INTERNAL_SYSCALL (time, err, 1, NULL);
    // ...
    return res;
}

The system call is defined as: (Source)

SYSCALL_DEFINE1(time, time_t __user *, tloc)
{
    time_t i = get_seconds();
    // ...
    return i;
}

The function get_seconds() returns an unsigned long, like so: (Source)

unsigned long get_seconds(void)
{
    struct timekeeper *tk = &timekeeper;

    return tk->xtime_sec;
}

And timekeeper.xtime_sec is actually 64-bit: (Source)

struct timekeeper {
    // ...
    /* Current CLOCK_REALTIME time in seconds */
    u64                     xtime_sec;
    // ...
}

Now, if you know your C, you know that the size of unsigned long is actually implementation-dependant. On my 64-bit machine here, it's 64-bit; but on my 32-bit machine here, it's 32-bit. It possibly could be 64-bit on some 32-bit implementation, but there's no guarantee.

On the other hand, u64 is always 64-bit, so at the very base, the kernel keeps track of the time in a 64-bit type. Why it then proceeds to return this as an unsigned long, which is not guaranteed to be 64-bit long, is beyond me.

In the end, even if libc's would force time_t to hold a 64-bit value, it wouldn't change a thing.

You could tie your application deeply into the kernel, but I don't think it's even worth it.

like image 101
netcoder Avatar answered Sep 22 '22 21:09

netcoder


Many answers above said that this is impossible, but that's entirely incorrect. It was not possible at that time yet people had been talking about fixing it for years. Finally 64-bit time support on 32-bit platforms was introduced to the Linux 5.1 kernel with the addition of the new *time64 syscalls. Look at this table you can see that those syscalls are only available on 32-bit platforms. Now if you're writing code for 32-bit systems you can call clock_gettime64 directly (from inline assembly or C with syscall()) to get the current time

However after that you're completely on your own. If you want full userspace support you must be on Linux 5.6 or higher along with musl 1.2+ or glibc 2.32+. Just rebuild your code and your time_t will become 64-bit long

  • All user space must be compiled with a 64-bit time_t, which will be supported in the coming musl-1.2 and glibc-2.32 releases, along with installed kernel headers from linux-5.6 or higher.

  • Applications that use the system call interfaces directly need to be ported to use the time64 syscalls added in linux-5.1 in place of the existing system calls. This impacts most users of futex() and seccomp() as well as programming languages that have their own runtime environment not based on libc.

https://lkml.org/lkml/2020/1/29/355?anz=web

For more information

  • Approaching the kernel year-2038 end game
  • 64-bit time symbol handling in the GNU C Library
  • glibc Y2038 Proofness Design
  • Change time_t and clock_t to 64 bit
like image 24
phuclv Avatar answered Sep 19 '22 21:09

phuclv