rtl_timer.c

来自「fsmlabs的real time linux的内核」· C语言 代码 · 共 279 行

C
279
字号
/* * POSIX.4 Timers  * * Written by J. Vidal, F. Vazquez * Copyright (C) Dec, 2002 OCERA Consortium. * * 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 version 2. * */ #include <time.h>#ifdef CONFIG_OC_PTIMERS#define CONFIG_OC_PTIMERS_DEBUG /* Timer List Manipulation. */ struct rtl_timer_struct *timer_list_start=NULL;spinlock_t rtl_timer_list_lock;int del_rtl_timer_from_list(struct rtl_timer_struct **start,timer_t timer);int add_rtl_timer_to_list(struct rtl_timer_struct *new_element,struct rtl_timer_struct **start);/* POSIX.4 Timers API.*//* One-Shot and Repeating Timers */ int timer_create(clockid_t clock_id, const struct sigevent *signal_specification, timer_t *timer_ptr){  static int id=0;    if ((pthread_self() != pthread_linux())) {errno=EINVAL;    return -1;  }  // for now, only CLOCK_REALTIME & CLOCK_MONOTONIC.   if (clock_id != CLOCK_REALTIME && clock_id != CLOCK_MONOTONIC){    errno=EINVAL;    return -1;  }  *timer_ptr=(timer_t) kmalloc (sizeof(struct rtl_timer_struct), GFP_KERNEL);    if (!(*timer_ptr))    {       rtl_printf("Can't allocate memory for timer %d\n",id);       errno= EAGAIN;      return -1;     }  (*timer_ptr)->id=id++;  (*timer_ptr)->clock_id=clock_id;    if (signal_specification){    (*timer_ptr)->signal.sigev_notify=signal_specification->sigev_notify;    if (signal_specification->sigev_notify == SIGEV_SIGNAL) {      if (signal_specification->sigev_signo >= RTL_SIGUSR1 && signal_specification->sigev_signo <= RTL_MAX_SIGNAL){	(*timer_ptr)->signal.sigev_signo=signal_specification->sigev_signo;      }else {	errno=EINVAL;	return -1;      }    }  } else {    (*timer_ptr)->signal.sigev_signo=0;  }      (*timer_ptr)->owner=NULL;   (*timer_ptr)->expires.it_interval=0;  (*timer_ptr)->expires.it_value=0;    (*timer_ptr)->magic= RTL_TIMER_MAGIC;    return 0; } int timer_delete(timer_t timer_id){  if (!timer_id) {    errno=EINVAL;    return -1;  }  #ifdef CONFIG_OC_PTIMERS_DEBUG   if  (!CHECK_VALID_TIMER(timer_id)){    errno=EINVAL;    return -1;  }#endif    if ((pthread_self() != pthread_linux())) {    return EAGAIN;  }  timer_id->magic=0;  // Protect timer list from writes,  rtl_spin_lock (&rtl_timer_list_lock);  del_rtl_timer_from_list(get_ptr_to_timer_list_start(),timer_id);  rtl_spin_unlock (&rtl_timer_list_lock);      kfree(timer_id);  return 0;}int timer_settime(timer_t timer_id, int flags, const struct itimerspec *new_setting, struct itimerspec *old_setting){  hrtime_t now=0;    if (!timer_id){        errno=EINVAL;    return -1;  }  #ifdef CONFIG_OC_PTIMERS_DEBUG   if (!CHECK_VALID_TIMER(timer_id)){        errno=EINVAL;    return -1;  }#endif    if (old_setting){    timer_gettime(timer_id,old_setting);  }  // Valid specs ?  if (!new_setting ||       new_setting->it_value.tv_nsec < 0 || new_setting->it_value.tv_nsec >=NSECS_PER_SEC ||      new_setting->it_interval.tv_nsec < 0 || new_setting->it_interval.tv_nsec >=NSECS_PER_SEC ||      new_setting->it_value.tv_sec < 0 ||      new_setting->it_interval.tv_sec < 0 ){    errno=EINVAL;     return -1;  }    /*      Check that it_value is different from 0, to     program the timer. IF both are 0 timer is disarmed.  */  if (new_setting->it_value.tv_sec || new_setting->it_value.tv_nsec)     {            // If the expiration time (it_value) is relative, convert it to absolute.      if (!(flags & TIMER_ABSTIME)){	now=clock_gethrtime(timer_id->clock_id);      }            timer_id->expires.it_value=now+timespec_to_ns(&new_setting->it_value);      timer_id->expires.it_interval=timespec_to_ns(&new_setting->it_interval);            /*	Both it_value.tv_sec & it_value.tv_nsec are 0,	so disarm timer.      */     }else{      DISARME_TIMER(timer_id);      return 0;    }  //set timer owner and reorder timer list if needed.  if (timer_id->owner!=pthread_self()){    // Protect timer_list from writes,    rtl_spin_lock (&rtl_timer_list_lock);    /* if the timer had already an owner, delete from timer list and ...*/    if (timer_id->owner)      del_rtl_timer_from_list(get_ptr_to_timer_list_start(),timer_id);    timer_id->owner=pthread_self();     /* insert it ordered by the new owner priority. */    add_rtl_timer_to_list(timer_id, get_ptr_to_timer_list_start());    rtl_spin_unlock (&rtl_timer_list_lock);      }     /* For now, the schedule is called allways */   clear_bit (RTL_SCHED_TIMER_OK, &sched_data((timer_id->owner)->cpu)->sched_flags);   rtl_schedule();  return 0;}int timer_gettime(timer_t timer_id, struct itimerspec *ts_set){  if (!timer_id || !ts_set){        errno=EINVAL;    return -1;  }  #ifdef CONFIG_OC_PTIMERS_DEBUG   if (!CHECK_VALID_TIMER(timer_id)){        errno=EINVAL;    return -1;  }#endif  if (TIMER_ARMED(timer_id)){         ts_set->it_value=timespec_from_ns((long long)(timer_id->expires.it_value - clock_gethrtime(timer_id->clock_id)));  } else {    ts_set->it_value.tv_sec=0;    ts_set->it_value.tv_nsec=0;  }  ts_set->it_interval= timespec_from_ns( timer_id->expires.it_interval);  return 0;}     int timer_getoverrun(timer_t timer_id){  return EINVAL;}/* Timer List Manipulation. */ /* Removes a timer from the timer list*/int del_rtl_timer_from_list(struct rtl_timer_struct **start,timer_t timer){  struct rtl_timer_struct *p=*start , *prev=NULL;  while (p != NULL) {    if (p->id == timer->id)      break;    prev = p;    p = p->next;  }  if (p == NULL) {    return -1;/* not found */  }  if (prev == NULL) {/* deletion of list's head */    *start = p->next;  }  else {    prev->next = p->next;  }  return 0;}/* Adds a new timer to the list,   maintainig it ordered by thread   owner priority. */int add_rtl_timer_to_list(struct rtl_timer_struct *newtimer,struct rtl_timer_struct **start){  struct rtl_timer_struct *p=*start, *prev=NULL;#ifdef CONFIG_OC_PTIMERS_DEBUG  if (!CHECK_VALID_TIMER(newtimer)) {    rtl_printf("PANIC in add_rtl_timer_to_list: newtimer not a valid timer !\n");    return -1;  }#endif  /* find the right place to put new timer */  while (p != NULL) {    if (RTL_PRIO(newtimer->owner) > RTL_PRIO(p->owner)){/* we have found the place */      break;    }    prev = p;    p = p->next;  }  if (prev == NULL) {/* First element */    newtimer->next = *start; /* append list */    *start = newtimer; /* new item becomes head of list */  }  else {/* is in the middle */    newtimer->next = p;    prev->next = newtimer;  }      return 0;}#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?