/*
* linux/kernel/posix_timers.c
*
*
* 2002-10-15 Posix Clocks & timers
* by George Anzinger george@mvista.com
*
* Copyright (C) 2002 2003 by MontaVista Software.
*
* 2004-06-01 Fix CLOCK_REALTIME clock/timer TIMER_ABSTIME bug.
* Copyright (C) 2004 Boris Hu
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* MontaVista Software | 1237 East Arques Avenue | Sunnyvale | CA 94085 | USA
*/
/* These are all the functions necessary to implement
* POSIX clocks & timers
*/
#include <linux/mm.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
#include <linux/list.h>
#include <linux/init.h>
#include <linux/compiler.h>
#include <linux/idr.h>
#include <linux/posix-timers.h>
#include <linux/syscalls.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <linux/module.h>
#ifndef div_long_long_rem
#include <asm/div64.h>
#define div_long_long_rem(dividend,divisor,remainder) ({ \
u64 result = dividend; \
*remainder = do_div(result,divisor); \
result; })
#endif
#define CLOCK_REALTIME_RES TICK_NSEC /* In nano seconds. */
static inline u64 mpy_l_X_l_ll(unsigned long mpy1,unsigned long mpy2)
{
return (u64)mpy1 * mpy2;
}
/*
* Management arrays for POSIX timers. Timers are kept in slab memory
* Timer ids are allocated by an external routine that keeps track of the
* id and the timer. The external interface is:
*
* void *idr_find(struct idr *idp, int id); to find timer_id <id>
* int idr_get_new(struct idr *idp, void *ptr); to get a new id and
* related it to <ptr>
* void idr_remove(struct idr *idp, int id); to release <id>
* void idr_init(struct idr *idp); to initialize <idp>
* which we supply.
* The idr_get_new *may* call slab for more memory so it must not be
* called under a spin lock. Likewise idr_remore may release memory
* (but it may be ok to do this under a lock...).
* idr_find is just a memory look up and is quite fast. A -1 return
* indicates that the requested id does not exist.
*/
/*
* Lets keep our timers in a slab cache :-)
*/
static kmem_cache_t *posix_timers_cache;
static struct idr posix_timers_id;
static DEFINE_SPINLOCK(idr_lock);
/*
* we assume that the new SIGEV_THREAD_ID shares no bits with the other
* SIGEV values. Here we put out an error if this assumption fails.
*/
#if SIGEV_THREAD_ID != (SIGEV_THREAD_ID & \
~(SIGEV_SIGNAL | SIGEV_NONE | SIGEV_THREAD))
#error "SIGEV_THREAD_ID must not share bit with other SIGEV values!"
#endif
/*
* The timer ID is turned into a timer address by idr_find().
* Verifying a valid ID consists of:
*
* a) checking that idr_find() returns other than -1.
* b) checking that the timer id matches the one in the timer itself.
* c) that the timer owner is in the callers thread group.
*/
/*
* CLOCKs: The POSIX standard calls for a couple of clocks and allows us
* to implement others. This structure defines the various
* clocks and allows the possibility of adding others. We
* provide an interface to add clocks to the table and expect
* the "arch" code to add at least one clock that is high
* resolution. Here we define the standard CLOCK_REALTIME as a
* 1/HZ resolution clock.
*
* RESOLUTION: Clock resolution is used to round up timer and interval
* times, NOT to report clock times, which are reported with as
* much resolution as the system can muster. In some cases this
* resolution may depend on the underlying clock hardware and
* may not be quantifiable until run time, and only then is the
* necessary code is written. The standard says we should say
* something about this issue in the documentation...
*
* FUNCTIONS: The CLOCKs structure defines possible functions to handle
* various clock functions. For clocks that use the standard
* system timer code these entries should be NULL. This will
* allow dispatch without the overhead of indirect function
* calls. CLOCKS that depend on other sources (e.g. WWV or GPS)
* must supply functions here, even if the function just returns
* ENOSYS. The standard POSIX timer management code assumes the
* following: 1.) The k_itimer struct (sched.h) is used for the
* timer. 2.) The list, it_lock, it_clock, it_id and it_process
* fields are not modified by timer code.
*
* At this time all functions EXCEPT clock_nanosleep can be
* redirected by the CLOCKS structure. Clock_nanosleep is in
* there, but the code ignores it.
*
* Permissions: It is assumed that the clock_settime() function defined
* for each clock will take care of permission checks. Some
* clocks may be set able by any user (i.e. local process
* clocks) others not. Currently the only set able clock we
* have is CLOCK_REALTIME and its high res counter part, both of
* which we beg off on and pass to do_sys_settimeofday().
*/
static struct k_clock posix_clocks[MAX_CLOCKS];
/*
* We only have one real clock that can be set so we need only one abs list,
* even if we should want to have several clocks with differing resolutions.
*/
static struct k_clock_abs abs_list = {.list = LIST_HEAD_INIT(abs_list.list),
.lock = SPIN_LOCK_UNLOCKED};
static void posix_timer_fn(unsigned long);
static u64 do_posix_clock_monotonic_gettime_parts(
struct timespec *tp, struct timespec *mo);
int do_posix_clock_monotonic_gettime(struct timespec *tp);
static int do_posix_clock_monotonic_get(clockid_t, struct timespec *tp);
static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags);
static inline void unlock_timer(struct k_itimer *timr, unsigned long flags)
{
spin_unlock_irqrestore(&timr->it_lock, flags);
}
/*
* Call the k_clock hook function if non-null, or the default function.
*/
#define CLOCK_DISPATCH(clock, call, arglist) \
((clock) < 0 ? posix_cpu_##call arglist : \
(posix_clocks[clock].call != NULL \
? (*posix_clocks[clock].call) arglist : common_##call arglist))
/*
* Default clock hook functions when the struct k_clock passed
* to register_posix_clock leaves a function pointer null.
*
* The function common_CALL is the default implementation for
* the function pointer CALL in struct k_clock.
*/
static inline int common_clock_getres(clockid_t which_clock,
struct timespec *tp)
{
tp->tv_sec = 0;
tp->tv_nsec = posix_clocks[which_clock].res;
return 0;
}
static inline int common_clock_get(clockid_t which_clock, struct time
|