1. 28 Jan, 2022 1 commit
  2. 24 Jan, 2022 1 commit
    • Ben Avison's avatar
      Improve behaviour when used with RTSupport threads · 28fdd6df
      Ben Avison authored
      Two of the locking data types - mutex_t and spinrw_t - offer a
      lock-with-sleep function. These can cause the current thread to sleep until
      another thread releases the lock. Sleeping is achieved using OS_UpCall 6, and
      so supports thread suspension by either TaskWindow or RTSupport.
      This is usually fine, but RTSupport, unlike TaskWindow, permits threads to
      be assigned differing priority levels. Thus, if a lock is held by a
      low-priority thread when a high-priority thread attempts to lock it, the
      low-priority thread continues to run (this is a common feature of
      priority-based threading systems known as priority inversion). This is
      unavoidable in some situations, but ideally the high-priority thread should
      be resumed as soon as the shared resource (in this case the lock) is
      released by the low-priority thread. Previously, there was no mechanism to
      achieve this with either of these two lock types.
      One challenge is to achieve this without making the unlock functions
      unnecessarily slow in the common case where there is no higher-priority
      thread to resume. This is achieved in two ways:
      1) Yielding is performed using RT_Yield to explicitly rescan pollwords for
         RTSupport threads only. Since TaskWindow threads are all implicitly of
         identical priority, we avoid using an OS_UpCall 6 yield, which would
         cause all TaskWindow pollwords to be rescanned as well.
      2) An internal flag inside the lock struct is used to remember whether any
         other threads attempted to lock it when it was already locked, and a yield
         is only performed when unlocking if this indicates there is (or might be)
         another thread waiting.
      The situation is complicated by the fact that (despite what the SWI docs say)
      RT_Yield can cause IRQs to trigger even if the caller has them disabled. This
      can however be inferred from the entry conditions of RTSupport callback
      routines, which usually have IRQs enabled, so if any IRQ-enabled routine is
      pending when we call RT_Yield, IRQs will become enabled. This is a problem
      because if the calling thread also holds non-re-entrant locks (e.g. a
      spinlock) then we defeat those locks by pre-empting the thread in this way.
      To deal with this, we check that IRQs are enabled prior to calling RT_Yield,
      even though this will also discard many cases where a yield would have been
      desirable. A future enhancement would be to maintain a thread-local flag, and
      trigger RT_Yield when the outermost IRQ-disabling lock is released (even if
      that lock type wouldn't ordinarily cause other threads to sleep) but this
      presumes thread-local storage, which is not yet implemented for RTSupport.
      More sophisticated schemes are possible, such as by comparing the relative
      priorities of the lock holder and waiter, but these introduce additional
      overheads into the lock and unlock functions, so unless and until it becomes
      clear that they are required, they have not been implemented.
  3. 17 Dec, 2021 2 commits
  4. 07 May, 2018 1 commit
    • Jeffrey Lee's avatar
      Fix wrong spinrw function name exports. Add new spinrw_write_to_read function. · a8d592ef
      Jeffrey Lee authored
        h/spinrw - Fix header file to use the correct names for the write try lock & sleep lock functions.
        s/spinrw - Add new spinrw_write_to_read function, which atomically converts a held write lock to a read lock. This can be useful if you have a long routine which needs to update some state and then perform extra actions based on the new value - if the write occurs at the start of the routine, the write access can then be downgraded to read access, allowing interrupts + concurrent read access, while still making sure the data hasn't changed from what was written.
        Tested on OMAP3, OMAP4
      Version 0.05. Tagged as 'SyncLib-0_05'
  5. 06 Jun, 2017 1 commit
    • Jeffrey Lee's avatar
      Fix a couple of spinrw issues · eaab0406
      Jeffrey Lee authored
        s/spinrw - Add a barrier to the Pause macro to prevent excessive spinning when multiple cores are competing for the same lock.
        Also, fix garbage pointer being passed to OS_UpCall by spinrw_write_sleep_lock
        Tested on Raspberry Pi 3
      Version 0.04. Tagged as 'SyncLib-0_04'
  6. 08 May, 2016 1 commit
    • Jeffrey Lee's avatar
      Update atomic_process_smp to cope with the possibility of the process function... · eb3ebf01
      Jeffrey Lee authored
      Update atomic_process_smp to cope with the possibility of the process function altering the state of the exclusive monitor. Prefer CPS over MSR when performing PSR manipulation.
        s/atomic - Since the exclusive monitor can have its state affected by almost anything, atomic_process_smp can't assume that the state remains stable across the call to the user's process function. Instead we must perform our LDREX-STREX sequence after the callback, manually checking that the value being updated hasn't been altered by anyone else while the process function was executing.
        s/spin, s/spinrw - When disabling interrupts prefer CPS over MSR. Apart from making the sequences one instruction shorter, CPS generally delivers better performance than the equivalent MSR.
        Tested on Cortex-A15
      Version 0.03. Tagged as 'SyncLib-0_03'
  7. 29 Feb, 2016 1 commit
    • Ben Avison's avatar
      Extra function to assist with ARMv8 compatibility · ebe048fb
      Ben Avison authored
        atomic_update_byte() is the equivalent of atomic_update() but deals with
        byte-wide rather than word-wide data fields. It operates using either
        SWPB or LDREXB/STREXB instructions, depending upon the architecture, and
        is therefore suitable for updating any modules which currently use SWPB
        explicitly in order to make them compatible with ARMv8 where the SWPB
        instruction has been removed.
        Tested on Raspberry Pi 3.
      Version 0.02. Tagged as 'SyncLib-0_02'
  8. 29 May, 2012 1 commit
    • Ben Avison's avatar
      Initial import of SyncLib · 2fec96d6
      Ben Avison authored
        SyncLib is a library containing architecture-independent synchronisation
        primitives. It supports uniprocessor and SMP systems, even though RISC OS
        itself does not (yet) support SMP - but it allows individual modules to
        start to be modified in preparation for any such future support. The
        library adjusts itself according to the architecture targeted by your
        chosen build, so in particular when used in ROM builds, only supported for
        the appropriate CPU(s) will be included.
        SyncLib is used heavily by SDIODriver and SDFS - they have acted as a test
        bed for the library and also as a proof of concept for SMP-ready modules.