Ignore:
File:
1 edited

Legend:

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

    r98000fb 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.");
     
    8689        uptime->seconds1 = 0;
    8790        uptime->seconds2 = 0;
    88         uptime->useconds = 0; 
    89 
     91        uptime->useconds = 0;
     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 
     147       
     148        /* Account CPU usage */
     149        cpu_update_accounting();
     150       
    140151        /*
    141152         * To avoid lock ordering problems,
    142153         * run all expired timeouts as you visit them.
     154         *
    143155         */
     156        size_t i;
    144157        for (i = 0; i <= missed_clock_ticks; i++) {
     158                /* Update counters and accounting */
    145159                clock_update_counters();
    146                 spinlock_lock(&CPU->timeoutlock);
    147                 while ((l = CPU->timeout_active_head.next) != &CPU->timeout_active_head) {
    148                         h = list_get_instance(l, timeout_t, link);
    149                         spinlock_lock(&h->lock);
    150                         if (h->ticks-- != 0) {
    151                                 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);
    152171                                break;
    153172                        }
    154                         list_remove(l);
    155                         f = h->handler;
    156                         arg = h->arg;
    157                         timeout_reinitialize(h);
    158                         spinlock_unlock(&h->lock);     
    159                         spinlock_unlock(&CPU->timeoutlock);
    160 
    161                         f(arg);
    162 
    163                         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);
    164185                }
    165                 spinlock_unlock(&CPU->timeoutlock);
     186               
     187                irq_spinlock_unlock(&CPU->timeoutlock, false);
    166188        }
    167189        CPU->missed_clock_ticks = 0;
    168 
     190       
    169191        /*
    170192         * Do CPU usage accounting and find out whether to preempt THREAD.
     193         *
    171194         */
    172 
     195       
    173196        if (THREAD) {
    174197                uint64_t ticks;
    175198               
    176                 spinlock_lock(&CPU->lock);
     199                irq_spinlock_lock(&CPU->lock, false);
    177200                CPU->needs_relink += 1 + missed_clock_ticks;
    178                 spinlock_unlock(&CPU->lock);   
    179        
    180                 spinlock_lock(&THREAD->lock);
     201                irq_spinlock_unlock(&CPU->lock, false);
     202               
     203                irq_spinlock_lock(&THREAD->lock, false);
    181204                if ((ticks = THREAD->ticks)) {
    182205                        if (ticks >= 1 + missed_clock_ticks)
     
    185208                                THREAD->ticks = 0;
    186209                }
    187                 spinlock_unlock(&THREAD->lock);
    188                
    189                 if (!ticks && !PREEMPTION_DISABLED) {
    190 #ifdef CONFIG_UDEBUG
    191                         istate_t *istate;
    192 #endif
     210                irq_spinlock_unlock(&THREAD->lock, false);
     211               
     212                if ((!ticks) && (!PREEMPTION_DISABLED)) {
    193213                        scheduler();
    194214#ifdef CONFIG_UDEBUG
     
    197217                         * before it begins executing userspace code.
    198218                         */
    199                         istate = THREAD->udebug.uspace_state;
    200                         if (istate && istate_from_uspace(istate))
     219                        istate_t *istate = THREAD->udebug.uspace_state;
     220                        if ((istate) && (istate_from_uspace(istate)))
    201221                                udebug_before_thread_runs();
    202222#endif
    203223                }
    204224        }
    205 
    206225}
    207226
Note: See TracChangeset for help on using the changeset viewer.