|
|
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.