Changeset 669 for trunk/kernel/kern/alarm.c
- Timestamp:
- Nov 19, 2020, 11:44:34 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/kern/alarm.c
r494 r669 1 1 /* 2 * kern/time.c - thread time related management 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 2 * alarm.c - timer based kernel alarm implementation 6 3 * 7 * This file is part of ALMOS-kernel.4 * Author Alain Greiner (2016,2017,2018,2019,2020) 8 5 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 6 * Copyright (c) UPMC Sorbonne Universites 7 * 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * You should have received a copy of the GNU General Public License 19 * along with ALMOS- kernel; if not, write to the Free Software Foundation,20 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 23 #include <types.h> 24 #include <kernel_config.h> 25 #include <hal_kernel_types.h> 26 #include <printk.h> 27 #include <list.h> 24 28 #include <thread.h> 25 #include <task.h> 26 #include <scheduler.h> 27 #include <time.h> 28 #include <list.h> 29 #include <rt_timer.h> 30 #include <kmagics.h> 29 #include <core.h> 30 #include <alarm.h> 31 31 32 error_t alarm_wait(struct alarm_info_s *info, uint_t msec) 32 //////////////////////////////////////////////////////////////////////////////////////////// 33 // This static function registers the alarm identified ny the <new_alarm> argument 34 // in the list of alarms rooted in the core identified by the <core> argument. 35 // When the existing list of alarms is not empty, it scan the list to insert the new 36 // alarm in the right place to respect the absolute dates ordering. 37 //////////////////////////////////////////////////////////////////////////////////////////// 38 // @ new_alarm : local pointer on the new alarm. 39 // @ core : local pointer on the target core. 40 //////////////////////////////////////////////////////////////////////////////////////////// 41 static void alarm_register( alarm_t * new_alarm, 42 core_t * core ) 33 43 { 34 register uint_t tm_now; 35 struct cpu_s *cpu; 36 struct alarm_s *alarm_mgr; 37 struct list_entry *iter; 38 struct alarm_info_s *current; 39 uint_t irq_state; 44 list_entry_t * current; // pointer on current list_entry in existing list 45 list_entry_t * previous; // pointer on previous list_entry in existing list 46 alarm_t * current_alarm; // pointer on current alarm in existing list 47 cycle_t current_date; // date of current alarm in existing list 40 48 41 cpu = current_cpu; 42 alarm_mgr = &cpu->alarm_mgr; 49 bool_t done = false; 43 50 44 cpu_disable_all_irq(&irq_state); 51 // get pointers on root of alarms and lock 52 list_entry_t * root = &core->alarms_root; 53 busylock_t * lock = &core->alarms_lock; 45 54 46 tm_now = cpu_get_ticks(cpu) * MSEC_PER_TICK; 47 info->signature = ALRM_INFO_ID; 48 info->tm_wakeup = tm_now + msec; 55 // get pointer on new_alarm list_entry 56 list_entry_t * new_entry = &new_alarm->list; 49 57 50 if(list_empty(&alarm_mgr->wait_queue)) 51 list_add_first(&alarm_mgr->wait_queue, &info->list); 52 else 53 { 54 list_foreach_forward(&alarm_mgr->wait_queue, iter) 55 { 56 current = list_element(iter, struct alarm_info_s, list); 57 58 if(info->tm_wakeup <= current->tm_wakeup) 59 { 60 list_add_pred(iter, &info->list); 61 goto NEXT_TRAITMENT; 62 } 63 } 64 list_add_last(&alarm_mgr->wait_queue, &info->list); 65 } 58 // get new_alarm date 59 cycle_t new_date = new_alarm->date; 66 60 67 NEXT_TRAITMENT: 68 cpu_restore_irq(irq_state); 69 return 0; 70 } 61 // take the lock 62 busylock_acquire( lock ); 71 63 72 void alarm_clock(struct alarm_s *alarm, uint_t ticks_nr) 64 // insert new alarm to respect dates order 65 if( list_is_empty( root ) ) // list empty 66 { 67 list_add_first( root , new_entry ); 68 } 69 else // list non empty 70 { 71 for( current = root->next ; 72 (current != root) && (done == false) ; 73 current = current->next ) 74 { 75 // get pointer on previous entry in existing list 76 previous = current->pred; 77 78 // get pointer on current alarm 79 current_alarm = LIST_ELEMENT( current , alarm_t , list ); 80 81 // get date for current alarm 82 current_date = current_alarm->date; 83 84 if( current_date > new_date ) // insert new alarm just before current 85 { 86 new_entry->next = current; 87 new_entry->pred = previous; 88 89 current->pred = new_entry; 90 previous->next = new_entry; 91 92 done = true; 93 } 94 } // end for 95 96 if( done == false ) // new_date is larger than all registered dates 97 { 98 list_add_last( root , new_entry ); 99 } 100 } 101 102 // release the lock 103 busylock_release( lock ); 104 105 } // end alarm_register() 106 107 ////////////////////////////////////// 108 void alarm_start( cycle_t date, 109 void * func_ptr, 110 xptr_t args_xp, 111 thread_t * thread ) 73 112 { 74 register uint_t tm_msec; 75 register struct list_entry *iter; 76 register struct alarm_info_s *info; 77 78 tm_msec = ticks_nr * MSEC_PER_TICK; 113 // get pointer on alarm 114 alarm_t * alarm = &thread->alarm; 79 115 80 list_foreach_forward(&alarm->wait_queue, iter) 81 { 82 info = list_element(iter, struct alarm_info_s, list); 116 // initialize alarm descriptor 117 alarm->date = date; 118 alarm->func_ptr = func_ptr; 119 alarm->args_xp = args_xp; 120 121 // register alarm in core list 122 alarm_register( alarm , thread->core ); 83 123 84 assert((info->signature == ALRM_INFO_ID), "Not an ALRM info object"); 124 } // end alarm_start() 85 125 86 if(tm_msec < info->tm_wakeup) 87 break; 126 ///////////////////////////////////// 127 void alarm_update( thread_t * thread, 128 cycle_t new_date ) 129 { 130 // get pointer on alarm 131 alarm_t * alarm = &thread->alarm; 132 133 // get pointer on core 134 core_t * core = thread->core; 135 136 // get pointer on lock protecting the alarms list 137 busylock_t * lock = &core->alarms_lock; 138 139 // unlink the alarm from the core list 140 busylock_acquire( lock ); 141 list_unlink( &alarm->list ); 142 busylock_release( lock ); 143 144 // update the alarm date 145 alarm->date = new_date; 146 147 // register alarm in core list 148 alarm_register( alarm , core ); 88 149 89 list_unlink(iter); 90 event_send(info->event, current_cpu->gid); 91 } 92 } 150 } // end alarm_update() 93 151 94 error_t alarm_manager_init(struct alarm_s *alarm) 152 //////////////////////////////////// 153 void alarm_stop( thread_t * thread ) 95 154 { 96 list_root_init(&alarm->wait_queue); 97 return 0; 98 } 155 // get pointer on alarm 156 alarm_t * alarm = &thread->alarm; 99 157 158 // get pointer on core 159 core_t * core = thread->core; 100 160 101 #if CONFIG_THREAD_TIME_STAT 161 // get pointer on lock protecting the alarms list 162 busylock_t * lock = &core->alarms_lock; 102 163 103 inline void tm_sleep_compute(struct thread_s *thread) 104 { 105 uint_t tm_now; 164 // unlink the alarm from the list rooted in core 165 busylock_acquire( lock ); 166 list_unlink( &alarm->list ); 167 busylock_release( lock ); 106 168 107 if(thread->type == TH_IDLE) 108 return; 169 } // end alarm_stop() 109 170 110 rt_timer_read(&tm_now);111 thread->info.tm_sleep += (tm_now - thread->info.tm_tmp);112 thread->info.tm_tmp = tm_now;113 }114 115 inline void tm_usr_compute(struct thread_s *thread)116 {117 uint_t tm_now;118 119 rt_timer_read(&tm_now);120 thread->info.tm_usr += (tm_now - thread->info.tm_tmp);121 thread->info.tm_tmp = tm_now;122 }123 124 inline void tm_sys_compute(struct thread_s *thread)125 {126 uint_t tm_now;127 128 rt_timer_read(&tm_now);129 thread->info.tm_sys += (tm_now - thread->info.tm_tmp);130 thread->info.tm_tmp = tm_now;131 }132 133 inline void tm_wait_compute(struct thread_s *thread)134 {135 uint_t tm_now;136 137 if(thread->type == TH_IDLE)138 return;139 140 rt_timer_read(&tm_now);141 thread->info.tm_wait += (tm_now - thread->info.tm_tmp);142 thread->info.tm_tmp = tm_now;143 thread->info.tm_exec = tm_now;144 }145 146 inline void tm_exit_compute(struct thread_s *thread)147 {148 uint_t tm_now;149 150 rt_timer_read(&tm_now);151 thread->info.tm_sys += tm_now - thread->info.tm_tmp;152 thread->info.tm_dead = tm_now;153 }154 155 inline void tm_born_compute(struct thread_s *thread)156 {157 uint_t tm_now;158 159 rt_timer_read(&tm_now);160 thread->info.tm_born = tm_now;161 thread->info.tm_tmp = tm_now;162 thread->info.tm_exec = tm_now;163 }164 165 inline void tm_create_compute(struct thread_s *thread)166 {167 rt_timer_read(&thread->info.tm_create);168 }169 170 171 #endif /* CONFIG_THREAD_TIME_STAT */
Note: See TracChangeset
for help on using the changeset viewer.