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 + -
显示快捷键?