Commit 2fec96d6 authored by Ben Avison's avatar Ben Avison
Browse files

Initial import of SyncLib

Detail:
  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.
Admin:
  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.
parents
hdr/** gitlab-language=armasm linguist-language=armasm linguist-detectable=true
s/** gitlab-language=armasm linguist-language=armasm linguist-detectable=true
c/** gitlab-language=c linguist-language=c linguist-detectable=true
h/** gitlab-language=c linguist-language=c linguist-detectable=true
Copyright (c) 2011-2012, Ben Avison
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of their
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Makefile for SyncLib
COMPONENT = SyncLib
HDRS = atomic barrier cpuevent mutex spin spinrw synclib
OBJS = atomic barrier cpuevent init mutex spin spinrw
include CLibrary
# Dynamic dependencies:
Dir <Obey$Dir>
amu all_libs THROWBACK=-throwback
Dir <Obey$Dir>
amu clean
stripdepnd
Dir <Obey$Dir>
amu export_hdrs
amu export_libs THROWBACK=-throwback
/* (0.01)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 0.01
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 29 May 2012
#define Module_MajorVersion "0.01"
#define Module_Version 1
#define Module_MinorVersion ""
#define Module_Date "29 May 2012"
#define Module_ApplicationDate "29-May-12"
#define Module_ComponentName "SyncLib"
#define Module_ComponentPath "bsd/RiscOS/Sources/Lib/SyncLib"
#define Module_FullVersion "0.01"
#define Module_HelpVersion "0.01 (29 May 2012)"
#define Module_LibraryVersionInfo "0:1"
/*
* Copyright (c) 2012, Ben Avison
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holder nor the names of their
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** \file mutex.c
* An implementation of a simple mutex. Does not disable interrupts while the
* mutex is held, so is suitable for mutexes that are held for an extended
* period, but is not appropriate if you need it to always be possible to lock
* the mutex from the background (e.g. in an interrupt handler).
*/
#include "swis.h"
#include "SyncLib/synclib.h"
bool mutex_try_lock(mutex_t *mutex)
{
if (atomic_update(MUTEX_LOCKED, (uint32_t *) mutex) == MUTEX_LOCKED)
return false;
barrier();
return true;
}
void mutex_lock(mutex_t *mutex)
{
while (atomic_update(MUTEX_LOCKED, (uint32_t *) mutex) == MUTEX_LOCKED)
cpuevent_wait();
barrier();
}
void mutex_sleep_lock(mutex_t *mutex)
{
while (atomic_update(MUTEX_LOCKED, (uint32_t *) mutex) == MUTEX_LOCKED)
_swix(OS_UpCall, _INR(0,1), 6, mutex);
barrier();
}
void mutex_unlock(mutex_t *mutex)
{
barrier();
*mutex = MUTEX_UNLOCKED;
barrier_sync();
cpuevent_send();
}
/*
* Copyright (c) 2012, Ben Avison
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holder nor the names of their
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef ATOMIC_H
#define ATOMIC_H
#include <stdint.h>
/** \file atomic.h
* An implementation of atomic memory accesses that uses ARM's favoured
* instructions, dependent upon the current CPU.
*/
/** Atomic read/write of a 32-bit value.
* Can be entered in any processor mode.
* \arg new_value Value to write.
* \arg address Memory location at which to perform the read/write.
* \return Value that was read.
*/
uint32_t atomic_update(uint32_t new_value, volatile uint32_t *address);
/** User-defined atomic operation on a 32-bit value.
* Can be entered in any processor mode unless you need to support
* architecture 5 or earlier, in which case must be entered in privileged mode.
* \arg callback Routine to change the value (may be called more than once).
* \arg argument Value to pass to callback as its second argument.
* \arg address Memory location at which to operate.
* \return Value that was at location before operation.
*/
uint32_t atomic_process(uint32_t (*callback)(uint32_t, uint32_t), uint32_t argument, volatile uint32_t *address);
#endif
/*
* Copyright (c) 2012, Ben Avison
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holder nor the names of their
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BARRIER_H
#define BARRIER_H
/** \file barrier.h
* An implementation of CPU data barriers.
*/
/** Call this to enforce the order of memory accesses as viewed by other CPUs
* in the system. Can be entered in any processor mode.
*/
void barrier(void);
/** Call this to enforce the order of memory accesses as viewed by other CPUs
* in the system, but also synchronise non-data transfer instructions for the
* present CPU with respect to its memory accesses. Can be entered in any
* processor mode.
*/
void barrier_sync(void);
#endif
/*
* Copyright (c) 2012, Ben Avison
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holder nor the names of their
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CPUEVENT_H
#define CPUEVENT_H
/** \file cpuevent.h
* An implementation of CPU synchronisation events.
*/
/** Wake up any other sleeping CPUs. Can be entered in any processor mode.
*/
void cpuevent_send(void);
/** Sleep the present CPU. Can be entered in any processor mode.
*/
void cpuevent_wait(void);
#endif
/*
* Copyright (c) 2012, Ben Avison
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holder nor the names of their
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MUTEX_H
#define MUTEX_H
#include <stdbool.h>
#include <stdint.h>
/** \file mutex.h
* An implementation of a simple mutex. Does not disable interrupts while the
* mutex is held, so is suitable for mutexes that are held for an extended
* period, but is not appropriate if you need it to always be possible to lock
* the mutex from the background (e.g. in an interrupt handler).
*/
/** The data block used to hold the state of a mutex. */
typedef enum
{
MUTEX_LOCKED,
MUTEX_UNLOCKED
} mutex_t;
/** Attempt to lock a mutex.
* Can be entered in any processor mode.
* \arg mutex Pointer to mutex.
* \return Whether the lock succeeded.
*/
bool mutex_try_lock(mutex_t *mutex);
/** Lock a mutex, waiting (forever if necessary) for it to become available.
* Can be entered in any processor mode.
* \arg mutex Pointer to mutex.
*/
void mutex_lock(mutex_t *mutex);
/** Lock a mutex, waiting (forever if necessary) for it to become available, sleeping the current task if necessary.
* Can be entered in any processor mode.
* \arg mutex Pointer to mutex.
*/
void mutex_sleep_lock(mutex_t *mutex);
/** Unlock a mutex.
* Can be entered in any processor mode.
* \arg mutex Pointer to mutex.
*/
void mutex_unlock(mutex_t *mutex);
#endif
/*
* Copyright (c) 2011, Ben Avison
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holder nor the names of their
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SPIN_H
#define SPIN_H
#include <stdint.h>
/** \file spin.h
* An implementation of a simple SVC-mode spin lock. Only one CPU can hold it
* at a time, and interrupts are disabled on the CPU that holds it, to avoid
* any re-entrancy concerns.
*/
/** The data block used to hold the state of a spinlock. */
typedef struct
{
uint32_t opaque[2];
} spinlock_t;
/** Use this to initialise any new spin locks you create. */
#define SPIN_INITIALISER { 1, 0 }
/** Disable IRQs and, if on a SMP system, wait (forever if necessary) for any
* other CPU using this lock to release it, and claim it ourselves.
* Must be entered in privileged mode.
* \arg lock Pointer to spinlock block.
*/
void spin_lock(spinlock_t *lock);
/** Release the lock and restore the IRQ disable state to how it was when the
* lock was claimed.
* Must be entered in privileged mode.
* \arg lock Pointer to spinlock block.
*/
void spin_unlock(spinlock_t *lock);
#endif
/*
* Copyright (c) 2012, Ben Avison
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holder nor the names of their
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SPINRW_H
#define SPINRW_H
#include <stdbool.h>
#include <stdint.h>
/** \file spinrw.h
* An implementation of an SVC-mode read-write spin lock.
*
* The lock can be held only once for writing, but multiple times for reading.
* It can only be held for reading or writing, not both at the same time.
*
* While the lock is held for writing, interrupts are disabled on the CPU
* holding the lock, so it is always possible to claim a read lock from
* interrupt context.
*
* Interrupts are *not* disabled while one or more read locks are held. This
* allows read locks to be held for extended periods, but means that claiming a
* write lock from interrupt context can fail. For this reason, you may wish to
* design your software such that write locks are only ever claimed from the
* foreground.
*/
/** The data block used to hold the state of a spinlock. */
typedef struct
{
uint32_t opaque[4];
} spinrwlock_t;
/** Use this to initialise any new read-write spin locks you create. */
#define SPINRW_INITIALISER { 1, 0, 0, 1 }
/** Attempt to claim a write lock. Will fail if the lock is already held for
* either reading or writing. If it succeeds, IRQs are disabled.
* Must be entered in privileged mode.
* \arg lock Pointer to spinrwlock block.
* \return Whether the lock succeeded.
*/
bool spinrw_try_write_lock(spinrwlock_t *lock);
/** Wait (forever if necessary) until the lock is not held for reading or
* writing, then claim a write lock and disable IRQs.
* Must be entered in privileged mode.
* \arg lock Pointer to spinrwlock block.
*/
void spinrw_write_lock(spinrwlock_t *lock);
/** Wait (forever if necessary) until the lock is not held for reading or
* writing, sleeping the current task if necessary, then claim a write lock and
* disable IRQs.
* Must be entered in privileged mode.
* \arg lock Pointer to spinrwlock block.
*/
void spinrw_sleep_write_lock(spinrwlock_t *lock);
/** Release a write lock and restore the IRQ disable state to how it was when
* the write lock was claimed.
* Must be entered in privileged mode.
* \arg lock Pointer to spinrwlock block.
*/
void spinrw_write_unlock(spinrwlock_t *lock);
/** Wait (forever if necessary) for any other CPU that holds the lock for
* writing to release it, then increment the number of times the lock is held
* for reading.
* Must be entered in privileged mode.
* \arg lock Pointer to spinrwlock block.
*/
void spinrw_read_lock(spinrwlock_t *lock);
/** Decrement the number of times the lock is held for reading.
* Must be entered in privileged mode.
* \arg lock Pointer to spinrwlock block.
*/
void spinrw_read_unlock(spinrwlock_t *lock);
#endif
/*
* Copyright (c) 2012, Ben Avison
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holder nor the names of their
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SYNCLIB_H
#define SYNCLIB_H
/** \file synclib.h
* A library containing architecture-independent synchronisation primitives.
* Supports uniprocessor and SMP systems.
*/
#include "SyncLib/atomic.h"
#include "SyncLib/barrier.h"
#include "SyncLib/cpuevent.h"
#include "SyncLib/mutex.h"
#include "SyncLib/spin.h"
#include "SyncLib/spinrw.h"
/** Library initialisation routine.
* Call this before any of the other functions in this library.
* Must be entered in privileged mode.
*/
void synclib_init(void);
#endif
;
; Copyright (c) 2012, Ben Avison
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
; * Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; * Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
; * Neither the name of the copyright holder nor the names of their
; contributors may be used to endorse or promote products derived from
; this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;
; Inline assembler version of the barrier routine
EXTERN barrier
EXTERN barrier_sync
MACRO
$label Barrier$cc
IF :LNOT: SupportARMv6
$label ; nothing
ELIF :LNOT: NoARMv7
$label
[ "$cc" <> "" :LAND: "$cc" <> "AL"
LCLS not
not SETS :REVERSE_CC: "$cc"
B$not %FT00
]
DMB ; can't be done conditionally
00
ELSE
$label Push "a4,ip,lr", $cc
BL$cc barrier ; preseves flags
Pull "a4,ip,lr", $cc
ENDIF
MEND
MACRO
$label BarrierSync$cc
IF :LNOT: SupportARMv6
$label ; nothing
ELIF :LNOT: NoARMv7
$label
[ "$cc" <> "" :LAND: "$cc" <> "AL"
LCLS not
not SETS :REVERSE_CC: "$cc"
B$not %FT00
]
DSB ; can't be done conditionally
00
ELSE
$label Push "a4,ip,lr", $cc
BL$cc barrier_sync ; preserves flags
Pull "a4,ip,lr", $cc
ENDIF
MEND
END
;
; Copyright (c) 2012, Ben Avison
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
; * Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; * Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
; * Neither the name of the copyright holder nor the names of their
; contributors may be used to endorse or promote products derived from
; this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;
; Inline assembler version of the barrier routine
EXTERN cpuevent_send
EXTERN cpuevent_wait
MACRO
$label CPUEventSend$cc
IF :LNOT: SupportARMK
$label ; nothing
ELIF :LNOT: NoARMK
$label SEV$cc
ELSE
$label Push "a4,ip,lr", $cc
BL$cc cpuevent_send ; preserves flags
Pull "a4,ip,lr", $cc
ENDIF
MEND
MACRO
$label CPUEventWait$cc
IF :LNOT: SupportARMK
$label ; nothing
ELIF :LNOT: NoARMK
$label WFE$cc
ELSE
$label Push "a4,ip,lr", $cc
BL$cc cpuevent_wait ; preserves flags
Pull "a4,ip,lr", $cc
ENDIF
MEND
END
;
; Copyright (c) 2012, Ben Avison
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
; * Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; * Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
; * Neither the name of the copyright holder nor the names of their
; contributors may be used to endorse or promote products derived from
; this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;
; CPU identification flags used in init routines
CPU_Exclusive * 1:SHL:0 ; assumes we only care about 32-bit accesses
CPU_Events * 1:SHL:1
CPU_CP15DSB * 1:SHL:2
CPU_CP15DMB * 1:SHL:3
CPU_Barriers * 1:SHL:4 ; instruction forms
END
;
; Copyright (c) 2012, Ben Avison
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
; * Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; * Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
; * Neither the name of the copyright holder nor the names of their
; contributors may be used to endorse or promote products derived from
; this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;
; These are a bit like the long-established LDRVar and STRVar macros,
; but with the following differences:
; * uses literal pools rather than requiring you to explicitly declare
; variables using LocalVar and related macros
; * only does relocation if zM is true (set by shared makefiles)
; * load macro supports loading the PC, although this does require that you
; supply the otherwise optional w1 argument
; * the condition code is specified as a postfix to the macro (objasm 4 feature)
;
; Normally, in the non-zM case, the variable will be reachable in a single
; instruction, but this depends upon the variable being within 4K of the
; instruction. If this is not the case, you can set the "far" argument.
[ :LNOT: :DEF: zM
GBLL zM
zM SETL {FALSE}
]
; Get the contents of a static variable.
MACRO
$label Load$cc $reg, $base, $var, $w1, $far
LCLS work
[ "$w1" = ""
work SETS "$reg"
|
work SETS "$w1"
]
ASSERT $work <> $base
ASSERT $work <> 15
[ zM
$label LDR$cc $work, =$var
LDR$cc $reg, [$base, $work]
|
[ "$far" = "far"
$label LDR$cc $work, =$var
LDR$cc $reg, [$work]
|
$label LDR$cc $reg, $var
]
]
MEND
; Set the contents of a static variable.
MACRO
$label Store$cc $reg, $base, $var, $w1, $far
ASSERT $w1 <> $base
ASSERT $w1 <> $reg
ASSERT $w1 <> 15
[ zM
$label LDR$cc $w1, =$var
STR$cc $reg, [$base, $w1]
|
[ "$far" = "far"
$label LDR$cc $w1, =$var
STR$cc $reg, [$w1]
|
$label STR$cc $reg, $var
]
]
MEND
END
;
; Copyright (c) 2012, Ben Avison
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
; * Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; * Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
; * Neither the name of the copyright holder nor the names of their
; contributors may be used to endorse or promote products derived from
; this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;
GET ListOpts
GET Macros
GET System
GET CPU/Arch
GET APCS/$APCS
GET hdr/init
GET hdr/vars
Strex_Succeeded * 0
Strex_Failed * 1
AREA |Asm$$Code|, CODE, READONLY
IF SupportARMv6 :LAND: NoARMv6 ; i.e. run-time detection is required
EXPORT atomic_init
atomic_init ROUT
[ zM
StaticBaseFromSL a4
]
ADR a2, atomic_update_uniproc
ADR a3, atomic_process_uniproc
TST a1, #CPU_Exclusive
ADRNE a2, atomic_update_smp
ADRNE a3, atomic_process_smp
Store a2, a4, update_fn, ip
Store a3, a4, process_fn, ip
Return , LinkNotStacked
ENDIF
IF :LNOT: SupportARMv6
atomic_update * atomic_update_uniproc
atomic_process * atomic_process_uniproc
ELIF :LNOT: NoARMv6
atomic_update * atomic_update_smp
atomic_process * atomic_process_smp
ELSE
atomic_update ROUT
[ zM
StaticBaseFromSL a4
]
Load pc, a4, update_fn, ip
atomic_process ROUT
[ zM
StaticBaseFromSL a4
]
Load pc, a4, process_fn, ip
ENDIF
IF NoARMv6
atomic_update_uniproc ROUT
; Let's not worry about ARM2 support
SWP a1, a1, [a2]
Return , LinkNotStacked
atomic_process_uniproc ROUT
FunctionEntry "v1-v3"
MOV ip, a1
MOV v1, a3
MRS v2, CPSR
ORR a4, v2, #I32_bit
MSR CPSR_c, a4 ; IRQs now disabled
LDR a1, [a3]
MOV v3, a1
MOV lr, pc
MOV pc, ip
STR a1, [v1]
MSR CPSR_c, v2
MOV a1, v3
Return "v1-v3"
ENDIF
IF SupportARMv6
atomic_update_smp ROUT
MOV a3, a1
01 LDREX a1, [a2]
STREX a4, a3, [a2]
TEQ a4, #Strex_Failed
BEQ %B01 ; another exclusive access happened between LDREX and STREX
Return , LinkNotStacked
atomic_process_smp ROUT
FunctionEntry "v1-v4"
MOV v3, a3
MOV v2, a2
MOV v1, a1
01 LDREX a1, [v3]
MOV a2, v2
MOV v4, a1
BLX v1 ; any CPU that has LDREX will have BLX too
STREX ip, a1, [v3]
TEQ ip, #Strex_Failed
BEQ %B01 ; another exclusive access happened between LDREX and STREX
MOV a1, v4
Return "v1-v4"
ENDIF
IF SupportARMv6 :LAND: NoARMv6
AREA |Asm$$Data|, DATA
update_fn
DCD 0
process_fn
DCD 0
ENDIF
EXPORT atomic_update
EXPORT atomic_process
END
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment