On Friday 27 November 2015 18:00:29 WEN Pingbo wrote:
To solve the y2038 problem in input_event, I had some attempts before [1], and this is the second one.
We can force userspace to use monotonic time in event timestamp, so the 'struct timeval' is enough to keep y2038-safe, as Arnd suggested. But we can not find a way to make kernel compatible with old binaries, which use realtime, and there are still some devices, which depend on realtime.
So I get a idea to add a new evdev interface, which is y2038 safe. And userspace can switch between the old and new interface via ioctl.
The patch series add three evdev interface type:
- EV_IF_LEGACY send event by input_event. This is the default option, keep kernel backward compatible.
The problem I see with this approach is that it still breaks any legacy source code that is compiled with a new libc that uses 64-bit time_t. If we are requiring source code changes for building users of input devices with a new libc, we can easily get them to handle the overflow (they normally only care about the microsecond portion anyway, so it doesn't matter in most cases), or to use monotonic time.
Did I miss something here?
Arnd
Hi, Arnd
在 2015年11月28日,00:58,Arnd Bergmann arnd@arndb.de 写道:
On Friday 27 November 2015 18:00:29 WEN Pingbo wrote:
To solve the y2038 problem in input_event, I had some attempts before [1], and this is the second one.
We can force userspace to use monotonic time in event timestamp, so the 'struct timeval' is enough to keep y2038-safe, as Arnd suggested. But we can not find a way to make kernel compatible with old binaries, which use realtime, and there are still some devices, which depend on realtime.
So I get a idea to add a new evdev interface, which is y2038 safe. And userspace can switch between the old and new interface via ioctl.
The patch series add three evdev interface type:
- EV_IF_LEGACY
send event by input_event. This is the default option, keep kernel backward compatible.
The problem I see with this approach is that it still breaks any legacy source code that is compiled with a new libc that uses 64-bit time_t. If we are requiring source code changes for building users of input devices with a new libc, we can easily get them to handle the overflow (they normally only care about the microsecond portion anyway, so it doesn't matter in most cases), or to use monotonic time.
I don’t think so.
Actually, from the view of userspace, EV_IF_LEGACY interface is work exactly the same as old evdev. We didn’t change anything in input_event and input_event_compat. And the problem you said will still be there, even without those patches.
Pingbo
On Sunday 29 November 2015 17:13:50 Pingbo Wen wrote:
在 2015年11月28日,00:58,Arnd Bergmann arnd@arndb.de 写道:
On Friday 27 November 2015 18:00:29 WEN Pingbo wrote:
To solve the y2038 problem in input_event, I had some attempts before [1], and this is the second one.
We can force userspace to use monotonic time in event timestamp, so the 'struct timeval' is enough to keep y2038-safe, as Arnd suggested. But we can not find a way to make kernel compatible with old binaries, which use realtime, and there are still some devices, which depend on realtime.
So I get a idea to add a new evdev interface, which is y2038 safe. And userspace can switch between the old and new interface via ioctl.
The patch series add three evdev interface type:
- EV_IF_LEGACY
send event by input_event. This is the default option, keep kernel backward compatible.
The problem I see with this approach is that it still breaks any legacy source code that is compiled with a new libc that uses 64-bit time_t. If we are requiring source code changes for building users of input devices with a new libc, we can easily get them to handle the overflow (they normally only care about the microsecond portion anyway, so it doesn't matter in most cases), or to use monotonic time.
I don’t think so.
Actually, from the view of userspace, EV_IF_LEGACY interface is work exactly the same as old evdev. We didn’t change anything in input_event and input_event_compat. And the problem you said will still be there, even without those patches.
I think we're still talking past one another. I thought we had established that
1. the current interface is broken when time_t changes in user space 2. we can fix it by redefining struct input_event in a way that is independent of time_t 3. once both user space and kernel are using the same ABI independent of time_t, we can look improving the timestamps so they don't overflow 4. the monotonic timestamp interface already avoids the overflow, so it would be sufficient as a solution for 3.
Where did I lose you here? Did you find any other facts that I was missing? I don't know whether the two new event structures make the interface better in some other way, but it seems mostly unrelated to either of the two problems we already have with time_t (the ABI mismatch, and the use of non-monotonic timestamps).
Arnd
Hi, Arnd
The patch series add three evdev interface type:
- EV_IF_LEGACY
send event by input_event. This is the default option, keep kernel backward compatible.
The problem I see with this approach is that it still breaks any legacy source code that is compiled with a new libc that uses 64-bit time_t. If we are requiring source code changes for building users of input devices with a new libc, we can easily get them to handle the overflow (they normally only care about the microsecond portion anyway, so it doesn't matter in most cases), or to use monotonic time.
I don’t think so.
Actually, from the view of userspace, EV_IF_LEGACY interface is work exactly the same as old evdev. We didn’t change anything in input_event and input_event_compat. And the problem you said will still be there, even without those patches.
I think we're still talking past one another. I thought we had established that
- the current interface is broken when time_t changes in user space
What kinds of changes in time_t? Extending it to 64-bits in both kernel and userspace? Ok, I get confused here, if there are some sample codes or use-cases here, it will help me a lot.
- we can fix it by redefining struct input_event in a way that
is independent of time_t 3. once both user space and kernel are using the same ABI independent of time_t, we can look improving the timestamps so they don't overflow 4. the monotonic timestamp interface already avoids the overflow, so it would be sufficient as a solution for 3.
Where did I lose you here? Did you find any other facts that I was missing? I don't know whether the two new event structures make the interface better in some other way, but it seems mostly unrelated to either of the two problems we already have with time_t (the ABI mismatch, and the use of non-monotonic timestamps).
It seems we are mismatch here.
Actually input_composite_event has the similar structure with input_event, but with a nicer definition, which can take both monotonic and non-monotonic timestamps safely.
What I assumed here, is that leaving EV_IF_LEGACY as a untouched, deprecated interface. If userspace try to adapt to new libc and kernel, it should move to new interface. The userspace can do a lazy update, keep the code untouched, but suffer the y2038 problem by itself.
We can force kernel using monotonic time in EV_IF_LEGACY interface, and making input_event independent from time_t(after evdev has converted to input_value, it’s easy to do that), but that also imply userspace must change their code to fit this change. If changing userspace code is a mandatory option, why not to force them do a complete conversion?
Pingbo
Hi, Arnd
The patch series add three evdev interface type:
- EV_IF_LEGACY
send event by input_event. This is the default option, keep kernel backward compatible.
The problem I see with this approach is that it still breaks any legacy source code that is compiled with a new libc that uses 64-bit time_t. If we are requiring source code changes for building users of input devices with a new libc, we can easily get them to handle the overflow (they normally only care about the microsecond portion anyway, so it doesn't matter in most cases), or to use monotonic time.
I don’t think so.
Actually, from the view of userspace, EV_IF_LEGACY interface is work exactly the same as old evdev. We didn’t change anything in input_event and input_event_compat. And the problem you said will still be there, even without those patches.
I think we're still talking past one another. I thought we had established that
- the current interface is broken when time_t changes in user space
What kinds of changes in time_t? Extending it to 64-bits in both kernel and userspace? Ok, I get confused here, if there are some sample codes or use-cases here, it will help me a lot.
- we can fix it by redefining struct input_event in a way that
is independent of time_t 3. once both user space and kernel are using the same ABI independent of time_t, we can look improving the timestamps so they don't overflow 4. the monotonic timestamp interface already avoids the overflow, so it would be sufficient as a solution for 3.
Where did I lose you here? Did you find any other facts that I was missing? I don't know whether the two new event structures make the interface better in some other way, but it seems mostly unrelated to either of the two problems we already have with time_t (the ABI mismatch, and the use of non-monotonic timestamps).
It seems we are mismatch here.
Actually input_composite_event has the similar structure with input_event, but with a nicer definition, which can take both monotonic and non-monotonic timestamps safely.
What I assumed here, is that leaving EV_IF_LEGACY as a untouched, deprecated interface. If userspace try to adapt to new libc and kernel, it should move to new interface. The userspace can do a lazy update, keep the code untouched, but suffer the y2038 problem by itself.
We can force kernel using monotonic time in EV_IF_LEGACY interface, and making input_event independent from time_t(after evdev has converted to input_value, it’s easy to do that), but that also imply userspace must change their code to fit this change. If changing userspace code is a mandatory option, why not to force them do a complete conversion?
Pingbo
On Tuesday 01 December 2015 16:34:00 Pingbo Wen wrote:
Hi, Arnd
The patch series add three evdev interface type:
- EV_IF_LEGACY
send event by input_event. This is the default option, keep kernel backward compatible.
The problem I see with this approach is that it still breaks any legacy source code that is compiled with a new libc that uses 64-bit time_t. If we are requiring source code changes for building users of input devices with a new libc, we can easily get them to handle the overflow (they normally only care about the microsecond portion anyway, so it doesn't matter in most cases), or to use monotonic time.
I don’t think so.
Actually, from the view of userspace, EV_IF_LEGACY interface is work exactly the same as old evdev. We didn’t change anything in input_event and input_event_compat. And the problem you said will still be there, even without those patches.
I think we're still talking past one another. I thought we had established that
- the current interface is broken when time_t changes in user space
What kinds of changes in time_t? Extending it to 64-bits in both kernel and userspace? Ok, I get confused here, if there are some sample codes or use-cases here, it will help me a lot.
We don't change time_t in the kernel, we just try to replace it with time64_t, or ktime_t where appropriate.
What I meant is the problem when glibc defines their time_t to be 'long long' so that user space can be built that runs after 2038. This changes the timeval and timespec definitions, so a process that tries to use 'struct input_event' has a different layout compared to what the kernel has.
I though that we had already discussed that multiple times.
- we can fix it by redefining struct input_event in a way that
is independent of time_t 3. once both user space and kernel are using the same ABI independent of time_t, we can look improving the timestamps so they don't overflow 4. the monotonic timestamp interface already avoids the overflow, so it would be sufficient as a solution for 3.
Where did I lose you here? Did you find any other facts that I was missing? I don't know whether the two new event structures make the interface better in some other way, but it seems mostly unrelated to either of the two problems we already have with time_t (the ABI mismatch, and the use of non-monotonic timestamps).
It seems we are mismatch here.
Actually input_composite_event has the similar structure with input_event, but with a nicer definition, which can take both monotonic and non-monotonic timestamps safely.
What I assumed here, is that leaving EV_IF_LEGACY as a untouched, deprecated interface. If userspace try to adapt to new libc and kernel, it should move to new interface. The userspace can do a lazy update, keep the code untouched, but suffer the y2038 problem by itself.
Forcing the move to the new API is very ugly, because you can't do it in a way that works on old kernels as well, unless you then try to support both APIs at runtime.
Just requiring user space to switch to monotonic time is easily done, as it can likely work either way.
We can force kernel using monotonic time in EV_IF_LEGACY interface, and making input_event independent from time_t(after evdev has converted to input_value, it’s easy to do that), but that also imply userspace must change their code to fit this change. If changing userspace code is a mandatory option, why not to force them do a complete conversion?
Most user space programs won't care, as they don't even look at the tv_sec portion, and the goal is to avoid having to change them.
There is still an open question to how exactly we want to get user space to change.
We could do some compile-time trick by having a union in struct input_event and mark the existing timeval part as deprecated, so we flag any use of the 32-bit tv_sec member, such as:
struct input_event { #if !defined(__KERNEL__) && __TIME_T_BITS == __BITS_PER_LONG struct timeval time; #else struct { union { __u32 tv_sec __attribute__((deprecated)); __u32 tv_sec_monotonic; }; __s32 tv_usec; } time; #endif __u16 type; __u16 code; __s32 value; };
Another option is to do a runtime change, and always set the time field to zero when the kernel is built without support for 32-bit time_t and user space has not yet called the ioctl to change to monotonic time.
We can also do a combination of the two.
Arnd
在 2015年12月1日,18:47,Arnd Bergmann arnd@arndb.de 写道:
On Tuesday 01 December 2015 16:34:00 Pingbo Wen wrote:
What kinds of changes in time_t? Extending it to 64-bits in both kernel and userspace? Ok, I get confused here, if there are some sample codes or use-cases here, it will help me a lot.
We don't change time_t in the kernel, we just try to replace it with time64_t, or ktime_t where appropriate.
What I meant is the problem when glibc defines their time_t to be 'long long' so that user space can be built that runs after 2038. This changes the timeval and timespec definitions, so a process that tries to use 'struct input_event' has a different layout compared to what the kernel has.
Ok, I didn’t reach this point. Thanks to clarify.
It seems we are mismatch here.
Actually input_composite_event has the similar structure with input_event, but with a nicer definition, which can take both monotonic and non-monotonic timestamps safely.
What I assumed here, is that leaving EV_IF_LEGACY as a untouched, deprecated interface. If userspace try to adapt to new libc and kernel, it should move to new interface. The userspace can do a lazy update, keep the code untouched, but suffer the y2038 problem by itself.
Forcing the move to the new API is very ugly, because you can't do it in a way that works on old kernels as well, unless you then try to support both APIs at runtime.
Just requiring user space to switch to monotonic time is easily done, as it can likely work either way.
It seems I’m more aggressive:) But the legacy binary can still live 30 years longer without any changes.
We can force kernel using monotonic time in EV_IF_LEGACY interface, and making input_event independent from time_t(after evdev has converted to input_value, it’s easy to do that), but that also imply userspace must change their code to fit this change. If changing userspace code is a mandatory option, why not to force them do a complete conversion?
Most user space programs won't care, as they don't even look at the tv_sec portion, and the goal is to avoid having to change them.
There is still an open question to how exactly we want to get user space to change.
We could do some compile-time trick by having a union in struct input_event and mark the existing timeval part as deprecated, so we flag any use of the 32-bit tv_sec member, such as:
struct input_event { #if !defined(__KERNEL__) && __TIME_T_BITS == __BITS_PER_LONG struct timeval time;
#else struct { union { __u32 tv_sec __attribute__((deprecated)); __u32 tv_sec_monotonic; }; __s32 tv_usec; } time; #endif __u16 type; __u16 code; __s32 value; };
I have one question here, if userspace use this structure, all helper functions of timeval will not work. And userspace need to write extra helper function for this fake timeval. This just create an another urgly time structure.
And this method also forces most of old binaries to compile with new libc, adjust their codes with new fake time structure.
Besides, I get an idea to combine your structure with input_composite_event:
union { struct { __s32 tv_usec; __s32 tv_sec; }; __s64 time; } time;
I prefer to use a single s64 timestamp, if our goal is to remove timeval from kernel.
Pingbo
On Thursday 03 December 2015 20:49:06 Pingbo Wen wrote:
在 2015年12月1日,18:47,Arnd Bergmann arnd@arndb.de 写道: On Tuesday 01 December 2015 16:34:00 Pingbo Wen wrote:
We can force kernel using monotonic time in EV_IF_LEGACY interface, and making input_event independent from time_t(after evdev has converted to input_value, it’s easy to do that), but that also imply userspace must change their code to fit this change. If changing userspace code is a mandatory option, why not to force them do a complete conversion?
Most user space programs won't care, as they don't even look at the tv_sec portion, and the goal is to avoid having to change them.
There is still an open question to how exactly we want to get user space to change.
We could do some compile-time trick by having a union in struct input_event and mark the existing timeval part as deprecated, so we flag any use of the 32-bit tv_sec member, such as:
struct input_event { #if !defined(__KERNEL__) && __TIME_T_BITS == __BITS_PER_LONG struct timeval time;
#else struct { union { __u32 tv_sec __attribute__((deprecated)); __u32 tv_sec_monotonic; }; __s32 tv_usec; } time; #endif __u16 type; __u16 code; __s32 value; };
I have one question here, if userspace use this structure, all helper functions of timeval will not work. And userspace need to write extra helper function for this fake timeval. This just create an another urgly time structure.
Correct, this is a useful side-effect of the change: any user space access to the event->time member that assumes it's a timeval will cause a compile-time warning or error (depending on the access), which helps us identify the broken code and fix it to use monotonic times as well as access the right struct members.
And this method also forces most of old binaries to compile with new libc, adjust their codes with new fake time structure.
Besides, I get an idea to combine your structure with input_composite_event:
union { struct { __s32 tv_usec; __s32 tv_sec; }; __s64 time; } time;
I prefer to use a single s64 timestamp, if our goal is to remove timeval from kernel.
We can't really remove this instance of timeval anyway, so adding an __s64 member here is not all that helpful. We should use __s64 nanoseconds for new interfaces like this, but I see no reason to change the one we have here.
Arnd
On Thursday 03 December 2015 13:54:47 Arnd Bergmann wrote:
struct input_event { #if !defined(__KERNEL__) && __TIME_T_BITS == __BITS_PER_LONG struct timeval time;
#else struct { union { __u32 tv_sec __attribute__((deprecated)); __u32 tv_sec_monotonic; }; __s32 tv_usec; } time; #endif __u16 type; __u16 code; __s32 value; };
I have one question here, if userspace use this structure, all helper functions of timeval will not work. And userspace need to write extra helper function for this fake timeval. This just create an another urgly time structure.
Correct, this is a useful side-effect of the change: any user space access to the event->time member that assumes it's a timeval will cause a compile-time warning or error (depending on the access), which helps us identify the broken code and fix it to use monotonic times as well as access the right struct members.
To clarify, the code also intentionally only changes the types when we are compiling with a new 32-bit libc: everything that builds today will continue to build and work without warnings, unless it gets recompiled with 64-bit time_t and needs to be fixed.
Arnd