Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/time/clock.c

    r2e4e706 rd0c82c5  
    3333/**
    3434 * @file
    35  * @brief       High-level clock interrupt handler.
     35 * @brief High-level clock interrupt handler.
    3636 *
    3737 * This file contains the clock() function which is the source
    3838 * of preemption. It is also responsible for executing expired
    3939 * timeouts.
    40  */
    41  
     40 *
     41 */
     42
    4243#include <time/clock.h>
    4344#include <time/timeout.h>
     
    5657#include <mm/frame.h>
    5758#include <ddi/ddi.h>
     59#include <arch/cycle.h>
    5860
    5961/* Pointer to variable with uptime */
     
    6365static parea_t clock_parea;
    6466
    65 /* Variable holding fragment of second, so that we would update
    66  * seconds correctly
     67/** Fragment of second
     68 *
     69 * For updating  seconds correctly.
     70 *
    6771 */
    6872static unative_t secfrag = 0;
     
    7377 * information about realtime data. We allocate 1 page with these
    7478 * data and update it periodically.
     79 *
    7580 */
    7681void clock_counter_init(void)
    7782{
    78         void *faddr;
    79 
    80         faddr = frame_alloc(ONE_FRAME, FRAME_ATOMIC);
     83        void *faddr = frame_alloc(ONE_FRAME, FRAME_ATOMIC);
    8184        if (!faddr)
    8285                panic("Cannot allocate page for clock.");
     
    8790        uptime->seconds2 = 0;
    8891        uptime->useconds = 0;
    89 
     92       
    9093        clock_parea.pbase = (uintptr_t) faddr;
    9194        clock_parea.frames = 1;
    9295        ddi_parea_register(&clock_parea);
    93 
     96       
    9497        /*
    9598         * Prepare information for the userspace so that it can successfully
    9699         * physmem_map() the clock_parea.
     100         *
    97101         */
    98102        sysinfo_set_item_val("clock.cacheable", NULL, (unative_t) true);
     
    100104}
    101105
    102 
    103106/** Update public counters
    104107 *
    105108 * Update it only on first processor
    106  * TODO: Do we really need so many write barriers?
     109 * TODO: Do we really need so many write barriers?
     110 *
    107111 */
    108112static void clock_update_counters(void)
     
    122126}
    123127
     128static void cpu_update_accounting(void)
     129{
     130        irq_spinlock_lock(&CPU->lock, false);
     131        uint64_t now = get_cycle();
     132        CPU->busy_cycles += now - CPU->last_cycle;
     133        CPU->last_cycle = now;
     134        irq_spinlock_unlock(&CPU->lock, false);
     135}
     136
    124137/** Clock routine
    125138 *
     
    131144void clock(void)
    132145{
    133         link_t *l;
    134         timeout_t *h;
    135         timeout_handler_t f;
    136         void *arg;
    137146        size_t missed_clock_ticks = CPU->missed_clock_ticks;
    138         unsigned int i;
    139 
    140         /* Account lost ticks to CPU usage */
    141         if (CPU->idle) {
    142                 CPU->idle_ticks += missed_clock_ticks + 1;
    143         } else {
    144                 CPU->busy_ticks += missed_clock_ticks + 1;
    145         }
    146         CPU->idle = false;
    147 
     147       
     148        /* Account CPU usage */
     149        cpu_update_accounting();
     150       
    148151        /*
    149152         * To avoid lock ordering problems,
    150153         * run all expired timeouts as you visit them.
     154         *
    151155         */
     156        size_t i;
    152157        for (i = 0; i <= missed_clock_ticks; i++) {
     158                /* Update counters and accounting */
    153159                clock_update_counters();
    154                 spinlock_lock(&CPU->timeoutlock);
    155                 while ((l = CPU->timeout_active_head.next) != &CPU->timeout_active_head) {
    156                         h = list_get_instance(l, timeout_t, link);
    157                         spinlock_lock(&h->lock);
    158                         if (h->ticks-- != 0) {
    159                                 spinlock_unlock(&h->lock);
     160                cpu_update_accounting();
     161               
     162                irq_spinlock_lock(&CPU->timeoutlock, false);
     163               
     164                link_t *cur;
     165                while ((cur = CPU->timeout_active_head.next) != &CPU->timeout_active_head) {
     166                        timeout_t *timeout = list_get_instance(cur, timeout_t, link);
     167                       
     168                        irq_spinlock_lock(&timeout->lock, false);
     169                        if (timeout->ticks-- != 0) {
     170                                irq_spinlock_unlock(&timeout->lock, false);
    160171                                break;
    161172                        }
    162                         list_remove(l);
    163                         f = h->handler;
    164                         arg = h->arg;
    165                         timeout_reinitialize(h);
    166                         spinlock_unlock(&h->lock);     
    167                         spinlock_unlock(&CPU->timeoutlock);
    168 
    169                         f(arg);
    170 
    171                         spinlock_lock(&CPU->timeoutlock);
     173                       
     174                        list_remove(cur);
     175                        timeout_handler_t handler = timeout->handler;
     176                        void *arg = timeout->arg;
     177                        timeout_reinitialize(timeout);
     178                       
     179                        irq_spinlock_unlock(&timeout->lock, false);
     180                        irq_spinlock_unlock(&CPU->timeoutlock, false);
     181                       
     182                        handler(arg);
     183                       
     184                        irq_spinlock_lock(&CPU->timeoutlock, false);
    172185                }
    173                 spinlock_unlock(&CPU->timeoutlock);
     186               
     187                irq_spinlock_unlock(&CPU->timeoutlock, false);
    174188        }
    175189        CPU->missed_clock_ticks = 0;
    176 
     190       
    177191        /*
    178192         * Do CPU usage accounting and find out whether to preempt THREAD.
     193         *
    179194         */
    180 
     195       
    181196        if (THREAD) {
    182197                uint64_t ticks;
    183198               
    184                 spinlock_lock(&CPU->lock);
     199                irq_spinlock_lock(&CPU->lock, false);
    185200                CPU->needs_relink += 1 + missed_clock_ticks;
    186                 spinlock_unlock(&CPU->lock);   
    187        
    188                 spinlock_lock(&THREAD->lock);
     201                irq_spinlock_unlock(&CPU->lock, false);
     202               
     203                irq_spinlock_lock(&THREAD->lock, false);
    189204                if ((ticks = THREAD->ticks)) {
    190205                        if (ticks >= 1 + missed_clock_ticks)
     
    193208                                THREAD->ticks = 0;
    194209                }
    195                 spinlock_unlock(&THREAD->lock);
     210                irq_spinlock_unlock(&THREAD->lock, false);
    196211               
    197212                if ((!ticks) && (!PREEMPTION_DISABLED)) {
    198 #ifdef CONFIG_UDEBUG
    199                         istate_t *istate;
    200 #endif
    201213                        scheduler();
    202214#ifdef CONFIG_UDEBUG
     
    205217                         * before it begins executing userspace code.
    206218                         */
    207                         istate = THREAD->udebug.uspace_state;
    208                         if (istate && istate_from_uspace(istate))
     219                        istate_t *istate = THREAD->udebug.uspace_state;
     220                        if ((istate) && (istate_from_uspace(istate)))
    209221                                udebug_before_thread_runs();
    210222#endif
    211223                }
    212224        }
    213 
    214225}
    215226
Note: See TracChangeset for help on using the changeset viewer.