On 5/18/2026 2:27 PM, Warner Losh wrote:
> Add time-related system call shims: utimes, lutimes, futimes,
> futimesat, ktimer_create, ktimer_delete, ktimer_settime, and
> ktimer_gettime.
> 
> Signed-off-by: Stacey Son <[email protected]>
> Signed-off-by: MikaĆ«l Urankar <[email protected]>
> Signed-off-by: Kyle Evans <[email protected]>
> Signed-off-by: Warner Losh <[email protected]>
> Assisted-by: Claude Opus 4.6 (1M context)
> ---
>  bsd-user/freebsd/os-time.h | 210 
> +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 210 insertions(+)
> 
> diff --git a/bsd-user/freebsd/os-time.h b/bsd-user/freebsd/os-time.h
> index 16b71e6234..05fa043442 100644
> --- a/bsd-user/freebsd/os-time.h
> +++ b/bsd-user/freebsd/os-time.h
> @@ -217,5 +217,215 @@ static inline abi_long do_freebsd_ntp_gettime(abi_ulong 
> target_ntv_addr)
>  }
>  
>  
> +/* utimes(2) */
> +static inline abi_long do_freebsd_utimes(abi_long arg1, abi_long arg2)
> +{
> +    abi_long ret;
> +    void *p;
> +    struct timeval *tvp, tv[2];
> +
> +    if (arg2 != 0) {
> +        if (t2h_freebsd_timeval(&tv[0], arg2) ||
> +                t2h_freebsd_timeval(&tv[1], arg2 +
> +                        sizeof(struct target_freebsd_timeval))) {
> +            return -TARGET_EFAULT;
> +        }
> +        tvp = tv;
> +    } else {
> +        tvp = NULL;
> +    }
> +    p = lock_user_string(arg1);
> +    if (p == NULL) {
> +        return -TARGET_EFAULT;
> +    }
> +    ret = get_errno(utimes(p, tvp));
> +    unlock_user(p, arg1, 0);
> +
> +    return ret;
> +}
> +
> +/* lutimes(2) */
> +static inline abi_long do_freebsd_lutimes(abi_long arg1, abi_long arg2)
> +{
> +    abi_long ret;
> +    void *p;
> +    struct timeval *tvp, tv[2];
> +
> +    if (arg2 != 0) {
> +        if (t2h_freebsd_timeval(&tv[0], arg2) ||
> +                t2h_freebsd_timeval(&tv[1], arg2 +
> +                        sizeof(struct target_freebsd_timeval))) {
> +            return -TARGET_EFAULT;
> +        }
> +        tvp = tv;
> +    } else {
> +        tvp = NULL;
> +    }
> +    p = lock_user_string(arg1);
> +    if (p == NULL) {
> +        return -TARGET_EFAULT;
> +    }
> +    ret = get_errno(lutimes(p, tvp));
> +    unlock_user(p, arg1, 0);
> +
> +    return ret;
> +}
> +
> +/* futimes(2) */
> +static inline abi_long do_freebsd_futimes(abi_long arg1, abi_long arg2)
> +{
> +    struct timeval *tvp, tv[2];
> +
> +    if (arg2 != 0) {
> +        if (t2h_freebsd_timeval(&tv[0], arg2) ||
> +                t2h_freebsd_timeval(&tv[1], arg2 +
> +                        sizeof(struct target_freebsd_timeval))) {
> +            return -TARGET_EFAULT;
> +        }
> +        tvp = tv;
> +    } else {
> +        tvp = NULL;
> +    }
> +
> +    return get_errno(futimes(arg1, tvp));
> +}
> +
> +/* futimesat(2) */
> +static inline abi_long do_freebsd_futimesat(abi_long arg1, abi_long arg2,
> +        abi_long arg3)
> +{
> +    abi_long ret;
> +    void *p;
> +    struct timeval *tvp, tv[2];
> +
> +    if (arg3 != 0) {
> +        if (t2h_freebsd_timeval(&tv[0], arg3) ||
> +                t2h_freebsd_timeval(&tv[1], arg3 +
> +                        sizeof(struct target_freebsd_timeval))) {
> +            return -TARGET_EFAULT;
> +        }
> +        tvp = tv;
> +    } else {
> +        tvp = NULL;
> +    }
> +
> +    p = lock_user_string(arg2);
> +    if (p == NULL) {
> +        return -TARGET_EFAULT;
> +    }
> +    ret = get_errno(futimesat(arg1, p, tvp));
> +    unlock_user(p, arg2, 0);
> +
> +    return ret;
> +}
> +

The functions above are quite duplicated.
We could factor the first part at least, setting tvp.
The lock_user_string part can be replaced with LOCK_PATH.

> +/* timer_create(2) */
> +static inline abi_long do_freebsd_ktimer_create(abi_long arg1, abi_long arg2,
> +        abi_long arg3)
> +{
> +    /* args: clockid_t clockid, struct sigevent *sevp, int *timerid */
> +    abi_long ret;
> +
> +    struct sigevent host_sevp = { 0 }, *phost_sevp = NULL;
> +
> +    int clkid = arg1;
> +    int timer_index = next_free_host_timer();
> +
> +    if (timer_index < 0) {
> +        ret = -TARGET_EAGAIN;
> +    } else {
> +        int *phtimer = g_posix_timers  + timer_index;
> +
> +        if (arg2) {
> +            phost_sevp = &host_sevp;
> +            ret = target_to_host_sigevent(phost_sevp, arg2);
> +            if (ret != 0) {
> +                return -TARGET_EFAULT;
> +            }
> +        }
> +
> +        ret = get_errno(__sys_ktimer_create(clkid, phost_sevp, phtimer));
> +        if (ret) {
> +            phtimer = NULL;
> +        } else {
> +            if (put_user(TIMER_MAGIC | timer_index, arg3, int)) {
> +                ret = -TARGET_EFAULT;
> +            }
> +        }
> +    }
> +    return ret;
> +}
> +
> +/* timer_delete(2) */
> +static inline abi_long do_freebsd_ktimer_delete(abi_long arg1)
> +{
> +    /* args: int timerid */
> +    abi_long ret;
> +    int timerid = get_timer_id(arg1);
> +
> +    if (timerid < 0) {
> +        ret = timerid;
> +    } else {
> +        int htimer = g_posix_timers[timerid];
> +        ret = get_errno(__sys_ktimer_delete(htimer));
> +        g_posix_timers[timerid] = 0;
> +    }
> +    return ret;
> +}
> +
> +/* timer_settime(2) */
> +static inline abi_long do_freebsd_ktimer_settime(abi_long arg1, abi_long 
> arg2,
> +        abi_long arg3, abi_long arg4)
> +{
> +    /*
> +     * args: int timerid, int flags, const struct itimerspec *new_value,
> +     * struct itimerspec * old_value
> +     */
> +    abi_long ret;
> +    int timerid = get_timer_id(arg1);
> +
> +    if (timerid < 0) {
> +        ret = timerid;
> +    } else if (arg3 == 0) {
> +        ret = -TARGET_EINVAL;
> +    } else {
> +        int htimer = g_posix_timers[timerid];
> +        struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
> +
> +        if (target_to_host_itimerspec(&hspec_new, arg3)) {
> +            return -TARGET_EFAULT;
> +        }
> +        ret = get_errno(
> +            __sys_ktimer_settime(htimer, arg2, &hspec_new, &hspec_old));
> +        if (arg4 && host_to_target_itimerspec(arg4, &hspec_old)) {
> +            return -TARGET_EFAULT;
> +        }
> +    }
> +    return ret;
> +}
> +
> +/* timer_gettime(2) */
> +static inline abi_long do_freebsd_ktimer_gettime(abi_long arg1, abi_long 
> arg2)
> +{
> +    /* args: int timerid, struct itimerspec *curr_value */
> +    abi_long ret;
> +    int timerid = get_timer_id(arg1);
> +
> +    if (timerid < 0) {
> +        ret = timerid;
> +    } else if (!arg2) {
> +        ret = -TARGET_EFAULT;
> +    } else {
> +        int htimer = g_posix_timers[timerid];
> +        struct itimerspec hspec;
> +        ret = get_errno(__sys_ktimer_gettime(htimer, &hspec));
> +
> +        if (host_to_target_itimerspec(arg2, &hspec)) {
> +            ret = -TARGET_EFAULT;
> +        }
> +    }
> +    return ret;
> +}
> +
>  
>  #endif /* FREEBSD_OS_TIME_H */
> 


Reply via email to