Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 712c4ba in mainline


Ignore:
Timestamp:
2011-05-20T16:09:24Z (11 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master
Children:
b6f3e7e
Parents:
326bf65
Message:

avoid spinlocks to be taken in the direct code path to physically outputing kconsole characters to the framebuffer (this fixes ticket #243)
the spinlock in printf() (kernel) was sacrificed, this might lead potentially to scrambled kconsole output
the hack of ignoring spinlocks whose names start with "*" in the livelock detector can be removed

Location:
kernel
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • kernel/genarch/src/drivers/ega/ega.c

    r326bf65 r712c4ba  
    4040#include <mm/as.h>
    4141#include <mm/slab.h>
     42#include <synch/mutex.h>
    4243#include <arch/mm/page.h>
    43 #include <synch/spinlock.h>
    4444#include <typedefs.h>
    4545#include <arch/asm.h>
     
    6363
    6464typedef struct {
    65         IRQ_SPINLOCK_DECLARE(lock);
     65        mutex_t mtx;
    6666       
    6767        uint32_t cursor;
     
    540540        ega_instance_t *instance = (ega_instance_t *) dev->data;
    541541       
    542         irq_spinlock_lock(&instance->lock, true);
     542        mutex_lock(&instance->mtx);
    543543       
    544544        switch (ch) {
     
    563563        ega_move_cursor(instance, silent);
    564564       
    565         irq_spinlock_unlock(&instance->lock, true);
     565        mutex_unlock(&instance->mtx);
    566566}
    567567
     
    570570        ega_instance_t *instance = (ega_instance_t *) dev->data;
    571571       
    572         irq_spinlock_lock(&instance->lock, true);
     572        mutex_lock(&instance->mtx);
    573573       
    574574        memcpy(instance->addr, instance->backbuf, EGA_VRAM_SIZE);
     
    576576        ega_show_cursor(instance, silent);
    577577       
    578         irq_spinlock_unlock(&instance->lock, true);
     578        mutex_unlock(&instance->mtx);
    579579}
    580580
     
    594594        egadev->data = instance;
    595595       
    596         irq_spinlock_initialize(&instance->lock, "*ega.instance.lock");
     596        mutex_initialize(&instance->mtx, MUTEX_PASSIVE);
    597597       
    598598        instance->base = base;
  • kernel/genarch/src/fb/fb.c

    r326bf65 r712c4ba  
    8080
    8181typedef struct {
    82         SPINLOCK_DECLARE(lock);
     82        mutex_t mtx;
    8383       
    8484        uint8_t *addr;
     
    365365{
    366366        fb_instance_t *instance = (fb_instance_t *) dev->data;
    367         spinlock_lock(&instance->lock);
     367        mutex_lock(&instance->mtx);
    368368       
    369369        switch (ch) {
     
    406406        cursor_put(instance, silent);
    407407       
    408         spinlock_unlock(&instance->lock);
     408        mutex_unlock(&instance->mtx);
    409409}
    410410
     
    473473        fb_instance_t *instance = (fb_instance_t *) dev->data;
    474474       
    475         spinlock_lock(&instance->lock);
     475        mutex_lock(&instance->mtx);
    476476        fb_redraw_internal(instance);
    477         spinlock_unlock(&instance->lock);
     477        mutex_unlock(&instance->mtx);
    478478}
    479479
     
    554554        fbdev->data = instance;
    555555       
    556         spinlock_initialize(&instance->lock, "*fb.instance.lock");
     556        mutex_initialize(&instance->mtx, MUTEX_PASSIVE);
    557557        instance->rgb_conv = rgb_conv;
    558558        instance->pixelbytes = pixelbytes;
  • kernel/generic/src/console/console.c

    r326bf65 r712c4ba  
    6060
    6161/** Kernel log initialized */
    62 static bool klog_inited = false;
     62static atomic_t klog_inited = {false};
    6363
    6464/** First kernel log characters */
     
    7575
    7676/** Kernel log spinlock */
    77 SPINLOCK_STATIC_INITIALIZE_NAME(klog_lock, "*klog_lock");
     77SPINLOCK_STATIC_INITIALIZE_NAME(klog_lock, "klog_lock");
    7878
    7979/** Physical memory area used for klog buffer */
     
    166166       
    167167        event_set_unmask_callback(EVENT_KLOG, klog_update);
    168        
    169         spinlock_lock(&klog_lock);
    170         klog_inited = true;
    171         spinlock_unlock(&klog_lock);
     168        atomic_set(&klog_inited, true);
    172169}
    173170
     
    264261void klog_update(void)
    265262{
     263        if (!atomic_get(&klog_inited))
     264                return;
     265       
    266266        spinlock_lock(&klog_lock);
    267267       
    268         if ((klog_inited) && (klog_uspace > 0)) {
     268        if (klog_uspace > 0) {
    269269                if (event_notify_3(EVENT_KLOG, true, klog_start, klog_len,
    270270                    klog_uspace) == EOK)
     
    277277void putchar(const wchar_t ch)
    278278{
     279        bool ordy = ((stdout) && (stdout->op->write));
     280       
    279281        spinlock_lock(&klog_lock);
    280282       
    281         if ((klog_stored > 0) && (stdout) && (stdout->op->write)) {
    282                 /* Print charaters stored in kernel log */
    283                 size_t i;
    284                 for (i = klog_len - klog_stored; i < klog_len; i++)
    285                         stdout->op->write(stdout, klog[(klog_start + i) % KLOG_LENGTH], silent);
    286                 klog_stored = 0;
     283        /* Print charaters stored in kernel log */
     284        if (ordy) {
     285                while (klog_stored > 0) {
     286                        wchar_t tmp = klog[(klog_start + klog_len - klog_stored) % KLOG_LENGTH];
     287                        klog_stored--;
     288                       
     289                        /*
     290                         * We need to give up the spinlock for
     291                         * the physical operation of writting out
     292                         * the character.
     293                         */
     294                        spinlock_unlock(&klog_lock);
     295                        stdout->op->write(stdout, tmp, silent);
     296                        spinlock_lock(&klog_lock);
     297                }
    287298        }
    288299       
     
    294305                klog_start = (klog_start + 1) % KLOG_LENGTH;
    295306       
    296         if ((stdout) && (stdout->op->write))
     307        if (!ordy) {
     308                if (klog_stored < klog_len)
     309                        klog_stored++;
     310        }
     311       
     312        /* The character is stored for uspace */
     313        if (klog_uspace < klog_len)
     314                klog_uspace++;
     315       
     316        spinlock_unlock(&klog_lock);
     317       
     318        if (ordy) {
     319                /*
     320                 * Output the character. In this case
     321                 * it should be no longer buffered.
     322                 */
    297323                stdout->op->write(stdout, ch, silent);
    298         else {
     324        } else {
    299325                /*
    300326                 * No standard output routine defined yet.
     
    306332                 * Note that the early_putc() function might be
    307333                 * a no-op on certain hardware configurations.
    308                  *
    309334                 */
    310335                early_putchar(ch);
    311                
    312                 if (klog_stored < klog_len)
    313                         klog_stored++;
    314         }
    315        
    316         /* The character is stored for uspace */
    317         if (klog_uspace < klog_len)
    318                 klog_uspace++;
    319        
    320         spinlock_unlock(&klog_lock);
     336        }
    321337       
    322338        /* Force notification on newline */
  • kernel/generic/src/printf/vprintf.c

    r326bf65 r712c4ba  
    4141#include <typedefs.h>
    4242#include <str.h>
    43 
    44 IRQ_SPINLOCK_STATIC_INITIALIZE_NAME(printf_lock, "*printf_lock");
    4543
    4644static int vprintf_str_write(const char *str, size_t size, void *data)
     
    9391        };
    9492       
    95         irq_spinlock_lock(&printf_lock, true);
    96         int ret = printf_core(fmt, &ps, ap);
    97         irq_spinlock_unlock(&printf_lock, true);
    98        
    99         return ret;
     93        return printf_core(fmt, &ps, ap);
    10094}
    10195
  • kernel/generic/src/synch/spinlock.c

    r326bf65 r712c4ba  
    8484                 * This conserns especially printf_lock and the
    8585                 * framebuffer lock.
    86                  *
    87                  * Any lock whose name is prefixed by "*" will be
    88                  * ignored by this deadlock detection routine
    89                  * as this might cause an infinite recursion.
    90                  * We trust our code that there is no possible deadlock
    91                  * caused by these locks (except when an exception
    92                  * is triggered for instance by printf()).
    93                  *
    94                  * We encountered false positives caused by very
    95                  * slow framebuffer interaction (especially when
    96                  * run in a simulator) that caused problems with both
    97                  * printf_lock and the framebuffer lock.
    98                  *
    9986                 */
    100                 if (lock->name[0] == '*')
    101                         continue;
    102                
    10387                if (i++ > DEADLOCK_THRESHOLD) {
    10488                        printf("cpu%u: looping on spinlock %p:%s, "
Note: See TracChangeset for help on using the changeset viewer.