linux/time.h 中缺少 do_posix_clock_monotonic_gettime

linux/time.h 中缺少 do_posix_clock_monotonic_gettime

我正在尝试编译驱动程序。do_posix_clock_monotonic_gettime在源代码中使用,并且我确定该文件具有#include <linux/time.h>.当我尝试编译它时,我得到了隐式声明。当我在磁盘上打开 time.h 文件时,它没有do_posix_clock_monotonic_gettime声明。有人可以帮我弄这个吗?

这是内容time.h

#ifndef _LINUX_TIME_H
#define _LINUX_TIME_H

# include <linux/cache.h>
# include <linux/seqlock.h>
# include <linux/math64.h>
# include <linux/time64.h>

extern struct timezone sys_tz;

#define TIME_T_MAX  (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)

static inline int timespec_equal(const struct timespec *a,
                                 const struct timespec *b)
{
    return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
}

/*
 * lhs < rhs:  return <0
 * lhs == rhs: return 0
 * lhs > rhs:  return >0
 */
static inline int timespec_compare(const struct timespec *lhs, const struct timespec *rhs)
{
    if (lhs->tv_sec < rhs->tv_sec)
        return -1;
    if (lhs->tv_sec > rhs->tv_sec)
        return 1;
    return lhs->tv_nsec - rhs->tv_nsec;
}

static inline int timeval_compare(const struct timeval *lhs, const struct timeval *rhs)
{
    if (lhs->tv_sec < rhs->tv_sec)
        return -1;
    if (lhs->tv_sec > rhs->tv_sec)
        return 1;
    return lhs->tv_usec - rhs->tv_usec;
}

extern time64_t mktime64(const unsigned int year, const unsigned int mon,
            const unsigned int day, const unsigned int hour,
            const unsigned int min, const unsigned int sec);

/**
 * Deprecated. Use mktime64().
 */
static inline unsigned long mktime(const unsigned int year,
            const unsigned int mon, const unsigned int day,
            const unsigned int hour, const unsigned int min,
            const unsigned int sec)
{
    return mktime64(year, mon, day, hour, min, sec);
}

extern void set_normalized_timespec(struct timespec *ts, time_t sec, s64 nsec);

/*
 * timespec_add_safe assumes both values are positive and checks
 * for overflow. It will return TIME_T_MAX if the reutrn would be
 * smaller then either of the arguments.
 */
extern struct timespec timespec_add_safe(const struct timespec lhs,
                     const struct timespec rhs);


static inline struct timespec timespec_add(struct timespec lhs,
                        struct timespec rhs)
{
    struct timespec ts_delta;
    set_normalized_timespec(&ts_delta, lhs.tv_sec + rhs.tv_sec,
                lhs.tv_nsec + rhs.tv_nsec);
    return ts_delta;
}

/*
 * sub = lhs - rhs, in normalized form
 */
static inline struct timespec timespec_sub(struct timespec lhs,
                        struct timespec rhs)
{
    struct timespec ts_delta;
    set_normalized_timespec(&ts_delta, lhs.tv_sec - rhs.tv_sec,
                lhs.tv_nsec - rhs.tv_nsec);
    return ts_delta;
}

/*
 * Returns true if the timespec is norm, false if denorm:
 */
static inline bool timespec_valid(const struct timespec *ts)
{
    /* Dates before 1970 are bogus */
    if (ts->tv_sec < 0)
        return false;
    /* Can't have more nanoseconds then a second */
    if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC)
        return false;
    return true;
}

static inline bool timespec_valid_strict(const struct timespec *ts)
{
    if (!timespec_valid(ts))
        return false;
    /* Disallow values that could overflow ktime_t */
    if ((unsigned long long)ts->tv_sec >= KTIME_SEC_MAX)
        return false;
    return true;
}

static inline bool timeval_valid(const struct timeval *tv)
{
    /* Dates before 1970 are bogus */
    if (tv->tv_sec < 0)
        return false;

    /* Can't have more microseconds then a second */
    if (tv->tv_usec < 0 || tv->tv_usec >= USEC_PER_SEC)
        return false;

    return true;
}

extern struct timespec timespec_trunc(struct timespec t, unsigned gran);

/*
 * Validates if a timespec/timeval used to inject a time offset is valid.
 * Offsets can be postive or negative. The value of the timeval/timespec
 * is the sum of its fields, but *NOTE*: the field tv_usec/tv_nsec must
 * always be non-negative.
 */
static inline bool timeval_inject_offset_valid(const struct timeval *tv)
{
    /* We don't check the tv_sec as it can be positive or negative */

    /* Can't have more microseconds then a second */
    if (tv->tv_usec < 0 || tv->tv_usec >= USEC_PER_SEC)
        return false;
    return true;
}

static inline bool timespec_inject_offset_valid(const struct timespec *ts)
{
    /* We don't check the tv_sec as it can be positive or negative */

    /* Can't have more nanoseconds then a second */
    if (ts->tv_nsec < 0 || ts->tv_nsec >= NSEC_PER_SEC)
        return false;
    return true;
}

#define CURRENT_TIME        (current_kernel_time())
#define CURRENT_TIME_SEC    ((struct timespec) { get_seconds(), 0 })

/* Some architectures do not supply their own clocksource.
 * This is mainly the case in architectures that get their
 * inter-tick times by reading the counter on their interval
 * timer. Since these timers wrap every tick, they're not really
 * useful as clocksources. Wrapping them to act like one is possible
 * but not very efficient. So we provide a callout these arches
 * can implement for use with the jiffies clocksource to provide
 * finer then tick granular time.
 */
#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
extern u32 (*arch_gettimeoffset)(void);
#endif

struct itimerval;
extern int do_setitimer(int which, struct itimerval *value,
            struct itimerval *ovalue);
extern int do_getitimer(int which, struct itimerval *value);

extern unsigned int alarm_setitimer(unsigned int seconds);

extern long do_utimes(int dfd, const char __user *filename, struct timespec *times, int flags);

struct tms;
extern void do_sys_times(struct tms *);

/*
 * Similar to the struct tm in userspace <time.h>, but it needs to be here so
 * that the kernel source is self contained.
 */
struct tm {
    /*
     * the number of seconds after the minute, normally in the range
     * 0 to 59, but can be up to 60 to allow for leap seconds
     */
    int tm_sec;
    /* the number of minutes after the hour, in the range 0 to 59*/
    int tm_min;
    /* the number of hours past midnight, in the range 0 to 23 */
    int tm_hour;
    /* the day of the month, in the range 1 to 31 */
    int tm_mday;
    /* the number of months since January, in the range 0 to 11 */
    int tm_mon;
    /* the number of years since 1900 */
    long tm_year;
    /* the number of days since Sunday, in the range 0 to 6 */
    int tm_wday;
    /* the number of days since January 1, in the range 0 to 365 */
    int tm_yday;
};

void time_to_tm(time_t totalsecs, int offset, struct tm *result);

/**
 * timespec_to_ns - Convert timespec to nanoseconds
 * @ts:     pointer to the timespec variable to be converted
 *
 * Returns the scalar nanosecond representation of the timespec
 * parameter.
 */
static inline s64 timespec_to_ns(const struct timespec *ts)
{
    return ((s64) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
}

/**
 * timeval_to_ns - Convert timeval to nanoseconds
 * @ts:     pointer to the timeval variable to be converted
 *
 * Returns the scalar nanosecond representation of the timeval
 * parameter.
 */
static inline s64 timeval_to_ns(const struct timeval *tv)
{
    return ((s64) tv->tv_sec * NSEC_PER_SEC) +
        tv->tv_usec * NSEC_PER_USEC;
}

/**
 * ns_to_timespec - Convert nanoseconds to timespec
 * @nsec:   the nanoseconds value to be converted
 *
 * Returns the timespec representation of the nsec parameter.
 */
extern struct timespec ns_to_timespec(const s64 nsec);

/**
 * ns_to_timeval - Convert nanoseconds to timeval
 * @nsec:   the nanoseconds value to be converted
 *
 * Returns the timeval representation of the nsec parameter.
 */
extern struct timeval ns_to_timeval(const s64 nsec);

/**
 * timespec_add_ns - Adds nanoseconds to a timespec
 * @a:      pointer to timespec to be incremented
 * @ns:     unsigned nanoseconds value to be added
 *
 * This must always be inlined because its used from the x86-64 vdso,
 * which cannot call other kernel functions.
 */
static __always_inline void timespec_add_ns(struct timespec *a, u64 ns)
{
    a->tv_sec += __iter_div_u64_rem(a->tv_nsec + ns, NSEC_PER_SEC, &ns);
    a->tv_nsec = ns;
}

#endif

在 Arch 上使用内核 4.7.2-1。

提前致谢。

编辑:

我使用了配置和制作。但没有成功。它给了我一个关于时间和日期的错误。这正是我得到的error: macro "__DATE__" might prevent reproducible builds [-Werror=date-time]。因此,我通过添加额外的 cflag 来抑制警告Wno-error=date-time。现在我明白了

error: implicit declaration of function ‘do_posix_clock_monotonic_gettime’ [-Werror=implicit-function-declaration]
   do_posix_clock_monotonic_gettime(&tstamp);

导致错误的代码是

static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
{
    struct snd_timer *timer;
    unsigned long flags;
    unsigned long resolution = 0;
    struct snd_timer_instance *ts;
    struct timespec tstamp;

    if (timer_tstamp_monotonic)
        do_posix_clock_monotonic_gettime(&tstamp);
    else
        getnstimeofday(&tstamp);
    if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_START ||
               event > SNDRV_TIMER_EVENT_PAUSE))
        return;
    if (event == SNDRV_TIMER_EVENT_START ||
        event == SNDRV_TIMER_EVENT_CONTINUE)
        resolution = snd_timer_resolution(ti);
    if (ti->ccallback)
        ti->ccallback(ti, event, &tstamp, resolution);
    if (ti->flags & SNDRV_TIMER_IFLG_SLAVE)
        return;
    timer = ti->timer;
    if (timer == NULL)
        return;
    if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
        return;
    spin_lock_irqsave(&timer->lock, flags);
    list_for_each_entry(ts, &ti->slave_active_head, active_list)
        if (ts->ccallback)
            ts->ccallback(ti, event + 100, &tstamp, resolution);
    spin_unlock_irqrestore(&timer->lock, flags);
}

还有一个函数使用 do_posix_clock_monotime_gettime。它的代码是:

static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
                      unsigned long resolution,
                      unsigned long ticks)
{
    struct snd_timer_user *tu = timeri->callback_data;
    struct snd_timer_tread *r, r1;
    struct timespec tstamp;
    int prev, append = 0;

    memset(&tstamp, 0, sizeof(tstamp));
    spin_lock(&tu->qlock);
    if ((tu->filter & ((1 << SNDRV_TIMER_EVENT_RESOLUTION) |
               (1 << SNDRV_TIMER_EVENT_TICK))) == 0) {
        spin_unlock(&tu->qlock);
        return;
    }
    if (tu->last_resolution != resolution || ticks > 0) {
        if (timer_tstamp_monotonic)
            do_posix_clock_monotonic_gettime(&tstamp);
        else
            getnstimeofday(&tstamp);
    }
    if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) &&
        tu->last_resolution != resolution) {
        r1.event = SNDRV_TIMER_EVENT_RESOLUTION;
        r1.tstamp = tstamp;
        r1.val = resolution;
        snd_timer_user_append_to_tqueue(tu, &r1);
        tu->last_resolution = resolution;
        append++;
    }
    if ((tu->filter & (1 << SNDRV_TIMER_EVENT_TICK)) == 0)
        goto __wake;
    if (ticks == 0)
        goto __wake;
    if (tu->qused > 0) {
        prev = tu->qtail == 0 ? tu->queue_size - 1 : tu->qtail - 1;
        r = &tu->tqueue[prev];
        if (r->event == SNDRV_TIMER_EVENT_TICK) {
            r->tstamp = tstamp;
            r->val += ticks;
            append++;
            goto __wake;
        }
    }
    r1.event = SNDRV_TIMER_EVENT_TICK;
    r1.tstamp = tstamp;
    r1.val = ticks;
    snd_timer_user_append_to_tqueue(tu, &r1);
    append++;
      __wake:
    spin_unlock(&tu->qlock);
    if (append == 0)
        return;
    kill_fasync(&tu->fasync, SIGIO, POLL_IN);
    wake_up(&tu->qchange_sleep);
}

答案1

该问题是由于删除了#define do_posix_clock_monotonic_gettime 4.0 之前的内核而导致的。

它曾经被定义为

#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)

您可以将该定义包含到某些驱动程序的标头中。另请注意,ktime_get_ts定义于linux/timekeeping.h4.7.2。

另外,我并不期望该驱动程序能够在 4.7.2 下正常运行,因为它似乎只在 3.xx 下进行了测试,不过,请尝试一下。

我希望这有帮助

相关内容