* ELL API changes before stabilizing @ 2016-10-05 21:45 Mat Martineau 2016-10-05 22:33 ` Denis Kenzior 0 siblings, 1 reply; 11+ messages in thread From: Mat Martineau @ 2016-10-05 21:45 UTC (permalink / raw) To: ell [-- Attachment #1: Type: text/plain, Size: 1297 bytes --] We will soon reach a point where breaking changes to the ELL APIs will get a lot more painful - changes already create a headache for the handful of projects we know about. Given that, I took a look over the public headers to see if there were any obvious adjustments to be made, and only found a few issues that jumped out at me. 1. timeout: extra nanosecond APIs with extremely_long_function_names. We could scrap the *_with_nanosecond calls and include nanoseconds in l_timeout_create and l_timeout_modify. 2. timeout: Why not use time_t for seconds? Yeah, 4 billion seconds should be enough for anyone, but the same argument could be made for the underlying struct timespec that's used for the system calls. 3. main: We recently changed l_main_exit() to be a cleanup function. It used to trigger an exit action. It would be more consistent to name the function for what it does rather than when it should be run (l_main_cleanup()?). 4. uintset: Why does uintset_new() create a set with min == 1? C programmers are more likely to assume it's 0-indexed. Maybe we don't need both l_uintset_new and l_uintset_new_from_range. One function that takes min and max seems sufficient. Anything else you've noticed? -- Mat Martineau Intel OTC ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: ELL API changes before stabilizing 2016-10-05 21:45 ELL API changes before stabilizing Mat Martineau @ 2016-10-05 22:33 ` Denis Kenzior 2016-10-06 16:36 ` Mat Martineau 0 siblings, 1 reply; 11+ messages in thread From: Denis Kenzior @ 2016-10-05 22:33 UTC (permalink / raw) To: ell [-- Attachment #1: Type: text/plain, Size: 2513 bytes --] Hi Mat, On 10/05/2016 04:45 PM, Mat Martineau wrote: > > We will soon reach a point where breaking changes to the ELL APIs will > get a lot more painful - changes already create a headache for the > handful of projects we know about. Given that, I took a look over the > public headers to see if there were any obvious adjustments to be made, > and only found a few issues that jumped out at me. > > > 1. timeout: extra nanosecond APIs with extremely_long_function_names. We > could scrap the *_with_nanosecond calls and include nanoseconds in > l_timeout_create and l_timeout_modify. So the background on this is that oFono/ConnMan/BlueZ tend to use g_timeout_add_seconds since it was supposedly cheaper than using the g_timeout_add version. Hence in ell we used the seconds as the 'preferred' version and introduced l_idle class as a g_timeout_add(0, ...) replacement. It is rare (non-existent in iwd & oFono) that we need timers that contain both seconds and microseconds, it is usually one-or-the-other situation. Do we have any users of the nanosecond version? iwd doesn't use it currently. > > > 2. timeout: Why not use time_t for seconds? Yeah, 4 billion seconds > should be enough for anyone, but the same argument could be made for the > underlying struct timespec that's used for the system calls. What's the advantage besides requiring an extra #include? time_t is a long in the end. So on 32-bit you're not buying anything, and on 64-bit you're in overkill territory. > > > 3. main: We recently changed l_main_exit() to be a cleanup function. It > used to trigger an exit action. It would be more consistent to name the > function for what it does rather than when it should be run > (l_main_cleanup()?). We tend to use _init to init modules and _exit to tear them down. So the naming sort of makes sense. I also like the symmetry between l_main_init and l_main_exit. > > > 4. uintset: Why does uintset_new() create a set with min == 1? C > programmers are more likely to assume it's 0-indexed. Maybe we don't > need both l_uintset_new and l_uintset_new_from_range. One function that > takes min and max seems sufficient. > This class was a straight up port from ofono's idmap utility. It is generally used where 0 is not a valid value. But I agree that having two constructors is redundant. > > Anything else you've noticed? > Thanks for doing this btw, its still on my TODO list. Regards, -Denis ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: ELL API changes before stabilizing 2016-10-05 22:33 ` Denis Kenzior @ 2016-10-06 16:36 ` Mat Martineau 2016-10-06 17:03 ` Denis Kenzior 0 siblings, 1 reply; 11+ messages in thread From: Mat Martineau @ 2016-10-06 16:36 UTC (permalink / raw) To: ell [-- Attachment #1: Type: text/plain, Size: 4185 bytes --] On Wed, 5 Oct 2016, Denis Kenzior wrote: > Hi Mat, > > On 10/05/2016 04:45 PM, Mat Martineau wrote: >> >> We will soon reach a point where breaking changes to the ELL APIs will >> get a lot more painful - changes already create a headache for the >> handful of projects we know about. Given that, I took a look over the >> public headers to see if there were any obvious adjustments to be made, >> and only found a few issues that jumped out at me. >> >> >> 1. timeout: extra nanosecond APIs with extremely_long_function_names. We >> could scrap the *_with_nanosecond calls and include nanoseconds in >> l_timeout_create and l_timeout_modify. > > So the background on this is that oFono/ConnMan/BlueZ tend to use > g_timeout_add_seconds since it was supposedly cheaper than using the > g_timeout_add version. Hence in ell we used the seconds as the 'preferred' > version and introduced l_idle class as a g_timeout_add(0, ...) replacement. Until just now, I thought l_idle callbacks only ran when the event loop ran out of things to do (you know, when "idle"). It's good that it works the way it does since we don't want idle callbacks to get starved when there's lots of I/O, but add "l_idle" naming to my list as a (very) minor annoyance. I think there's still a use case for a zero timeout when you want some recurring work to be triggered by either an event or the timer. It would be simpler to modify an existing timer with l_timeout_modify(0, ...) than it would be to remove the timer, use l_idle, and create an l_timeout again later. Right now this can be done by using a 1-nanosecond timeout, which isn't pretty. How about allowing 0 second/nanosecond values in l_timeout_modify but not _create? > It is rare (non-existent in iwd & oFono) that we need timers that contain > both seconds and microseconds, it is usually one-or-the-other situation. > > Do we have any users of the nanosecond version? iwd doesn't use it currently. Yes, that's why I cc'd Brian. The nanosecond version has separate parameters for seconds and nanoseconds, and they are in use together to specify timeouts greater than one second with subsecond accuracy. So my proposal is to get rid of the seconds-only version and always include the nanoseconds (which can be easily set to 0). struct l_timeout *l_timeout_create(time_t seconds, long nanoseconds, l_timeout_notify_cb_t callback, void *user_data, l_timeout_destroy_cb_t destroy); void l_timeout_modify(struct l_timeout *timeout, unsigned int seconds, long nanoseconds); > >> >> >> 2. timeout: Why not use time_t for seconds? Yeah, 4 billion seconds >> should be enough for anyone, but the same argument could be made for the >> underlying struct timespec that's used for the system calls. > > What's the advantage besides requiring an extra #include? time_t is a long in > the end. So on 32-bit you're not buying anything, and on 64-bit you're in > overkill territory. For relative timestamps, it's not a big deal. 136 years is a long time, even if it's not always a long int. >> 3. main: We recently changed l_main_exit() to be a cleanup function. It >> used to trigger an exit action. It would be more consistent to name the >> function for what it does rather than when it should be run >> (l_main_cleanup()?). > > We tend to use _init to init modules and _exit to tear them down. So the > naming sort of makes sense. I also like the symmetry between l_main_init and > l_main_exit. > >> >> >> 4. uintset: Why does uintset_new() create a set with min == 1? C >> programmers are more likely to assume it's 0-indexed. Maybe we don't >> need both l_uintset_new and l_uintset_new_from_range. One function that >> takes min and max seems sufficient. >> > > This class was a straight up port from ofono's idmap utility. It is > generally used where 0 is not a valid value. But I agree that having two > constructors is redundant. > >> >> Anything else you've noticed? >> > > Thanks for doing this btw, its still on my TODO list. -- Mat Martineau Intel OTC ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: ELL API changes before stabilizing 2016-10-06 16:36 ` Mat Martineau @ 2016-10-06 17:03 ` Denis Kenzior 2016-10-06 18:15 ` Mat Martineau 0 siblings, 1 reply; 11+ messages in thread From: Denis Kenzior @ 2016-10-06 17:03 UTC (permalink / raw) To: ell [-- Attachment #1: Type: text/plain, Size: 3907 bytes --] Hi Mat, On 10/06/2016 11:36 AM, Mat Martineau wrote: > > On Wed, 5 Oct 2016, Denis Kenzior wrote: > >> Hi Mat, >> >> On 10/05/2016 04:45 PM, Mat Martineau wrote: >>> >>> We will soon reach a point where breaking changes to the ELL APIs will >>> get a lot more painful - changes already create a headache for the >>> handful of projects we know about. Given that, I took a look over the >>> public headers to see if there were any obvious adjustments to be made, >>> and only found a few issues that jumped out at me. >>> >>> >>> 1. timeout: extra nanosecond APIs with extremely_long_function_names. We >>> could scrap the *_with_nanosecond calls and include nanoseconds in >>> l_timeout_create and l_timeout_modify. >> >> So the background on this is that oFono/ConnMan/BlueZ tend to use >> g_timeout_add_seconds since it was supposedly cheaper than using the >> g_timeout_add version. Hence in ell we used the seconds as the >> 'preferred' version and introduced l_idle class as a g_timeout_add(0, >> ...) replacement. > > Until just now, I thought l_idle callbacks only ran when the event loop > ran out of things to do (you know, when "idle"). It's good that it works > the way it does since we don't want idle callbacks to get starved when > there's lots of I/O, but add "l_idle" naming to my list as a (very) > minor annoyance. l_idle is simply invoked the next time the event loop runs. If we have idle objects scheduled, then the event loop will not sleep inside epoll, but instead run a tight-loop polling for file descriptor events. g_timeout_add(0, ...) is generally used to get out of re-entrancy conditions, which are tricky and lead to crashes. > > I think there's still a use case for a zero timeout when you want some > recurring work to be triggered by either an event or the timer. It would l_idle will call the callback until l_idle_remove is called. l_idle_oneshot is somewhat equivalent of g_timeout_add(0, ...) > be simpler to modify an existing timer with l_timeout_modify(0, ...) > than it would be to remove the timer, use l_idle, and create an > l_timeout again later. Right now this can be done by using a > 1-nanosecond timeout, which isn't pretty. How about allowing 0 > second/nanosecond values in l_timeout_modify but not _create? > Do we have an actual usecase ? I'm failing to see the utility, but I may be missing something. >> It is rare (non-existent in iwd & oFono) that we need timers that >> contain both seconds and microseconds, it is usually one-or-the-other >> situation. >> >> Do we have any users of the nanosecond version? iwd doesn't use it >> currently. > > Yes, that's why I cc'd Brian. > > The nanosecond version has separate parameters for seconds and > nanoseconds, and they are in use together to specify timeouts greater > than one second with subsecond accuracy. So my proposal is to get rid of > the seconds-only version and always include the nanoseconds (which can > be easily set to 0). > > struct l_timeout *l_timeout_create(time_t seconds, > long nanoseconds, l_timeout_notify_cb_t callback, > void *user_data, l_timeout_destroy_cb_t destroy); > void l_timeout_modify(struct l_timeout *timeout, > unsigned int seconds, long nanoseconds); > So then everyone pays the price of specifying seconds and nanoseconds when in reality 75% of calls will be the second version, 20% will be nanosecond version. And the 5% outlier actually wants to specify both. Not strictly against this, but just pointing out that ell API is supposed to be optimized for our actual usecases. Perhaps we should just do l_timeout_create, l_timeout_create_ms (oFono abuses sub-second timers, but it has zero need for nanosecond precision) and l_timeout_create_full to shorten the name. Regards, -Denis ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: ELL API changes before stabilizing 2016-10-06 17:03 ` Denis Kenzior @ 2016-10-06 18:15 ` Mat Martineau 2016-10-06 18:21 ` Marcel Holtmann ` (2 more replies) 0 siblings, 3 replies; 11+ messages in thread From: Mat Martineau @ 2016-10-06 18:15 UTC (permalink / raw) To: ell [-- Attachment #1: Type: text/plain, Size: 5371 bytes --] On Thu, 6 Oct 2016, Denis Kenzior wrote: > Hi Mat, > > On 10/06/2016 11:36 AM, Mat Martineau wrote: >> >> On Wed, 5 Oct 2016, Denis Kenzior wrote: >> >>> Hi Mat, >>> >>> On 10/05/2016 04:45 PM, Mat Martineau wrote: >>>> >>>> We will soon reach a point where breaking changes to the ELL APIs will >>>> get a lot more painful - changes already create a headache for the >>>> handful of projects we know about. Given that, I took a look over the >>>> public headers to see if there were any obvious adjustments to be made, >>>> and only found a few issues that jumped out at me. >>>> >>>> >>>> 1. timeout: extra nanosecond APIs with extremely_long_function_names. We >>>> could scrap the *_with_nanosecond calls and include nanoseconds in >>>> l_timeout_create and l_timeout_modify. >>> >>> So the background on this is that oFono/ConnMan/BlueZ tend to use >>> g_timeout_add_seconds since it was supposedly cheaper than using the >>> g_timeout_add version. Hence in ell we used the seconds as the >>> 'preferred' version and introduced l_idle class as a g_timeout_add(0, >>> ...) replacement. >> >> Until just now, I thought l_idle callbacks only ran when the event loop >> ran out of things to do (you know, when "idle"). It's good that it works >> the way it does since we don't want idle callbacks to get starved when >> there's lots of I/O, but add "l_idle" naming to my list as a (very) >> minor annoyance. > > l_idle is simply invoked the next time the event loop runs. If we have idle > objects scheduled, then the event loop will not sleep inside epoll, but > instead run a tight-loop polling for file descriptor events. g_timeout_add(0, > ...) is generally used to get out of re-entrancy conditions, which are tricky > and lead to crashes. Now that I've read the timerfd_create man page more closely... nevermind. Setting both tv_sec and tv_nsec to 0 disarms the timer. > >> >> I think there's still a use case for a zero timeout when you want some >> recurring work to be triggered by either an event or the timer. It would > > l_idle will call the callback until l_idle_remove is called. l_idle_oneshot > is somewhat equivalent of g_timeout_add(0, ...) > >> be simpler to modify an existing timer with l_timeout_modify(0, ...) >> than it would be to remove the timer, use l_idle, and create an >> l_timeout again later. Right now this can be done by using a >> 1-nanosecond timeout, which isn't pretty. How about allowing 0 >> second/nanosecond values in l_timeout_modify but not _create? >> > > Do we have an actual usecase ? I'm failing to see the utility, but I may be > missing something. Since a zero timeout disables the timer, the "immediate timeout" use case is moot. l_idle_oneshot does the trick where something needs to be scheduled immediately but not on the current stack. >>> It is rare (non-existent in iwd & oFono) that we need timers that >>> contain both seconds and microseconds, it is usually one-or-the-other >>> situation. >>> >>> Do we have any users of the nanosecond version? iwd doesn't use it >>> currently. >> >> Yes, that's why I cc'd Brian. >> >> The nanosecond version has separate parameters for seconds and >> nanoseconds, and they are in use together to specify timeouts greater >> than one second with subsecond accuracy. So my proposal is to get rid of >> the seconds-only version and always include the nanoseconds (which can >> be easily set to 0). >> >> struct l_timeout *l_timeout_create(time_t seconds, >> long nanoseconds, l_timeout_notify_cb_t callback, >> void *user_data, l_timeout_destroy_cb_t destroy); >> void l_timeout_modify(struct l_timeout *timeout, >> unsigned int seconds, long nanoseconds); >> > > So then everyone pays the price of specifying seconds and nanoseconds when in > reality 75% of calls will be the second version, 20% will be nanosecond > version. And the 5% outlier actually wants to specify both. The nanoseconds calls don't pay any price, they *already* have both seconds and nanoseconds (nanoseconds value must be less than 1000000000). Look at the existing timeout.h - all I did in those function prototypes above is remove "_with_nanoseconds". My whole point here is that I see it as a favorable tradeoff to pass an extra '0' to the timeout APIs when subsecond resolution is not required rather than have superfluous API calls. It's only a matter of what ELL users see in their code, not code efficiency: the current whole-second APIs are just wrappers around full-resolution common code anyway. If the whole-seconds use case is overly impacted by the extra parameter, then the tradeoff may not be favorable. > Not strictly against this, but just pointing out that ell API is supposed to > be optimized for our actual usecases. Perhaps we should just do > l_timeout_create, l_timeout_create_ms (oFono abuses sub-second timers, but it > has zero need for nanosecond precision) and l_timeout_create_full to shorten > the name. I agree that nanoseconds are overkill, but I don't mind seeing the platform detail filter up to the ELL API level. In practice, milliseconds are likely sufficient and would save a lot of '0' keypresses. -- Mat Martineau Intel OTC ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: ELL API changes before stabilizing 2016-10-06 18:15 ` Mat Martineau @ 2016-10-06 18:21 ` Marcel Holtmann 2016-10-07 18:42 ` Mat Martineau 2016-10-06 18:22 ` Gix, Brian 2016-10-06 18:51 ` Denis Kenzior 2 siblings, 1 reply; 11+ messages in thread From: Marcel Holtmann @ 2016-10-06 18:21 UTC (permalink / raw) To: ell [-- Attachment #1: Type: text/plain, Size: 5653 bytes --] Hi Mat, >>>>> We will soon reach a point where breaking changes to the ELL APIs will >>>>> get a lot more painful - changes already create a headache for the >>>>> handful of projects we know about. Given that, I took a look over the >>>>> public headers to see if there were any obvious adjustments to be made, >>>>> and only found a few issues that jumped out at me. >>>>> 1. timeout: extra nanosecond APIs with extremely_long_function_names. We >>>>> could scrap the *_with_nanosecond calls and include nanoseconds in >>>>> l_timeout_create and l_timeout_modify. >>>> So the background on this is that oFono/ConnMan/BlueZ tend to use >>>> g_timeout_add_seconds since it was supposedly cheaper than using the >>>> g_timeout_add version. Hence in ell we used the seconds as the >>>> 'preferred' version and introduced l_idle class as a g_timeout_add(0, >>>> ...) replacement. >>> Until just now, I thought l_idle callbacks only ran when the event loop >>> ran out of things to do (you know, when "idle"). It's good that it works >>> the way it does since we don't want idle callbacks to get starved when >>> there's lots of I/O, but add "l_idle" naming to my list as a (very) >>> minor annoyance. >> >> l_idle is simply invoked the next time the event loop runs. If we have idle objects scheduled, then the event loop will not sleep inside epoll, but instead run a tight-loop polling for file descriptor events. g_timeout_add(0, ...) is generally used to get out of re-entrancy conditions, which are tricky and lead to crashes. > > Now that I've read the timerfd_create man page more closely... nevermind. Setting both tv_sec and tv_nsec to 0 disarms the timer. > >> >>> I think there's still a use case for a zero timeout when you want some >>> recurring work to be triggered by either an event or the timer. It would >> >> l_idle will call the callback until l_idle_remove is called. l_idle_oneshot is somewhat equivalent of g_timeout_add(0, ...) >> >>> be simpler to modify an existing timer with l_timeout_modify(0, ...) >>> than it would be to remove the timer, use l_idle, and create an >>> l_timeout again later. Right now this can be done by using a >>> 1-nanosecond timeout, which isn't pretty. How about allowing 0 >>> second/nanosecond values in l_timeout_modify but not _create? >> >> Do we have an actual usecase ? I'm failing to see the utility, but I may be missing something. > > Since a zero timeout disables the timer, the "immediate timeout" use case is moot. l_idle_oneshot does the trick where something needs to be scheduled immediately but not on the current stack. > >>>> It is rare (non-existent in iwd & oFono) that we need timers that >>>> contain both seconds and microseconds, it is usually one-or-the-other >>>> situation. >>>> Do we have any users of the nanosecond version? iwd doesn't use it >>>> currently. >>> Yes, that's why I cc'd Brian. >>> The nanosecond version has separate parameters for seconds and >>> nanoseconds, and they are in use together to specify timeouts greater >>> than one second with subsecond accuracy. So my proposal is to get rid of >>> the seconds-only version and always include the nanoseconds (which can >>> be easily set to 0). >>> struct l_timeout *l_timeout_create(time_t seconds, >>> long nanoseconds, l_timeout_notify_cb_t callback, >>> void *user_data, l_timeout_destroy_cb_t destroy); >>> void l_timeout_modify(struct l_timeout *timeout, >>> unsigned int seconds, long nanoseconds); >> >> So then everyone pays the price of specifying seconds and nanoseconds when in reality 75% of calls will be the second version, 20% will be nanosecond version. And the 5% outlier actually wants to specify both. > > The nanoseconds calls don't pay any price, they *already* have both seconds and nanoseconds (nanoseconds value must be less than 1000000000). Look at the existing timeout.h - all I did in those function prototypes above is remove "_with_nanoseconds". > > My whole point here is that I see it as a favorable tradeoff to pass an extra '0' to the timeout APIs when subsecond resolution is not required rather than have superfluous API calls. It's only a matter of what ELL users see in their code, not code efficiency: the current whole-second APIs are just wrappers around full-resolution common code anyway. If the whole-seconds use case is overly impacted by the extra parameter, then the tradeoff may not be favorable. > >> Not strictly against this, but just pointing out that ell API is supposed to be optimized for our actual usecases. Perhaps we should just do >> l_timeout_create, l_timeout_create_ms (oFono abuses sub-second timers, but it has zero need for nanosecond precision) and l_timeout_create_full to shorten the name. > > I agree that nanoseconds are overkill, but I don't mind seeing the platform detail filter up to the ELL API level. In practice, milliseconds are likely sufficient and would save a lot of '0' keypresses. we actually wanted the timerfd API to expose also range timers. In the kernel it is possible to specify a range and then the kernel will coalesce the wakeup time. That is what we really want. One that coalesces for us and another that is precise. The seconds vs nanoseconds is most likely not a good representation of that and we should just switch to using milliseconds, but as range timeout and one as precise timeout. I am also not convinced that creating a timerfd for each struct is a good idea. It might be better to share timerfd and update timeout wakeups. Regards Marcel ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: ELL API changes before stabilizing 2016-10-06 18:21 ` Marcel Holtmann @ 2016-10-07 18:42 ` Mat Martineau 0 siblings, 0 replies; 11+ messages in thread From: Mat Martineau @ 2016-10-07 18:42 UTC (permalink / raw) To: ell [-- Attachment #1: Type: text/plain, Size: 1481 bytes --] On Thu, 6 Oct 2016, Marcel Holtmann wrote: > we actually wanted the timerfd API to expose also range timers. In the > kernel it is possible to specify a range and then the kernel will > coalesce the wakeup time. That is what we really want. One that > coalesces for us and another that is precise. The seconds vs nanoseconds > is most likely not a good representation of that and we should just > switch to using milliseconds, but as range timeout and one as precise > timeout. Denis makes the case that multiple constructors aren't so bad, and coarse (1 sec resolution) timeouts seem to be a common enough need. timerfd needs some work to use the underlying hrtimer range capabilities. One approach is to add a TFD_SLACK flag that would make that timer use the per-thread slack value set by prctl(PR_SET_TIMERSLACK, ...). That only gives us one precise timer pool and one slack timer pool, though. > I am also not convinced that creating a timerfd for each struct is a > good idea. It might be better to share timerfd and update timeout > wakeups. It would make sense to consume an fd only for the next timer to expire. We would probably switch to using TFD_TIMER_ABSTIME instead of relative time values in timerfd_settime to prevent the later timers from drifting, which would require additional clock_gettime() syscalls. Another benefit would be the opportunity to handle some coalescing in ELL. -- Mat Martineau Intel OTC ^ permalink raw reply [flat|nested] 11+ messages in thread
* RE: ELL API changes before stabilizing 2016-10-06 18:15 ` Mat Martineau 2016-10-06 18:21 ` Marcel Holtmann @ 2016-10-06 18:22 ` Gix, Brian 2016-10-06 18:51 ` Denis Kenzior 2 siblings, 0 replies; 11+ messages in thread From: Gix, Brian @ 2016-10-06 18:22 UTC (permalink / raw) To: ell [-- Attachment #1: Type: text/plain, Size: 5968 bytes --] To advocate for Bluetooth Mesh, we have a number of situations where we have Random Timers between 0 - 1.5 seconds, or 0-10 seconds, where we want sub-second increments to keep multiple and many rf devices from talking over each other. -----Original Message----- From: Mat Martineau [mailto:mathew.j.martineau(a)linux.intel.com] Sent: Thursday, October 6, 2016 11:16 AM To: Denis Kenzior <denkenz@gmail.com> Cc: ell(a)lists.01.org; Gix, Brian <brian.gix@intel.com>; Zaborowski, Andrew <andrew.zaborowski@intel.com> Subject: Re: ELL API changes before stabilizing On Thu, 6 Oct 2016, Denis Kenzior wrote: > Hi Mat, > > On 10/06/2016 11:36 AM, Mat Martineau wrote: >> >> On Wed, 5 Oct 2016, Denis Kenzior wrote: >> >>> Hi Mat, >>> >>> On 10/05/2016 04:45 PM, Mat Martineau wrote: >>>> >>>> We will soon reach a point where breaking changes to the ELL APIs >>>> will get a lot more painful - changes already create a headache for >>>> the handful of projects we know about. Given that, I took a look >>>> over the public headers to see if there were any obvious >>>> adjustments to be made, and only found a few issues that jumped out at me. >>>> >>>> >>>> 1. timeout: extra nanosecond APIs with >>>> extremely_long_function_names. We could scrap the *_with_nanosecond >>>> calls and include nanoseconds in l_timeout_create and l_timeout_modify. >>> >>> So the background on this is that oFono/ConnMan/BlueZ tend to use >>> g_timeout_add_seconds since it was supposedly cheaper than using the >>> g_timeout_add version. Hence in ell we used the seconds as the >>> 'preferred' version and introduced l_idle class as a >>> g_timeout_add(0, >>> ...) replacement. >> >> Until just now, I thought l_idle callbacks only ran when the event >> loop ran out of things to do (you know, when "idle"). It's good that >> it works the way it does since we don't want idle callbacks to get >> starved when there's lots of I/O, but add "l_idle" naming to my list >> as a (very) minor annoyance. > > l_idle is simply invoked the next time the event loop runs. If we > have idle objects scheduled, then the event loop will not sleep inside > epoll, but instead run a tight-loop polling for file descriptor > events. g_timeout_add(0, > ...) is generally used to get out of re-entrancy conditions, which are > tricky and lead to crashes. Now that I've read the timerfd_create man page more closely... nevermind. Setting both tv_sec and tv_nsec to 0 disarms the timer. > >> >> I think there's still a use case for a zero timeout when you want >> some recurring work to be triggered by either an event or the timer. >> It would > > l_idle will call the callback until l_idle_remove is called. > l_idle_oneshot is somewhat equivalent of g_timeout_add(0, ...) > >> be simpler to modify an existing timer with l_timeout_modify(0, ...) >> than it would be to remove the timer, use l_idle, and create an >> l_timeout again later. Right now this can be done by using a >> 1-nanosecond timeout, which isn't pretty. How about allowing 0 >> second/nanosecond values in l_timeout_modify but not _create? >> > > Do we have an actual usecase ? I'm failing to see the utility, but I > may be missing something. Since a zero timeout disables the timer, the "immediate timeout" use case is moot. l_idle_oneshot does the trick where something needs to be scheduled immediately but not on the current stack. >>> It is rare (non-existent in iwd & oFono) that we need timers that >>> contain both seconds and microseconds, it is usually >>> one-or-the-other situation. >>> >>> Do we have any users of the nanosecond version? iwd doesn't use it >>> currently. >> >> Yes, that's why I cc'd Brian. >> >> The nanosecond version has separate parameters for seconds and >> nanoseconds, and they are in use together to specify timeouts greater >> than one second with subsecond accuracy. So my proposal is to get rid >> of the seconds-only version and always include the nanoseconds (which >> can be easily set to 0). >> >> struct l_timeout *l_timeout_create(time_t seconds, >> long nanoseconds, l_timeout_notify_cb_t callback, >> void *user_data, l_timeout_destroy_cb_t destroy); void >> l_timeout_modify(struct l_timeout *timeout, >> unsigned int seconds, long >> nanoseconds); >> > > So then everyone pays the price of specifying seconds and nanoseconds > when in reality 75% of calls will be the second version, 20% will be > nanosecond version. And the 5% outlier actually wants to specify both. The nanoseconds calls don't pay any price, they *already* have both seconds and nanoseconds (nanoseconds value must be less than 1000000000). Look at the existing timeout.h - all I did in those function prototypes above is remove "_with_nanoseconds". My whole point here is that I see it as a favorable tradeoff to pass an extra '0' to the timeout APIs when subsecond resolution is not required rather than have superfluous API calls. It's only a matter of what ELL users see in their code, not code efficiency: the current whole-second APIs are just wrappers around full-resolution common code anyway. If the whole-seconds use case is overly impacted by the extra parameter, then the tradeoff may not be favorable. > Not strictly against this, but just pointing out that ell API is > supposed to be optimized for our actual usecases. Perhaps we should > just do l_timeout_create, l_timeout_create_ms (oFono abuses sub-second > timers, but it has zero need for nanosecond precision) and > l_timeout_create_full to shorten the name. I agree that nanoseconds are overkill, but I don't mind seeing the platform detail filter up to the ELL API level. In practice, milliseconds are likely sufficient and would save a lot of '0' keypresses. -- Mat Martineau Intel OTC ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: ELL API changes before stabilizing 2016-10-06 18:15 ` Mat Martineau 2016-10-06 18:21 ` Marcel Holtmann 2016-10-06 18:22 ` Gix, Brian @ 2016-10-06 18:51 ` Denis Kenzior 2016-10-07 18:05 ` Mat Martineau 2 siblings, 1 reply; 11+ messages in thread From: Denis Kenzior @ 2016-10-06 18:51 UTC (permalink / raw) To: ell [-- Attachment #1: Type: text/plain, Size: 1580 bytes --] Hi Mat, > > My whole point here is that I see it as a favorable tradeoff to pass an > extra '0' to the timeout APIs when subsecond resolution is not required > rather than have superfluous API calls. It's only a matter of what ELL > users see in their code, not code efficiency: the current whole-second > APIs are just wrappers around full-resolution common code anyway. If the > whole-seconds use case is overly impacted by the extra parameter, then > the tradeoff may not be favorable. That is really what I meant. I want to save the users from typing the extra 0 parameter unnecessarily. We already have 4 arguments to l_timeout_create, with lots of potential zeros. > I agree that nanoseconds are overkill, but I don't mind seeing the > platform detail filter up to the ELL API level. In practice, > milliseconds are likely sufficient and would save a lot of '0' keypresses. > Hence my question. Do we actually need to expose nanoseconds? I can't believe someone needs that level of precision. MS is fine. If we add the range stuff in, then that's another argument or two, depending on representation. I actually don't mind multiple constructors. They're just shorthands and are easier to read than trying to parse the arguments. We can include a range fudge factor as part of the API. e.g. second version of timeout_create fudges by +/- 500ms. MS versions can fudge by +/- 500 nanoseconds, etc. And if someone wants full control, then a full-blown provide-everything constructor can be added. Regards, -Denis ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: ELL API changes before stabilizing 2016-10-06 18:51 ` Denis Kenzior @ 2016-10-07 18:05 ` Mat Martineau 2016-10-07 18:41 ` Denis Kenzior 0 siblings, 1 reply; 11+ messages in thread From: Mat Martineau @ 2016-10-07 18:05 UTC (permalink / raw) To: ell [-- Attachment #1: Type: text/plain, Size: 2192 bytes --] On Thu, 6 Oct 2016, Denis Kenzior wrote: > Hi Mat, > >> >> My whole point here is that I see it as a favorable tradeoff to pass an >> extra '0' to the timeout APIs when subsecond resolution is not required >> rather than have superfluous API calls. It's only a matter of what ELL >> users see in their code, not code efficiency: the current whole-second >> APIs are just wrappers around full-resolution common code anyway. If the >> whole-seconds use case is overly impacted by the extra parameter, then >> the tradeoff may not be favorable. > > That is really what I meant. I want to save the users from typing the extra > 0 parameter unnecessarily. We already have 4 arguments to l_timeout_create, > with lots of potential zeros. Ok, sounds fine. >> I agree that nanoseconds are overkill, but I don't mind seeing the >> platform detail filter up to the ELL API level. In practice, >> milliseconds are likely sufficient and would save a lot of '0' keypresses. >> > > Hence my question. Do we actually need to expose nanoseconds? I can't > believe someone needs that level of precision. MS is fine. Sounds like we're in agreement that nanoseconds are overkill and ms is sufficient. > If we add the range stuff in, then that's another argument or two, depending > on representation. > > I actually don't mind multiple constructors. They're just shorthands and are > easier to read than trying to parse the arguments. We can include a range > fudge factor as part of the API. e.g. second version of timeout_create > fudges by +/- 500ms. MS versions can fudge by +/- 500 nanoseconds, etc. > > And if someone wants full control, then a full-blown provide-everything > constructor can be added. Works for me. Do we have a consensus around removing the nanosecond versions and adding: struct l_timeout *l_timeout_create_ms(unsigned long milliseconds, l_timeout_notify_cb_t callback, void *user_data, l_timeout_destroy_cb_t destroy); void l_timeout_modify_ms(struct l_timeout *timeout, unsigned long milliseconds); -- Mat Martineau Intel OTC ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: ELL API changes before stabilizing 2016-10-07 18:05 ` Mat Martineau @ 2016-10-07 18:41 ` Denis Kenzior 0 siblings, 0 replies; 11+ messages in thread From: Denis Kenzior @ 2016-10-07 18:41 UTC (permalink / raw) To: ell [-- Attachment #1: Type: text/plain, Size: 519 bytes --] Hi Mat, > > Works for me. Do we have a consensus around removing the nanosecond > versions and adding: > > struct l_timeout *l_timeout_create_ms(unsigned long milliseconds, > l_timeout_notify_cb_t callback, > void *user_data, > l_timeout_destroy_cb_t destroy); > void l_timeout_modify_ms(struct l_timeout *timeout, > unsigned long milliseconds); > This looks fine to me. Regards, -Denis ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2016-10-07 18:42 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2016-10-05 21:45 ELL API changes before stabilizing Mat Martineau 2016-10-05 22:33 ` Denis Kenzior 2016-10-06 16:36 ` Mat Martineau 2016-10-06 17:03 ` Denis Kenzior 2016-10-06 18:15 ` Mat Martineau 2016-10-06 18:21 ` Marcel Holtmann 2016-10-07 18:42 ` Mat Martineau 2016-10-06 18:22 ` Gix, Brian 2016-10-06 18:51 ` Denis Kenzior 2016-10-07 18:05 ` Mat Martineau 2016-10-07 18:41 ` Denis Kenzior
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.