Changeset 6b54dcb in rtems for c/src/lib/libbsp/i386


Ignore:
Timestamp:
Oct 12, 2016, 7:40:41 AM (3 years ago)
Author:
Pavel Pisa <pisa@…>
Branches:
master
Children:
20625a5
Parents:
f45ddee
git-author:
Pavel Pisa <pisa@…> (10/12/16 07:40:41)
git-committer:
Pavel Pisa <pisa@…> (10/17/16 07:41:58)
Message:

bsps/i386: replace global interrupt disable by SMP build supporting locking.

Location:
c/src/lib/libbsp/i386
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/i386/pc386/clock/ckinit.c

    rf45ddee r6b54dcb  
    8585  uint32_t                 irqs;
    8686  uint8_t                  lsb, msb;
    87   rtems_interrupt_level    level;
     87  rtems_interrupt_lock_context lock_context;
    8888
    8989  /*
    9090   * Fetch all the data in an interrupt critical section.
    9191   */
    92   rtems_interrupt_disable(level);
     92
     93  rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
     94
    9395    READ_8254(lsb, msb);
    9496    irqs = Clock_driver_ticks;
    95   rtems_interrupt_enable(level);
     97
     98  rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
    9699
    97100  return (irqs + 1) * pc386_microseconds_per_isr - ((msb << 8) | lsb);
     
    142145static void clockOn(void)
    143146{
     147  rtems_interrupt_lock_context lock_context;
    144148  pc386_isrs_per_tick        = 1;
    145149  pc386_microseconds_per_isr = rtems_configuration_get_microseconds_per_tick();
     
    150154  }
    151155  pc386_clock_click_count = US_TO_TICK(pc386_microseconds_per_isr);
    152 
    153   bsp_interrupt_vector_enable( BSP_PERIODIC_TIMER - BSP_IRQ_VECTOR_BASE );
    154156
    155157  #if 0
     
    161163  #endif
    162164
     165  rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
    163166  outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
    164167  outport_byte(TIMER_CNTR0, pc386_clock_click_count >> 0 & 0xff);
    165168  outport_byte(TIMER_CNTR0, pc386_clock_click_count >> 8 & 0xff);
     169  rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
     170
     171  bsp_interrupt_vector_enable( BSP_PERIODIC_TIMER - BSP_IRQ_VECTOR_BASE );
    166172
    167173  /*
     
    175181static void clockOff(void)
    176182{
     183  rtems_interrupt_lock_context lock_context;
     184  rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
    177185  /* reset timer mode to standard (BIOS) value */
    178186  outport_byte(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN);
    179187  outport_byte(TIMER_CNTR0, 0);
    180188  outport_byte(TIMER_CNTR0, 0);
     189  rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
    181190} /* Clock_exit */
    182191
  • c/src/lib/libbsp/i386/pc386/console/inch.c

    rf45ddee r6b54dcb  
    261261{
    262262  int                    rc;
    263   rtems_interrupt_level level;
    264 
    265   rtems_interrupt_disable(level);
     263
     264  /*
     265   * The locking or disable of interrupts does not help
     266   * there because if interrupts are enabled after leave of this
     267   * function the state can change without notice anyway.
     268   */
     269  RTEMS_COMPILER_MEMORY_BARRIER();
    266270
    267271  rc = ( kbd_first != kbd_last ) ? TRUE : FALSE;
    268272
    269   rtems_interrupt_enable(level);
     273  RTEMS_COMPILER_MEMORY_BARRIER();
    270274
    271275  return rc;
  • c/src/lib/libbsp/i386/pc386/console/keyboard.c

    rf45ddee r6b54dcb  
    1010#include <bsp.h>
    1111#include <bsp/bootcard.h>
     12#include <stdatomic.h>
    1213
    1314#define SIZE(x) (sizeof(x)/sizeof((x)[0]))
     
    2930#endif
    3031
    31 static int set_bit(int nr, unsigned long * addr)
    32 {
    33   int                   mask;
     32static int kbd_test_and_set_bit(int nr, atomic_uint_least32_t * addr)
     33{
     34  uint_least32_t        mask;
    3435  int                   retval;
    35   rtems_interrupt_level level;
     36
     37  addr += nr >> 5;
     38  mask = 1UL << (nr & 0x1f);
     39
     40  retval = (atomic_fetch_or(addr, mask) & mask) != 0;
     41
     42  return retval;
     43}
     44
     45static int kbd_test_and_clear_bit(int nr, atomic_uint_least32_t * addr)
     46{
     47  uint_least32_t        mask;
     48  int                   retval;
     49
     50  addr += nr >> 5;
     51  mask = 1UL << (nr & 0x1f);
     52
     53  retval = (atomic_fetch_and(addr, ~mask) & mask) != 0;
     54
     55  return retval;
     56}
     57
     58static int kbd_test_bit(int nr, atomic_uint_least32_t * addr)
     59{
     60  unsigned long  mask;
    3661
    3762  addr += nr >> 5;
    3863  mask = 1 << (nr & 0x1f);
    39   rtems_interrupt_disable(level);
    40     retval = (mask & *addr) != 0;
    41     *addr |= mask;
    42   rtems_interrupt_enable(level);
    43   return retval;
    44 }
    45 
    46 static int clear_bit(int nr, unsigned long * addr)
    47 {
    48   int                   mask;
    49   int                   retval;
    50   rtems_interrupt_level level;
    51 
    52   addr += nr >> 5;
    53   mask = 1 << (nr & 0x1f);
    54   rtems_interrupt_disable(level);
    55     retval = (mask & *addr) != 0;
    56     *addr &= ~mask;
    57   rtems_interrupt_enable(level);
    58   return retval;
    59 }
    60 
    61 static int test_bit(int nr, unsigned long * addr)
    62 {
    63   int  mask;
    64 
    65   addr += nr >> 5;
    66   mask = 1 << (nr & 0x1f);
    67   return ((mask & *addr) != 0);
    68 }
    69 
    70 #define  test_and_set_bit(x,y)      set_bit(x,y)
    71 #define  test_and_clear_bit(x,y)    clear_bit(x,y)
     64  return ((mask & atomic_load(addr)) != 0);
     65}
    7266
    7367/*
     
    7670 * (last_console is now a global variable)
    7771 */
    78 #define  BITS_PER_LONG (sizeof(long)*CHAR_BIT)
     72#define  KBD_BITS_PER_ELEMENT (sizeof(atomic_uint_least32_t)*CHAR_BIT)
    7973
    8074/* shift state counters.. */
    8175static unsigned char k_down[NR_SHIFT] = {0, };
    8276/* keyboard key bitmap */
    83 static unsigned long key_down[256/BITS_PER_LONG] = { 0, };
     77static atomic_uint_least32_t
     78  key_down[(256 + KBD_BITS_PER_ELEMENT - 1) / KBD_BITS_PER_ELEMENT] = { 0, };
    8479
    8580static int dead_key_next = 0;
     
    244239  if (up_flag) {
    245240    rep = 0;
    246     if(!test_and_clear_bit(keycode, key_down))
     241    if(!kbd_test_and_clear_bit(keycode, key_down))
    247242        up_flag = kbd_unexpected_up(keycode);
    248243  } else
    249     rep = test_and_set_bit(keycode, key_down);
     244    rep = kbd_test_and_set_bit(keycode, key_down);
    250245
    251246#ifdef CONFIG_MAGIC_SYSRQ    /* Handle the SysRq Hack */
     
    696691
    697692  for(i=0; i < SIZE(key_down); i++)
    698     if(key_down[i]) {  /* skip this word if not a single bit on */
    699       k = i*BITS_PER_LONG;
    700       for(j=0; j<BITS_PER_LONG; j++,k++)
    701         if(test_bit(k, key_down)) {
     693    if(atomic_load(key_down + i)) {  /* skip this word if not a single bit on */
     694      k = i*KBD_BITS_PER_ELEMENT;
     695      for(j=0; j<KBD_BITS_PER_ELEMENT; j++,k++)
     696        if(kbd_test_bit(k, key_down)) {
    702697    sym = U(plain_map[k]);
    703698    if(KTYP(sym) == KT_SHIFT) {
  • c/src/lib/libbsp/i386/pc386/console/vt.c

    rf45ddee r6b54dcb  
    1919#include <errno.h>
    2020
     21#include <bsp.h>
    2122#include <i386_io.h>
    2223#include <rtems.h>
     
    7071{
    7172  unsigned int          count = 0;
    72   rtems_interrupt_level level;
     73  rtems_interrupt_lock_context lock_context;
    7374
    7475  if (hz > 20 && hz < 32767)
    7576    count = 1193180 / hz;
    7677
    77    rtems_interrupt_disable(level);
     78  rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
    7879/*  del_timer(&sound_timer);  */
    7980  if (count) {
     
    8182    outb_p(inb_p(0x61)|3, 0x61);
    8283    /* set command for counter 2, 2 byte write */
    83     outb_p(0xB6, 0x43);
     84    outb_p(0xB6, TIMER_MODE);
    8485    /* select desired HZ */
    85     outb_p(count & 0xff, 0x42);
    86     outb((count >> 8) & 0xff, 0x42);
     86    outb_p(count & 0xff, TIMER_CNTR2);
     87    outb((count >> 8) & 0xff, TIMER_CNTR2);
    8788
    8889/*
     
    9596    kd_nosound(0);
    9697
    97    rtems_interrupt_enable(level);
     98  rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
    9899  return;
    99100}
  • c/src/lib/libbsp/i386/pc386/include/bsp.h

    rf45ddee r6b54dcb  
    147147#define TIMER_TICK     1193182  /* The internal tick rate in ticks per second */
    148148
     149#if defined( RTEMS_SMP )
     150  extern ISR_lock_Control rtems_i386_i8254_access_lock;
     151#endif
     152
     153
    149154/*-------------------------------------------------------------------------+
    150155| Console Defines
  • c/src/lib/libbsp/i386/pc386/timer/timer.c

    rf45ddee r6b54dcb  
    4545#define CMD_READ_BACK_STATUS 0xE2   /* command read back status */
    4646
     47RTEMS_INTERRUPT_LOCK_DEFINE( /* visible global variable */ ,
     48   rtems_i386_i8254_access_lock, "rtems_i386_i8254_access_lock" );
     49
    4750/*
    4851 * Global Variables
     
    116119static void timerOff(const rtems_raw_irq_connect_data* used)
    117120{
     121  rtems_interrupt_lock_context lock_context;
    118122  /*
    119123   * disable interrrupt at i8259 level
    120124   */
    121    bsp_interrupt_vector_disable(used->idtIndex - BSP_IRQ_VECTOR_BASE);
     125  bsp_interrupt_vector_disable(used->idtIndex - BSP_IRQ_VECTOR_BASE);
     126
     127  rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
     128
    122129   /* reset timer mode to standard (DOS) value */
    123    outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
    124    outport_byte(TIMER_CNTR0, 0);
    125    outport_byte(TIMER_CNTR0, 0);
     130  outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
     131  outport_byte(TIMER_CNTR0, 0);
     132  outport_byte(TIMER_CNTR0, 0);
     133
     134  rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
    126135}
    127136
    128137static void timerOn(const rtems_raw_irq_connect_data* used)
    129138{
     139  rtems_interrupt_lock_context lock_context;
     140
     141  rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
     142
    130143  /* load timer for US_PER_ISR microsecond period */
    131144  outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
    132145  outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 0 & 0xff);
    133146  outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 8 & 0xff);
     147
     148  rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
    134149
    135150  /*
     
    200215  register uint32_t         total, clicks;
    201216  register uint8_t          lsb, msb;
    202 
     217  rtems_interrupt_lock_context lock_context;
     218
     219  rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
    203220  outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH);
    204221  inport_byte(TIMER_CNTR0, lsb);
    205222  inport_byte(TIMER_CNTR0, msb);
     223  rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
     224
    206225  clicks = (msb << 8) | lsb;
    207226  total  = (Ttimer_val * US_PER_ISR) + (US_PER_ISR - TICK_TO_US(clicks));
     
    274293static void loadTimerValue( unsigned short loadedValue )
    275294{
     295  rtems_interrupt_lock_context lock_context;
     296  rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
    276297  lastLoadedValue = loadedValue;
    277298  outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_SQWAVE);
    278299  outport_byte(TIMER_CNTR0, loadedValue & 0xff);
    279300  outport_byte(TIMER_CNTR0, (loadedValue >> 8) & 0xff);
     301  rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
    280302}
    281303
     
    291313  unsigned char  status;
    292314  unsigned int  count;
     315  rtems_interrupt_lock_context lock_context;
     316  rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
    293317
    294318  outport_byte(
     
    299323  inport_byte(TIMER_CNTR0, lsb);
    300324  inport_byte(TIMER_CNTR0, msb);
     325
     326  rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
     327
    301328  count = ( msb << 8 ) | lsb ;
    302329  if (status & RB_OUTPUT )
     
    338365  int retries = 0;
    339366
    340   rtems_interrupt_disable(level);
     367  /*
     368   * This code is designed to run before interrupt management
     369   * is enabled and running it on multiple CPUs and or after
     370   * secondary CPUs are bring up seems really broken.
     371   * Disabling of local interrupts is enough.
     372   */
     373  rtems_interrupt_local_disable(level);
    341374
    342375retry:
     
    507540  printk("slowLoop1ms = %u, fastLoop1ms = %u\n", slowLoop1ms, fastLoop1ms);
    508541#endif
    509   rtems_interrupt_enable(level);
     542  rtems_interrupt_local_enable(level);
    510543
    511544}
  • c/src/lib/libbsp/i386/shared/irq/idt.c

    rf45ddee r6b54dcb  
    2020#include <bsp/irq.h>
    2121
     22/*
     23 * This locking is not enough if IDT is changed at runtime
     24 * and entry can be changed for vector which is enabled
     25 * at change time. But such use is broken anyway.
     26 * Protect code only against concurrent changes.
     27 * Even that is probably unnecessary if different
     28 * entries are changed concurrently.
     29 */
     30RTEMS_INTERRUPT_LOCK_DEFINE( static, rtems_idt_access_lock, "rtems_idt_access_lock" );
     31
    2232static rtems_raw_irq_connect_data*      raw_irq_table;
    2333static rtems_raw_irq_connect_data       default_raw_irq_entry;
     
    6171    interrupt_gate_descriptor*  idt_entry_tbl;
    6272    unsigned                    limit;
    63     rtems_interrupt_level       level;
     73    rtems_interrupt_lock_context lock_context;
    6474
    6575    i386_get_info_from_IDTR (&idt_entry_tbl, &limit);
     
    8292    }
    8393
    84     rtems_interrupt_disable(level);
     94    rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context);
    8595
    8696    raw_irq_table [irq->idtIndex] = *irq;
     
    8999      irq->on(irq);
    90100
    91     rtems_interrupt_enable(level);
     101    rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context);
    92102    return 1;
    93103}
     
    100110    unsigned                    limit;
    101111    interrupt_gate_descriptor   new;
    102     rtems_interrupt_level       level;
     112    rtems_interrupt_lock_context lock_context;
    103113
    104114    i386_get_info_from_IDTR (&idt_entry_tbl, &limit);
     
    110120      return;
    111121    }
    112     rtems_interrupt_disable(level);
     122    rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context);
    113123    * ((unsigned int *) oldHdl) = idt_entry_tbl[vector].low_offsets_bits |
    114124        (idt_entry_tbl[vector].high_offsets_bits << 16);
     
    117127    idt_entry_tbl[vector] = new;
    118128
    119     rtems_interrupt_enable(level);
     129    rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context);
    120130}
    121131
     
    144154    interrupt_gate_descriptor*  idt_entry_tbl;
    145155    unsigned                    limit;
    146     rtems_interrupt_level       level;
     156    rtems_interrupt_lock_context lock_context;
    147157
    148158    i386_get_info_from_IDTR (&idt_entry_tbl, &limit);
     
    164174      return 0;
    165175    }
    166     rtems_interrupt_disable(level);
     176    rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context);
    167177
    168178    idt_entry_tbl[irq->idtIndex] = default_idt_entry;
     
    174184    raw_irq_table[irq->idtIndex].idtIndex = irq->idtIndex;
    175185
    176     rtems_interrupt_enable(level);
     186    rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context);
    177187
    178188    return 1;
     
    186196    unsigned                    limit;
    187197    unsigned                    i;
    188     rtems_interrupt_level       level;
     198    rtems_interrupt_lock_context lock_context;
    189199    interrupt_gate_descriptor*  idt_entry_tbl;
    190200
     
    204214    default_raw_irq_entry       = config->defaultRawEntry;
    205215
    206     rtems_interrupt_disable(level);
     216    rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context);
    207217
    208218    create_interrupt_gate_descriptor (&default_idt_entry, default_raw_irq_entry.hdl);
     
    219229      }
    220230    }
    221     rtems_interrupt_enable(level);
     231    rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context);
    222232
    223233    return 1;
  • c/src/lib/libbsp/i386/shared/irq/irq.c

    rf45ddee r6b54dcb  
    2323
    2424#include "elcr.h"
     25
     26RTEMS_INTERRUPT_LOCK_DEFINE( static, rtems_i8259_access_lock, "rtems_i8259_access_lock" );
    2527
    2628/*
     
    131133{
    132134  unsigned short        mask;
    133   rtems_interrupt_level level;
    134 
    135   rtems_interrupt_disable(level);
     135  rtems_interrupt_lock_context lock_context;
     136
     137  rtems_interrupt_lock_acquire(&rtems_i8259_access_lock, &lock_context);
    136138
    137139  mask = 1 << irqLine;
     
    147149  }
    148150
    149   rtems_interrupt_enable(level);
     151  rtems_interrupt_lock_release(&rtems_i8259_access_lock, &lock_context);
    150152
    151153  return 0;
     
    162164{
    163165  unsigned short        mask;
    164   rtems_interrupt_level level;
     166  rtems_interrupt_lock_context lock_context;
    165167  uint8_t               isr;
    166168  uint8_t               irr;
    167169
    168   rtems_interrupt_disable(level);
     170  rtems_interrupt_lock_acquire(&rtems_i8259_access_lock, &lock_context);
    169171
    170172  mask = 1 << irqLine;
     
    187189    printk("i386: isr=%x irr=%x\n", isr, irr);
    188190
    189   rtems_interrupt_enable(level);
     191  rtems_interrupt_lock_release(&rtems_i8259_access_lock, &lock_context);
    190192
    191193  return 0;
     
    240242static void compute_i8259_masks_from_prio (void)
    241243{
    242   rtems_interrupt_level level;
     244  rtems_interrupt_lock_context lock_context;
    243245  unsigned int i;
    244246  unsigned int j;
    245247
    246   rtems_interrupt_disable(level);
     248  rtems_interrupt_lock_acquire(&rtems_i8259_access_lock, &lock_context);
    247249
    248250  /*
     
    261263  }
    262264
    263   rtems_interrupt_enable(level);
     265  rtems_interrupt_lock_release(&rtems_i8259_access_lock, &lock_context);
    264266}
    265267
     
    315317void BSP_dispatch_isr(int vector)
    316318{
     319  rtems_interrupt_lock_context lock_context;
    317320  rtems_i8259_masks in_progress_save = 0;
    318321
     
    322325     */
    323326    if (vector <= BSP_IRQ_MAX_ON_i8259A) {
     327
     328      rtems_interrupt_lock_acquire_isr(&rtems_i8259_access_lock, &lock_context);
     329
    324330      /*
    325331       * See if this is a spurious interrupt.
     
    336342          if ((isr & (1 << 7)) == 0) {
    337343            ++spurious_count;
     344            rtems_interrupt_lock_release_isr(&rtems_i8259_access_lock, &lock_context);
    338345            return;
    339346          }
     
    356363       */
    357364      BSP_irq_ack_at_i8259a(vector);
     365
     366      rtems_interrupt_lock_release_isr(&rtems_i8259_access_lock, &lock_context);
    358367    }
    359368
     
    379388
    380389    if (vector <= BSP_IRQ_MAX_ON_i8259A) {
     390
     391      rtems_interrupt_lock_acquire_isr(&rtems_i8259_access_lock, &lock_context);
     392
    381393      /*
    382394       * Put the mask back but keep this vector masked if the trigger type is
     
    389401        BSP_i8259a_irq_update_slave_imr();
    390402      }
     403
     404      rtems_interrupt_lock_release_isr(&rtems_i8259_access_lock, &lock_context);
    391405    }
    392406  }
  • c/src/lib/libbsp/i386/shared/irq/irq_init.c

    rf45ddee r6b54dcb  
    125125    }
    126126
    127     rtems_interrupt_disable(level);
     127    /*
     128     * The interrupt management can be initialized only once
     129     * during system bootup and that should happen on boot
     130     * CPU so there is no need to synchronize with others CPUs.
     131     */
     132    rtems_interrupt_local_disable(level);
    128133
    129134    /*
Note: See TracChangeset for help on using the changeset viewer.