Changeset da1bafb in mainline for kernel/generic/src/time


Ignore:
Timestamp:
2010-05-24T18:57:31Z (15 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0095368
Parents:
666f492
Message:

major code revision

  • replace spinlocks taken with interrupts disabled with irq_spinlocks
  • change spacing (not indendation) to be tab-size independent
  • use unsigned integer types where appropriate (especially bit flags)
  • visual separation
  • remove argument names in function prototypes
  • string changes
  • correct some formating directives
  • replace various cryptic single-character variables (t, a, m, c, b, etc.) with proper identifiers (thread, task, timeout, as, itm, itc, etc.)
  • unify some assembler constructs
  • unused page table levels are now optimized out in compile time
  • replace several ints (with boolean semantics) with bools
  • use specifically sized types instead of generic types where appropriate (size_t, uint32_t, btree_key_t)
  • improve comments
  • split asserts with conjuction into multiple independent asserts
Location:
kernel/generic/src/time
Files:
2 edited

Legend:

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

    r666f492 rda1bafb  
    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>
     
    6364static parea_t clock_parea;
    6465
    65 /* Variable holding fragment of second, so that we would update
    66  * seconds correctly
     66/** Fragment of second
     67 *
     68 * For updating  seconds correctly.
     69 *
    6770 */
    6871static unative_t secfrag = 0;
     
    7376 * information about realtime data. We allocate 1 page with these
    7477 * data and update it periodically.
     78 *
    7579 */
    7680void clock_counter_init(void)
    7781{
    78         void *faddr;
    79 
    80         faddr = frame_alloc(ONE_FRAME, FRAME_ATOMIC);
     82        void *faddr = frame_alloc(ONE_FRAME, FRAME_ATOMIC);
    8183        if (!faddr)
    8284                panic("Cannot allocate page for clock.");
     
    8789        uptime->seconds2 = 0;
    8890        uptime->useconds = 0;
    89 
     91       
    9092        clock_parea.pbase = (uintptr_t) faddr;
    9193        clock_parea.frames = 1;
    9294        ddi_parea_register(&clock_parea);
    93 
     95       
    9496        /*
    9597         * Prepare information for the userspace so that it can successfully
    9698         * physmem_map() the clock_parea.
     99         *
    97100         */
    98101        sysinfo_set_item_val("clock.cacheable", NULL, (unative_t) true);
     
    100103}
    101104
    102 
    103105/** Update public counters
    104106 *
    105107 * Update it only on first processor
    106  * TODO: Do we really need so many write barriers?
     108 * TODO: Do we really need so many write barriers?
     109 *
    107110 */
    108111static void clock_update_counters(void)
     
    131134void clock(void)
    132135{
    133         link_t *l;
    134         timeout_t *h;
    135         timeout_handler_t f;
    136         void *arg;
    137136        size_t missed_clock_ticks = CPU->missed_clock_ticks;
    138         unsigned int i;
    139 
     137       
    140138        /* Account lost ticks to CPU usage */
    141         if (CPU->idle) {
     139        if (CPU->idle)
    142140                CPU->idle_ticks += missed_clock_ticks + 1;
    143         } else {
     141        else
    144142                CPU->busy_ticks += missed_clock_ticks + 1;
    145         }
     143       
    146144        CPU->idle = false;
    147 
     145       
    148146        /*
    149147         * To avoid lock ordering problems,
    150148         * run all expired timeouts as you visit them.
     149         *
    151150         */
     151        size_t i;
    152152        for (i = 0; i <= missed_clock_ticks; i++) {
    153153                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);
     154                irq_spinlock_lock(&CPU->timeoutlock, false);
     155               
     156                link_t *cur;
     157                while ((cur = CPU->timeout_active_head.next) != &CPU->timeout_active_head) {
     158                        timeout_t *timeout = list_get_instance(cur, timeout_t, link);
     159                       
     160                        irq_spinlock_lock(&timeout->lock, false);
     161                        if (timeout->ticks-- != 0) {
     162                                irq_spinlock_unlock(&timeout->lock, false);
    160163                                break;
    161164                        }
    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);
     165                       
     166                        list_remove(cur);
     167                        timeout_handler_t handler = timeout->handler;
     168                        void *arg = timeout->arg;
     169                        timeout_reinitialize(timeout);
     170                       
     171                        irq_spinlock_unlock(&timeout->lock, false);
     172                        irq_spinlock_unlock(&CPU->timeoutlock, false);
     173                       
     174                        handler(arg);
     175                       
     176                        irq_spinlock_lock(&CPU->timeoutlock, false);
    172177                }
    173                 spinlock_unlock(&CPU->timeoutlock);
     178               
     179                irq_spinlock_unlock(&CPU->timeoutlock, false);
    174180        }
    175181        CPU->missed_clock_ticks = 0;
    176 
     182       
    177183        /*
    178184         * Do CPU usage accounting and find out whether to preempt THREAD.
     185         *
    179186         */
    180 
     187       
    181188        if (THREAD) {
    182189                uint64_t ticks;
    183190               
    184                 spinlock_lock(&CPU->lock);
     191                irq_spinlock_lock(&CPU->lock, false);
    185192                CPU->needs_relink += 1 + missed_clock_ticks;
    186                 spinlock_unlock(&CPU->lock);   
    187        
    188                 spinlock_lock(&THREAD->lock);
     193                irq_spinlock_unlock(&CPU->lock, false);
     194               
     195                irq_spinlock_lock(&THREAD->lock, false);
    189196                if ((ticks = THREAD->ticks)) {
    190197                        if (ticks >= 1 + missed_clock_ticks)
     
    193200                                THREAD->ticks = 0;
    194201                }
    195                 spinlock_unlock(&THREAD->lock);
     202                irq_spinlock_unlock(&THREAD->lock, false);
    196203               
    197204                if ((!ticks) && (!PREEMPTION_DISABLED)) {
    198 #ifdef CONFIG_UDEBUG
    199                         istate_t *istate;
    200 #endif
    201205                        scheduler();
    202206#ifdef CONFIG_UDEBUG
     
    205209                         * before it begins executing userspace code.
    206210                         */
    207                         istate = THREAD->udebug.uspace_state;
    208                         if (istate && istate_from_uspace(istate))
     211                        istate_t *istate = THREAD->udebug.uspace_state;
     212                        if ((istate) && (istate_from_uspace(istate)))
    209213                                udebug_before_thread_runs();
    210214#endif
    211215                }
    212216        }
    213 
    214217}
    215218
  • kernel/generic/src/time/timeout.c

    r666f492 rda1bafb  
    3333/**
    3434 * @file
    35  * @brief               Timeout management functions.
     35 * @brief Timeout management functions.
    3636 */
    3737
     
    5353void timeout_init(void)
    5454{
    55         spinlock_initialize(&CPU->timeoutlock, "timeout_lock");
     55        irq_spinlock_initialize(&CPU->timeoutlock, "cpu.timeoutlock");
    5656        list_initialize(&CPU->timeout_active_head);
    5757}
    5858
    59 
    60 /** Reinitialize timeout
     59/** Reinitialize timeout
    6160 *
    6261 * Initialize all members except the lock.
    6362 *
    64  * @param t             Timeout to be initialized.
    65  *
    66  */
    67 void timeout_reinitialize(timeout_t *t)
    68 {
    69         t->cpu = NULL;
    70         t->ticks = 0;
    71         t->handler = NULL;
    72         t->arg = NULL;
    73         link_initialize(&t->link);
    74 }
    75 
     63 * @param timeout Timeout to be initialized.
     64 *
     65 */
     66void timeout_reinitialize(timeout_t *timeout)
     67{
     68        timeout->cpu = NULL;
     69        timeout->ticks = 0;
     70        timeout->handler = NULL;
     71        timeout->arg = NULL;
     72        link_initialize(&timeout->link);
     73}
    7674
    7775/** Initialize timeout
     
    7977 * Initialize all members including the lock.
    8078 *
    81  * @param t             Timeout to be initialized.
    82  *
    83  */
    84 void timeout_initialize(timeout_t *t)
    85 {
    86         spinlock_initialize(&t->lock, "timeout_t_lock");
    87         timeout_reinitialize(t);
    88 }
    89 
     79 * @param timeout Timeout to be initialized.
     80 *
     81 */
     82void timeout_initialize(timeout_t *timeout)
     83{
     84        irq_spinlock_initialize(&timeout->lock, "timeout_t_lock");
     85        timeout_reinitialize(timeout);
     86}
    9087
    9188/** Register timeout
     
    9592 * time microseconds (or slightly more).
    9693 *
    97  * @param t             Timeout structure.
    98  * @param time          Number of usec in the future to execute the handler.
    99  * @param f             Timeout handler function.
    100  * @param arg           Timeout handler argument.
    101  *
    102  */
    103 void
    104 timeout_register(timeout_t *t, uint64_t time, timeout_handler_t f, void *arg)
    105 {
    106         timeout_t *hlp = NULL;
    107         link_t *l, *m;
    108         ipl_t ipl;
    109         uint64_t sum;
    110 
    111         ipl = interrupts_disable();
    112         spinlock_lock(&CPU->timeoutlock);
    113         spinlock_lock(&t->lock);
    114 
    115         if (t->cpu)
    116                 panic("Unexpected: t->cpu != 0.");
    117 
    118         t->cpu = CPU;
    119         t->ticks = us2ticks(time);
    120        
    121         t->handler = f;
    122         t->arg = arg;
    123 
    124         /*
    125          * Insert t into the active timeouts list according to t->ticks.
    126          */
    127         sum = 0;
    128         l = CPU->timeout_active_head.next;
    129         while (l != &CPU->timeout_active_head) {
    130                 hlp = list_get_instance(l, timeout_t, link);
    131                 spinlock_lock(&hlp->lock);
    132                 if (t->ticks < sum + hlp->ticks) {
    133                         spinlock_unlock(&hlp->lock);
     94 * @param timeout Timeout structure.
     95 * @param time    Number of usec in the future to execute the handler.
     96 * @param handler Timeout handler function.
     97 * @param arg     Timeout handler argument.
     98 *
     99 */
     100void timeout_register(timeout_t *timeout, uint64_t time,
     101    timeout_handler_t handler, void *arg)
     102{
     103        irq_spinlock_lock(&CPU->timeoutlock, true);
     104        irq_spinlock_lock(&timeout->lock, false);
     105       
     106        if (timeout->cpu)
     107                panic("Unexpected: timeout->cpu != 0.");
     108       
     109        timeout->cpu = CPU;
     110        timeout->ticks = us2ticks(time);
     111       
     112        timeout->handler = handler;
     113        timeout->arg = arg;
     114       
     115        /*
     116         * Insert timeout into the active timeouts list according to timeout->ticks.
     117         */
     118        uint64_t sum = 0;
     119        timeout_t *target = NULL;
     120        link_t *cur;
     121        for (cur = CPU->timeout_active_head.next;
     122            cur != &CPU->timeout_active_head; cur = cur->next) {
     123                target = list_get_instance(cur, timeout_t, link);
     124                irq_spinlock_lock(&target->lock, false);
     125               
     126                if (timeout->ticks < sum + target->ticks) {
     127                        irq_spinlock_unlock(&target->lock, false);
    134128                        break;
    135129                }
    136                 sum += hlp->ticks;
    137                 spinlock_unlock(&hlp->lock);
    138                 l = l->next;
    139         }
    140 
    141         m = l->prev;
    142         list_prepend(&t->link, m); /* avoid using l->prev */
    143 
    144         /*
    145          * Adjust t->ticks according to ticks accumulated in h's predecessors.
    146          */
    147         t->ticks -= sum;
    148 
    149         /*
    150          * Decrease ticks of t's immediate succesor by t->ticks.
    151          */
    152         if (l != &CPU->timeout_active_head) {
    153                 spinlock_lock(&hlp->lock);
    154                 hlp->ticks -= t->ticks;
    155                 spinlock_unlock(&hlp->lock);
    156         }
    157 
    158         spinlock_unlock(&t->lock);
    159         spinlock_unlock(&CPU->timeoutlock);
    160         interrupts_restore(ipl);
    161 }
    162 
     130               
     131                sum += target->ticks;
     132                irq_spinlock_unlock(&target->lock, false);
     133        }
     134       
     135        /* Avoid using cur->prev directly */
     136        link_t *prev = cur->prev;
     137        list_prepend(&timeout->link, prev);
     138       
     139        /*
     140         * Adjust timeout->ticks according to ticks
     141         * accumulated in target's predecessors.
     142         */
     143        timeout->ticks -= sum;
     144       
     145        /*
     146         * Decrease ticks of timeout's immediate succesor by timeout->ticks.
     147         */
     148        if (cur != &CPU->timeout_active_head) {
     149                irq_spinlock_lock(&target->lock, false);
     150                target->ticks -= timeout->ticks;
     151                irq_spinlock_unlock(&target->lock, false);
     152        }
     153       
     154        irq_spinlock_unlock(&timeout->lock, false);
     155        irq_spinlock_unlock(&CPU->timeoutlock, true);
     156}
    163157
    164158/** Unregister timeout
     
    166160 * Remove timeout from timeout list.
    167161 *
    168  * @param t             Timeout to unregister.
    169  *
    170  * @return              True on success, false on failure.
    171  */
    172 bool timeout_unregister(timeout_t *t)
    173 {
    174         timeout_t *hlp;
    175         link_t *l;
    176         ipl_t ipl;
     162 * @param timeout Timeout to unregister.
     163 *
     164 * @return True on success, false on failure.
     165 *
     166 */
     167bool timeout_unregister(timeout_t *timeout)
     168{
    177169        DEADLOCK_PROBE_INIT(p_tolock);
    178 
     170       
    179171grab_locks:
    180         ipl = interrupts_disable();
    181         spinlock_lock(&t->lock);
    182         if (!t->cpu) {
    183                 spinlock_unlock(&t->lock);
    184                 interrupts_restore(ipl);
     172        irq_spinlock_lock(&timeout->lock, true);
     173        if (!timeout->cpu) {
     174                irq_spinlock_unlock(&timeout->lock, true);
    185175                return false;
    186176        }
    187         if (!spinlock_trylock(&t->cpu->timeoutlock)) {
    188                 spinlock_unlock(&t->lock);
    189                 interrupts_restore(ipl);
     177       
     178        if (!irq_spinlock_trylock(&timeout->cpu->timeoutlock)) {
     179                irq_spinlock_unlock(&timeout->lock, true);
    190180                DEADLOCK_PROBE(p_tolock, DEADLOCK_THRESHOLD);
    191181                goto grab_locks;
     
    193183       
    194184        /*
    195          * Now we know for sure that t hasn't been activated yet
    196          * and is lurking in t->cpu->timeout_active_head queue.
    197          */
    198 
    199         l = t->link.next;
    200         if (l != &t->cpu->timeout_active_head) {
    201                 hlp = list_get_instance(l, timeout_t, link);
    202                 spinlock_lock(&hlp->lock);
    203                 hlp->ticks += t->ticks;
    204                 spinlock_unlock(&hlp->lock);
    205         }
    206        
    207         list_remove(&t->link);
    208         spinlock_unlock(&t->cpu->timeoutlock);
    209 
    210         timeout_reinitialize(t);
    211         spinlock_unlock(&t->lock);
    212 
    213         interrupts_restore(ipl);
     185         * Now we know for sure that timeout hasn't been activated yet
     186         * and is lurking in timeout->cpu->timeout_active_head queue.
     187         */
     188       
     189        link_t *cur = timeout->link.next;
     190        if (cur != &timeout->cpu->timeout_active_head) {
     191                timeout_t *tmp = list_get_instance(cur, timeout_t, link);
     192                irq_spinlock_lock(&tmp->lock, false);
     193                tmp->ticks += timeout->ticks;
     194                irq_spinlock_unlock(&tmp->lock, false);
     195        }
     196       
     197        list_remove(&timeout->link);
     198        irq_spinlock_unlock(&timeout->cpu->timeoutlock, false);
     199       
     200        timeout_reinitialize(timeout);
     201        irq_spinlock_unlock(&timeout->lock, true);
     202       
    214203        return true;
    215204}
Note: See TracChangeset for help on using the changeset viewer.