From z/Architecture Principles of Operations TEST AND SET Assembly language instruction: TS D2(B2) [S] The leftmost bit (bit position 0) of the byte located at the second-operand address is used to set the condition code, and then the byte is set to all ones. Bits 8-15 of the instruction are ignored. The byte in storage is set to all ones as it is fetched for the testing of bit 0. This update appears to be an interlocked-update reference as observed by other CPUs.Resulting Condition Code: 0 Leftmost bit zero 1 Leftmost bit one 2 -3 -Program Exceptions: • Access (fetch and store, operand 2) Programming Notes: 1. TEST AND SET may be used for controlled sharing of a common storage area by programs operating on different CPUs. This instruction is provided primarily for compatibility with programs written for System/360. The instructions COMPARE AND SWAP and COMPARE DOUBLE AND SWAP provide functions which are more suitable for sharing among programs on a single CPU or for programs that may be interrupted. See the description of these instructions and the associated programming notes for details. 2. TEST AND SET does not interlock against storage accesses by channel programs. Therefore, the instruction should not be used to update a location into which a channel program may store, since the channel-program data may be lost. COMPARE AND SWAP CS R1,R3,D2(B2) [RS] CSY R1,R3,D2(B2) [RSY] CSG R1,R3,D2(B2) [RSY] COMPARE DOUBLE AND SWAP CDS R1,R3,D2(B2) [RS] CDSY R1,R3,D2(B2) [RSY] CDSG R1,R3,D2(B2) [RSY] The first and second operands are compared. If they are equal, the third operand is stored at the second operand location. If they are unequal, the second operand is loaded into the first-operand location. The result of the comparison is indicated in the condition code. For COMPARE AND SWAP (CS, CSY), the first and third operands are 32 bits in length, with each operand occupying bit positions 32-63 of a general register. The second operand is a word in storage. More details (not important here..) For COMPARE AND SWAP (CSG), the first and third operands are 64 bits in length, with each operand occupying bit positions 0-63 of a general register. The second operand is a doubleword in storage. For COMPARE DOUBLE AND SWAP (CDS, CDSY), the first and third operands are 64 bits in length. The first 32 bits of an operand occupy bit positions 32-63 of the even-numbered register of an even-odd pair of general registers, and the second 32 bits occupy bit positions 32-63 of the odd-numbered register of the pair. The second operand is a doubleword in storage. For COMPARE DOUBLE AND SWAP (CDSG), the first and third operands are 128 bits in length. The first 64 bits of an operand occupy bit positions 0-63 of the even-numbered register of an even-odd pair of general registers, and the second 64 bits occupy bit positions 0-63 of the odd-numbered register of the pair. The second operand is a quadword in storage. When an equal comparison occurs, the third operand is stored at the second-operand location. The fetch of the second operand for purposes of comparison and the store into the second-operand location appear to be a block-concurrent interlocked-update reference as observed by other CPUs. When the result of the comparison is unequal, the second operand is loaded at the first-operand location, and the second-operand location remains unchanged. However, on some models, the contents may be fetched and subsequently stored back unchanged at the second-operand location. This update appears to be a blockconcurrent interlockedupdate reference as observed by other CPUs. A serialization function is performed before the operand is fetched and again after the operation is completed. The displacement for CS and CDS is treated as a 12-bit unsigned binary integer. The displacement for CSY, CSG, CDSY, and CDSG is treated as a 20-bit signed binary integer. The second operand of COMPARE AND SWAP (CS, CSY) must be designated on a word boundary. The second operand of COMPARE AND SWAP (CSG) and COMPARE DOUBLE AND SWAP (CDS, CDSY) must be designated on a doubleword boundary. The second operand of COMPARE DOUBLE AND SWAP (CDSG) must be designated on a quadword boundary. The R1 and R3 fields for COMPARE DOUBLE AND SWAP must each designate an even-numbered register. Otherwise, a specification exception is recognized. The COMPARE AND SWAP (CS) and COMPARE DOUBLE AND SWAP (CDS) instructions can be used in multiprogramming or multiprocessing environments to serialize access to counters, flags, control words, and other common storage areas. The following examples of the use of the COMPARE AND SWAP and COMPARE DOUBLE AND SWAP instructions illustrate the applications for which the instructions are intended. It is important to note that these are examples of functions that can be performed by programs while the CPU is enabled for interruption (multiprogramming) or by programs that are being executed in a multiprocessing configuration. That is, the routine allows a program to modify the contents of a storage location while the CPU is enabled, even though the routine may be interrupted by another program on the same CPU that will update the location, and even though the possibility exists that another CPU may simultaneously update the same location. The COMPARE AND SWAP instruction first checks the value of a storage location and then modifies it only if the value is what the program expects; normally this would be a previously fetched value. If the value in storage is not what the program expects, then the location is not modified; instead, the current value of the location is loaded into a general register, in preparation for the program to loop back and try again. During the execution of COMPARE AND SWAP, no other CPU can perform a store access or interlocked-update access at the specified location. static inline void __attribute__ ((unused)) exampleSerializedUpdate(int quantity, int *value)//zArchitecture cs instr. { __asm__ __volatile__ ( //parameters: %1 is quantity, %2 is value pointer " \n" /* quantity: amount to increase*/ " l %%r0,%2 \n" /* load *value into R0 */ "0: \n" " lr %%r1,%%r0 \n" /* load *value into R1 */ " ar %%r1,%1 \n" /* add inc/dec amount */ " cs %%r0,%%r1,%2 \n" /* execute cs */ " jnz 0b \n" /* if cs not successful, retry*/ : "=Q" (*value) : "d" (quantity), "Q" (*value) : "0", "1", "cc", "memory"); return; } Updating Counters In this example, a 32-bit counter is updated by a program using the COMPARE AND SWAP instruction to ensure that the counter will be correctly updated. The original value of the counter is obtained by loading the word containing the counter into general register 7. This value is moved into general register 8 to provide a modifiable copy, and general register 6 (containing an increment to the counter) is added to the modifiable copy to provide the updated counter value. The COMPARE AND SWAP instruction is used to ensure valid storing of the counter. The program updating the counter checks the result by examining the condition code. The condition code 0 indicates a successful update, and the program can proceed. If the counter had been changed between the time that the program loaded its original value and the time that it executed the COMPARE AND SWAP instruction, the execution would have loaded the new counter value into general register 7 and set the condition code to 1, indicating an unsuccessful update. The program must then repeat the update sequence until the execution of the COMPARE AND SWAP instruction results in a successful update. The following instruction sequence performs the above procedure: LA 6,1 L 7,CNTR LOOP LR 8,7 AR 8,6 CS 7,8,CNTR BC 4,LOOP CPU A GR7 GR8 CNTR 16 Put increment (1) into GR6 Put original counter value into GR7 Set up copy in GR8 to modify Increment copy Update counter in storage If original value had changed, update new value CPU B GR7 GR8 16 16 16 16 17 17 17 17 18 18 Comments CPU A loads GR7 and GR8 from CNTR CPU B loads GR7 and GR8 from CNTR CPU B adds one to GR8 CPU A adds one to GR8 CPU A executes CS; successful match, store CPU B executes CS; no match, GR7 changed to CNTR value CPU B loads GR8 from GR7, adds one to GR8 CPU B executes CS; successful match, store