OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [kernel/] [itimer.c] - Diff between revs 1765 and 1782

Only display areas with differences | Details | Blame | View Log

Rev 1765 Rev 1782
/*
/*
 * linux/kernel/itimer.c
 * linux/kernel/itimer.c
 *
 *
 * Copyright (C) 1992 Darren Senn
 * Copyright (C) 1992 Darren Senn
 */
 */
 
 
/* These are all the functions necessary to implement itimers */
/* These are all the functions necessary to implement itimers */
 
 
#include <linux/signal.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/time.h>
#include <linux/time.h>
#include <linux/mm.h>
#include <linux/mm.h>
 
 
#include <asm/segment.h>
#include <asm/segment.h>
 
 
/*
/*
 * change timeval to jiffies, trying to avoid the
 * change timeval to jiffies, trying to avoid the
 * most obvious overflows..
 * most obvious overflows..
 *
 *
 * The tv_*sec values are signed, but nothing seems to
 * The tv_*sec values are signed, but nothing seems to
 * indicate whether we really should use them as signed values
 * indicate whether we really should use them as signed values
 * when doing itimers. POSIX doesn't mention this (but if
 * when doing itimers. POSIX doesn't mention this (but if
 * alarm() uses itimers without checking, we have to use unsigned
 * alarm() uses itimers without checking, we have to use unsigned
 * arithmetic).
 * arithmetic).
 */
 */
static unsigned long tvtojiffies(struct timeval *value)
static unsigned long tvtojiffies(struct timeval *value)
{
{
        unsigned long sec = (unsigned) value->tv_sec;
        unsigned long sec = (unsigned) value->tv_sec;
        unsigned long usec = (unsigned) value->tv_usec;
        unsigned long usec = (unsigned) value->tv_usec;
 
 
        if (sec > (ULONG_MAX / HZ))
        if (sec > (ULONG_MAX / HZ))
                return ULONG_MAX;
                return ULONG_MAX;
        usec += 1000000 / HZ - 1;
        usec += 1000000 / HZ - 1;
        usec /= 1000000 / HZ;
        usec /= 1000000 / HZ;
        return HZ*sec+usec;
        return HZ*sec+usec;
}
}
 
 
static void jiffiestotv(unsigned long jiffies, struct timeval *value)
static void jiffiestotv(unsigned long jiffies, struct timeval *value)
{
{
        value->tv_usec = (jiffies % HZ) * (1000000 / HZ);
        value->tv_usec = (jiffies % HZ) * (1000000 / HZ);
        value->tv_sec = jiffies / HZ;
        value->tv_sec = jiffies / HZ;
        return;
        return;
}
}
 
 
static int _getitimer(int which, struct itimerval *value)
static int _getitimer(int which, struct itimerval *value)
{
{
        register unsigned long val, interval;
        register unsigned long val, interval;
 
 
        switch (which) {
        switch (which) {
        case ITIMER_REAL:
        case ITIMER_REAL:
                interval = current->it_real_incr;
                interval = current->it_real_incr;
                val = 0;
                val = 0;
                if (del_timer(&current->real_timer)) {
                if (del_timer(&current->real_timer)) {
                        unsigned long now = jiffies;
                        unsigned long now = jiffies;
                        val = current->real_timer.expires;
                        val = current->real_timer.expires;
                        add_timer(&current->real_timer);
                        add_timer(&current->real_timer);
                        /* look out for negative/zero itimer.. */
                        /* look out for negative/zero itimer.. */
                        if (val <= now)
                        if (val <= now)
                                val = now+1;
                                val = now+1;
                        val -= now;
                        val -= now;
                }
                }
                break;
                break;
        case ITIMER_VIRTUAL:
        case ITIMER_VIRTUAL:
                val = current->it_virt_value;
                val = current->it_virt_value;
                interval = current->it_virt_incr;
                interval = current->it_virt_incr;
                break;
                break;
        case ITIMER_PROF:
        case ITIMER_PROF:
                val = current->it_prof_value;
                val = current->it_prof_value;
                interval = current->it_prof_incr;
                interval = current->it_prof_incr;
                break;
                break;
        default:
        default:
                return(-EINVAL);
                return(-EINVAL);
        }
        }
        jiffiestotv(val, &value->it_value);
        jiffiestotv(val, &value->it_value);
        jiffiestotv(interval, &value->it_interval);
        jiffiestotv(interval, &value->it_interval);
        return 0;
        return 0;
}
}
 
 
asmlinkage int sys_getitimer(int which, struct itimerval *value)
asmlinkage int sys_getitimer(int which, struct itimerval *value)
{
{
        int error;
        int error;
        struct itimerval get_buffer;
        struct itimerval get_buffer;
 
 
        if (!value)
        if (!value)
                return -EFAULT;
                return -EFAULT;
        error = _getitimer(which, &get_buffer);
        error = _getitimer(which, &get_buffer);
        if (error)
        if (error)
                return error;
                return error;
        error = verify_area(VERIFY_WRITE, value, sizeof(struct itimerval));
        error = verify_area(VERIFY_WRITE, value, sizeof(struct itimerval));
        if (error)
        if (error)
                return error;
                return error;
        memcpy_tofs(value, &get_buffer, sizeof(get_buffer));
        memcpy_tofs(value, &get_buffer, sizeof(get_buffer));
        return 0;
        return 0;
}
}
 
 
void it_real_fn(unsigned long __data)
void it_real_fn(unsigned long __data)
{
{
        struct task_struct * p = (struct task_struct *) __data;
        struct task_struct * p = (struct task_struct *) __data;
        unsigned long interval;
        unsigned long interval;
 
 
        send_sig(SIGALRM, p, 1);
        send_sig(SIGALRM, p, 1);
        interval = p->it_real_incr;
        interval = p->it_real_incr;
        if (interval) {
        if (interval) {
                unsigned long timeout = jiffies + interval;
                unsigned long timeout = jiffies + interval;
                /* check for overflow */
                /* check for overflow */
                if (timeout < interval)
                if (timeout < interval)
                        timeout = ULONG_MAX;
                        timeout = ULONG_MAX;
                p->real_timer.expires = timeout;
                p->real_timer.expires = timeout;
                add_timer(&p->real_timer);
                add_timer(&p->real_timer);
        }
        }
}
}
 
 
int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
{
{
        register unsigned long i, j;
        register unsigned long i, j;
        int k;
        int k;
 
 
        i = tvtojiffies(&value->it_interval);
        i = tvtojiffies(&value->it_interval);
        j = tvtojiffies(&value->it_value);
        j = tvtojiffies(&value->it_value);
        if (ovalue && (k = _getitimer(which, ovalue)) < 0)
        if (ovalue && (k = _getitimer(which, ovalue)) < 0)
                return k;
                return k;
        switch (which) {
        switch (which) {
                case ITIMER_REAL:
                case ITIMER_REAL:
                        del_timer(&current->real_timer);
                        del_timer(&current->real_timer);
                        current->it_real_value = j;
                        current->it_real_value = j;
                        current->it_real_incr = i;
                        current->it_real_incr = i;
                        if (!j)
                        if (!j)
                                break;
                                break;
                        i = j + jiffies;
                        i = j + jiffies;
                        /* check for overflow.. */
                        /* check for overflow.. */
                        if (i < j)
                        if (i < j)
                                i = ULONG_MAX;
                                i = ULONG_MAX;
                        current->real_timer.expires = i;
                        current->real_timer.expires = i;
                        add_timer(&current->real_timer);
                        add_timer(&current->real_timer);
                        break;
                        break;
                case ITIMER_VIRTUAL:
                case ITIMER_VIRTUAL:
                        if (j)
                        if (j)
                                j++;
                                j++;
                        current->it_virt_value = j;
                        current->it_virt_value = j;
                        current->it_virt_incr = i;
                        current->it_virt_incr = i;
                        break;
                        break;
                case ITIMER_PROF:
                case ITIMER_PROF:
                        if (j)
                        if (j)
                                j++;
                                j++;
                        current->it_prof_value = j;
                        current->it_prof_value = j;
                        current->it_prof_incr = i;
                        current->it_prof_incr = i;
                        break;
                        break;
                default:
                default:
                        return -EINVAL;
                        return -EINVAL;
        }
        }
        return 0;
        return 0;
}
}
 
 
asmlinkage int sys_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
asmlinkage int sys_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
{
{
        int error;
        int error;
        struct itimerval set_buffer, get_buffer;
        struct itimerval set_buffer, get_buffer;
 
 
        if (value) {
        if (value) {
                error = verify_area(VERIFY_READ, value, sizeof(*value));
                error = verify_area(VERIFY_READ, value, sizeof(*value));
                if (error)
                if (error)
                        return error;
                        return error;
                memcpy_fromfs(&set_buffer, value, sizeof(set_buffer));
                memcpy_fromfs(&set_buffer, value, sizeof(set_buffer));
        } else
        } else
                memset((char *) &set_buffer, 0, sizeof(set_buffer));
                memset((char *) &set_buffer, 0, sizeof(set_buffer));
 
 
        if (ovalue) {
        if (ovalue) {
                error = verify_area(VERIFY_WRITE, ovalue, sizeof(struct itimerval));
                error = verify_area(VERIFY_WRITE, ovalue, sizeof(struct itimerval));
                if (error)
                if (error)
                        return error;
                        return error;
        }
        }
 
 
        error = _setitimer(which, &set_buffer, ovalue ? &get_buffer : 0);
        error = _setitimer(which, &set_buffer, ovalue ? &get_buffer : 0);
        if (error || !ovalue)
        if (error || !ovalue)
                return error;
                return error;
 
 
        memcpy_tofs(ovalue, &get_buffer, sizeof(get_buffer));
        memcpy_tofs(ovalue, &get_buffer, sizeof(get_buffer));
        return error;
        return error;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.