|
|
1.1 ! root 1: / This file contains implementations of multiprocessor locking primitives used ! 2: / by the STREAMS and DDI/DDK subsystems. With GCC or other compilers that allow ! 3: / in-line generation of assembly language code in C programs a separate ! 4: / assembly-language file containing these implementations is not necessary. ! 5: / Since the MWC C compiler that is the default development tool under Coherent ! 6: / does not permit inlining, references to the locking functions will be turned ! 7: / into external function calls that will be resolved by the routines below. ! 8: .unixorder ! 9: ! 10: / The routines work by using the i386 feature that all cycles involving a ! 11: / single read or write are atomic regardless of alignment or lack thereof, and ! 12: / by using the XCHG instruction, which is an atomic read-modify-write ! 13: / instruction. Use of the atomic exchange primitive allows more efficient ! 14: / implementation of some data structures than the more fundamental test-and-set ! 15: / instruction (but is not as powerful as the atomic compare-and-swap ! 16: / instruction found in the Motorola 680x0 processors). ! 17: / Incidentally, atomic exchange is the only atomic operation in many new RISC ! 18: / processors such as the Motorola 88100. ! 19: ! 20: / The C-language header file <kernel/x86lock.h> defines data types and function ! 21: / prototypes that should match the definitions expected in this file. Since the ! 22: / regular read and write operations on the i386 are atomic, the definitions in ! 23: / this file are for those operations that cannot be performed in C; the other ! 24: / operations can be safely described by macros with the use of the 'volatile' ! 25: / keyword to prevent optimisation of accesses to these items (since other CPUs ! 26: / have the ability to modify the values contained in these locations, the ! 27: / data-flow analysis often performed by compilers to allow cacheing of values ! 28: / in registers would cause incorrect results). ! 29: ! 30: / Under Coherent, the iBCS2 function calling-sequence rules are in effect. This ! 31: / means that the registers %ebx, %esi and %edi are used for register variables ! 32: / and must be preserved by routines. However, all other registers are available ! 33: / for modification; with the i386 CPU the general registers %eax, %ecx and %edx ! 34: / are available for use as index registers with the addition of the SIB ! 35: / instruction forat. Parameters are passed in the stack from right to left, ! 36: / with the caller's return address being the "topmost" entry. ! 37: ! 38: .globl ATOMIC_FETCH_AND_STORE_CHAR ! 39: .globl ATOMIC_FETCH_AND_STORE_UCHAR ! 40: .globl ATOMIC_FETCH_AND_STORE_SHORT ! 41: .globl ATOMIC_FETCH_AND_STORE_USHORT ! 42: .globl ATOMIC_FETCH_AND_STORE_INT ! 43: .globl ATOMIC_FETCH_AND_STORE_UINT ! 44: .globl ATOMIC_FETCH_AND_STORE_LONG ! 45: .globl ATOMIC_FETCH_AND_STORE_ULONG ! 46: .globl ATOMIC_FETCH_AND_STORE_PTR ! 47: ! 48: ! 49: / char ATOMIC_FETCH_AND_STORE_CHAR (atomic_char_t _item, char _value); ! 50: ATOMIC_FETCH_AND_STORE_CHAR: ! 51: mov 8(%esp), %al / Value to store ! 52: mov 4(%esp), %edx / Address of atomic item ! 53: ! 54: xchg %al, (%edx) / Atomic fetch-and-store ! 55: cbw / Sign-extend %al->%ax ! 56: cwde / Sign-extend %ax->%eax ! 57: ret / return to caller ! 58: ! 59: ! 60: / uchar_t ATOMIC_FETCH_AND_STORE_UCHAR (atomic_uchar_t _item, uchar_t _value); ! 61: ATOMIC_FETCH_AND_STORE_UCHAR: ! 62: movzxb 8(%esp), %eax / Value to store, zero-extend ! 63: mov 4(%esp), %edx / Address of atomic item ! 64: ! 65: xchg %al, (%edx) / Atomic fetch-and-store ! 66: ret / return to caller ! 67: ! 68: ! 69: / short ATOMIC_FETCH_AND_STORE_SHORT (atomic_short_t _item, short _value); ! 70: ATOMIC_FETCH_AND_STORE_SHORT: ! 71: mov 8(%esp), %ax / Value to store ! 72: mov 4(%esp), %edx / Address of atomic item ! 73: ! 74: xchg %ax, (%edx) / Atomic fetch-and-store ! 75: cwde / Sign-extend %ax->%eax ! 76: ret / return to caller ! 77: ! 78: ! 79: / ushort_t ATOMIC_FETCH_AND_STORE_USHORT (atomic_ushort_t _item, ! 80: / ushort_t _value); ! 81: ATOMIC_FETCH_AND_STORE_USHORT: ! 82: movzxw 8(%esp), %eax / Value to store, zero-filled ! 83: mov 4(%esp), %edx / Address of atomic item ! 84: ! 85: xchg %ax, (%edx) / Atomic fetch-and-store ! 86: ret / return to caller ! 87: ! 88: ! 89: / int ATOMIC_FETCH_AND_STORE_INT (atomic_int_t _item, int _value); ! 90: ATOMIC_FETCH_AND_STORE_INT: ! 91: / long ATOMIC_FETCH_AND_STORE_LONG (atomic_long_t _item, long _value); ! 92: ATOMIC_FETCH_AND_STORE_LONG: ! 93: / uint_t ATOMIC_FETCH_AND_STORE_UINT (atomic_uint_t _item, uint_t _value); ! 94: ATOMIC_FETCH_AND_STORE_UINT: ! 95: / ulong_t ATOMIC_FETCH_AND_STORE_ULONG (atomic_ulong_t _item, ulong_t _value); ! 96: ATOMIC_FETCH_AND_STORE_ULONG: ! 97: / _VOID * ATOMIC_FETCH_AND_STORE_PTR (atomic_ptr_t _item, _VOID * value); ! 98: ATOMIC_FETCH_AND_STORE_PTR: ! 99: mov 8(%esp), %eax / Value to store ! 100: mov 4(%esp), %edx / Address of atomic item ! 101: ! 102: xchg %eax, (%edx) / Atomic fetch-and-store ! 103: ret / return to caller
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.