For anyone interested. THIS IS AN EXAMPLE OF A THE COMPLETE PROCESS USED TO ADD A NEW
DISPATCHABLE UNIT (DU) ENTRY TO A QUEUE OF ACTIVE DUS. FOR SIMPLICITY, A DU IS EQUIVALENT TO A TASK. THIS QUEUE CAN BE SIMULTANEOUSLY SEARCHED, NEW DUS ADDED AND TERMINATING DUS DELETED. ADDS AND DELETES ARE DONE VERY INFREQUENTLY (COMPARED TO SEARCHES) AND ONLY BY THE DU ITSELF. DU ENTRIES FOR OTHER DUS ARE NEVER ADDED OR DELETED FROM THE QUEUE BY ANOTHER DU. THE ADD AND DELETE RULE IS VERY IMPORTANT BECAUSE ONLY THE DU CAN OWN ITS ENTRY THUS INSURING THAT THE OWNER (CODE THAT REFERENCES THE ENTRY) IS THE ONLY CODE THAT CAN ADD OR DELETE THAT ENTRY. REGARDLESS OF WHAT TYPE OF QUEUE YOU ARE SERIALIZING WITH PLO, COMMON SENSE MUST APPLY. IF DELETES WERE ALLOWED WITH AN ENTRY THAT COULD STILL BE REFERENCED, THERE WILL BE UNDESIRABLE RESULTS. IN THOSE CASES. SUCH AS WORK QUEUE, THE ENTRY SHOULD BE DELETED FROM THE ACTIVE CHAIN OR A MECHANISM BE PROVIDED TO DEFINE OWNERSHIP THUS PREVENTING DELETES FROM "OWNED" ENTRIES. THE QUEUE POINTERS ARE KEPT IN COMMON STORAGE BUT NOT IN CSA. THIS CODE USES EITHER SHARED OR COMMON MEMORY OBJECTS. WHEN THIS CODE EXECUTES, IT IS GUARANTEED THAT THE MEMORY OBJECT IS AVAILABLE. THE FOLLOWING STRUCTURE IS ALWAYS USED FOR ALL QUEUES LIKE THIS ONE: QUEUE ... QUEUE__START DS D START OF CELLS USED FOR QUEUE * WHEN THE QUEUE IS INITIALIZED, THE FREE CHAIN IS 0 TO AVOID * ADDING FREE ELEMNTS TO THE WORKING SET OF THIS CODE. INSTAED, THE * HWM=START AND AVAILQ IS 0. CODE SHOW HOW THIS IS MANAGED * QUEUE_HWM DS D CURRENT HIGH WATER MARK OF CELLS QUEUE_END DS D END OF CELLS USED FOR THIS QUEUE * QUEUE_HEAD DS D CURRENT ACTIVRE HEAD QUEUE_TAIL DS D CURRENT ACTIVE TAIL QUEUE_COUNTERS DS 0D LOCK WORD AND COUNTERS QUEUE_CHANGES DS A HIGH WORD IS CHANGES QUEUE_ENTRIES DS A LOW WORD IS ENTRIES IN CHAIN * QUEUE_AVAILQ DS D FREE CHAIN IS SINGLY LINKED QUEUE_AVCOUNTERS DS 0D LOCK WORD AND COUNTERS FOR FREE QUEUE_AVCHANGES DS A HIGH WORD IS CHANGES QUEUE_AVENTRIES DS A LOW WORD IS ENTRIES IN CHAIN ... THE COUNTER IS A DOUBLEWORD CONSISTING OF 2 FULLWORD POINTERS. THE COUNTER IS ALWAYS USED AS THE PLO LOCK WORD AND IS ALWAYS LOADED WITH A LG (LOAD GRANDE). THE CHANGE COUNT IS ALWAYS THE HIGH WORD AND INCREMENT WITH INCCHANGES CONSTANT IN THE PROGRAM CONSTANTS. THE ENTRY COUNT IS ALWAYS THE LOW WORD AND INCREMENTED WITH AHI WHICH ONLY AFFECTS THE LOW WORD. I DON'T USE ANY OF THE SPECIAL HIGH WORD INST OR IMMEDIATE INSTR BECAUSE THEY ARE A FACILITY SO I KEEP THE CODE AT A FAIRLY OLD FACILITY LEVEL * CONSTANT IN PROGRAM DS 0D INCCHANGES DC F'1',F'0' THIS IS A SAMPLE ELEMENT LAYOUT. ESSENTIALLY, I ALWAYS KEEP THE PREV AND NEXT POINTERS AS THE FIRST DOUBLE WORDS IN AN ELEMENT. THE REMAINING AREAS OF THE ELEMENT HAVE NO BEARING ON THIS PROCESS. ELEMENT ... ELEMENT_PTRS DS 0XL16 ELEMENT_PREV DS D ELEMENT_NEXT DS D ELEMENT_DATA DS ... ... ELEMENT_SIZE EQU *-ELEMENT_PREV ALL THE CODE IS REENTRANT AND THE FOLOWING WORK AREAS ARE REFERENCED: * IN WORKING STORAGE PLOWORK DS XL144 NEED FOR COMPARE AND SWAP AND STORES SEARCH_PTR DS D INITIALIZED TO 0 FOR START OF SEARCH * SET TO 0 FOR ADD OR ENTRY TO BE DELETED SEARCH_COUNTER DS D SET BY CALLER TO CURRENT COUNTER VALUE SO HERE IS THE SAMPLE EXTRACTED FROM A WORKING ALGORITHM. I CAN'T PUT THE ORIGINAL CODE IN THIS EXAMPLE FOR MANY REASONS. BUT I CAREFULLY EXTRACTED FROM A WORKING ALGORIGHM AND MADE IT INTO THIS EXAMPLE. THIS EXAMPLE SHOWS COMPARE AND LOAD, COMPARE DOUBLE AND SWAP AND SWAP AND DOUBLE STORE. IF YOU'RE NOT FAMILIAR WITH PLO TYPE SERIALIZATIONS, IT MAY TAKE A WHILE TO DIGEST ALL OF THIS. I DON'T USE THE PLO MNEMONICS. I'VE BEEN CODING IT A VERY LONG TIME AND I JUST CODE IT. * START OF A SERVICE CALL FROM A DU, SEE IF ITS ALREADY BEEN ADDED * KEY IS ASCB ADDRESS AND DU (TCB). THE ADD ONLY RUNS IN THE DU BEING * ADDED ******************************************************************** * PRIME THE SEARCH ARGUMENTS. SEARCH_VALUE HAS THE QUEUE_COUNTERS AT * START OF THE SEARCH AND THEY ARE NOT CHANGED UNLESS THE PROCESS HAS * TO BE REDRIVEN SEARCH_REDRIVE DS 0H XC SEARCH_PTR,SEARCH_PTR PRIME TO START AT HEAD MVC SEARCH_COUNTER,QUEUE_COUNTERS GET STARTING COUNTER ********************************************************************* * SEARCH QUEUE FOR REQUIRED ELEMENT SEARCH_LOOP DS 0H LA R1,QUEUE_COUNTERS LOCK WORD LG R14,SEARCH_COUNTER LOAD CURRENT COUNTER *********************************************************************** * LOAD CURRENT PTR TO DETERMINE WHERE WE ARE IN THE QUEUE CHAIN LG R2,SEARCH_PTR LOAD LAST POINTER LTGR R2,R2 FIRST TIME? JH SEARCH_NEXT NO - GET NEXT *********************************************************************** * DO PLO LCOMPARE AND LOAD FOR HEAD LA R2,QUEUE_HEAD POINT TO HEAD OF CHAIN LA R0,2 COMPARE AND LOAD FUNCTION 64 BIT PLO R14,0(R1),R3,0(R2) IF COUNTER SAME, R3--> QUEUE HEAD JZ SEARCH_CHECK GOT HEAD POINTER J SEARCH_REDRIVE COUNTER CHANGED - REDRIVE *********************************************************************** * DO PLO COMPARE AND LOAD FOR NEXT SEARCH_NEXT DS 0H LA R0,2 COMPARE AND LOAD FUNCTION 64 BIT PLO R14,0(R1),R3,ELEMENT_NEXT-ELEMENT(R2) * IF COUNTER SAME, R3--> NEXT JNZ SEARCH_REDRIVE COUNTER CHANGED - REDRIVE *********************************************************************** * SEE IF WE'VE REACHED THE END OF CHAIN SEARCH_CHECK DS 0H LTGR R3,R3 GOT IT? JZ ADDFROMFREE NO - HAVE TO ADD IT *********************************************************************** * SEE IF THIS THE DESIRED ELEMENT PERFORM_SEARCHCOMP DS 0H STG R3,SEARCH_PTR SAVE FOR NEXT PASS ... COMPARE ELEMENT AND GO TO FOUND IF EQUAL J SEARCH_LOOP PROCESS NEXT ELEMENT *********************************************************************** * IF NOT FOUND, ADD A NEW ELEMENT. WE DON'T CHANGE THE COUNTER IN CASE * ANOTHER DU HAS ADDED AN ELEMENT FORCING A REDRIVE * * FIRST GET AN AVALIABLE SLOT. TO MINIMIZE WORKING SET, WE USE A FREE * CHAIN AND A HWM OF SLOTS. THIS WAY WE DON'T HAVE TO CHAIN ALL THE * SLOTS ONTO A FREE CHAIN DRIVING UP WORKING SET. DELETE WILL ADD * TO FREE CHAIN AS SLOTS ARE DELETED * ADDFROMFREE DS 0H LG R14,QUEUE_AVCOUNTERS GET COUNTER FOR AVAILABLE QUEUE LGR R15,R14 COPY COUNTER TO AJUST LA R1,QUEUE_AVCOUNTERS COUNTER IS LOCK WORD LG R2,QUEUE_AVAILQ GET CURRENT FREE ELEMENT HEAD LTGR R2,R2 GOT ONE? JNH ADDFROMHWM NO - ADJUST HIGH WATER MARK ALG R15,INCCHANGES INCR CHANGES BY 1 HIGH WORD AHI R15,-1 DECR ELEMENTS IN FREE BY 1 LG R3,ELEMENT_NEXT-ELEMENT(,R2) GET NEXT IN FREE LA R0,10 PLO DOUBLE COMPARE AND SWAP PLO R14,0(R1),R2,QUEUE_AVAILQ GET FREE ELEMENT ELEMENT JNZ ADDFROMFREE J ADDNEW ******************************************************************** * INCREMENT HWM FOR NEW ELEMENT ADDFROMHWM DS 0H LG R2,QUEUE_HWM GET CURRENT HIGH WATER MARK LA R3,ELEMENT_SIZE(,R3) INCR HWM CLG R3,QUEUE_END REACHED ED OF SLOTS? JH WEREOUTOFSPACE WE'RE OUT OF SPACE ALG R15,INCCHANGES INCREMENT CHANGE COUNT * ENTRY COUNT DOESN'T CHANGE LA R0,10 PLO DOUBLE COMPARE AND SWAP PLO R14,0(R1),R2,QUEUE_HWM GET FROM HWM JNZ ADDFROMFREE *********************************************************************** * NOW UPDATE THE ELEMENT AND ADD TO QUEUE * R2 - HAS SOT TO BUILD ELEMENT PERFORM_ADDNEW DS 0H LGR R3,R2 COPY SLOT ADDRESS STG R3,SEARCH_PTR USING ELEMENT,R3 XC ELEMENT_PTRS,ELEMENT_PTRS ... BUILD ELEMENT ********************************************************************** * ALWAYS ADD TO START OF QUEUE XC PLOWORK+56(56),PLOWORK+56 LG R14,SEARCH_COUNTER ORIGINAL COUNTER AT START LGR R15,R14 COPY COUNTER ALG R15,INCCHANGES INCREMENT CHANGE COUNT AHI R15,1 INCREMENT NUMBER OF ELEMENTS * STG R3,PLOWORK+56 NEW HEAD VAUE - OPER 3 LA R0,QUEUE_HEAD ADDRESS OF HEAD STG R0,PLOWORK+72 OPERAND 4 FOR DOUBLE STORE * STG R3,PLOWORK+88 NEW HEAD'S PREV - OPER 5 LG R1,QUEUE_HEAD CURRENT HEAD STG R1,ELEMENT_NEXT SET NEXT IN NEW ELEMENT LA R1,ELEMENT_PREV-ELEMENT(,R1) STG R1,PLOWORK+104 OPERAND 6 FOR DOUBLE STORE LA R1,QUEUE_COUNTERS SAME LOCK AS SEARCH LA R0,18 COMPARE AND SWAP AND DOUBLE STORE 64 BIT PLO R14,0(R1),R14,PLOWORK JZ FOUND ********************************************************************** * SOMEONE ELSE HAS UPDATED THE CHAIN. WE NEED TO RETURN THE BUILT * ELEMENT TO THE FREE CHAIN AND REDRIVE. REDRIVES ARE VERY INFREQUENT ADDTOFREE DS 0H XC ELEMENT_PTRS,ELEMENT_PTRS LG R14,QUEUE_AVCOUNTERS GET COUNTER FOR AVAILABLE QUEUE LGR R15,R14 COPY COUNTER TO AJUST LA R1,QUEUE_AVCOUNTERS COUNTER IS LOCK WORD LG R2,QUEUE_AVAILQ GET CURRENT FREE ELEMENT HEAD STG R2,ELEMENT_NEXT SET CURR HEAD AS NEXT ALG R15,INCCHANGES INCR CHANGES BY 1 HIGH WORD AHI R15,1 INCR ELEMENTS IN FREE BY 1 LA R0,10 PLO DOUBLE COMPARE AND SWAP PLO R14,0(R1),R2,QUEUE_AVAILQ ADD TO FREE ELEMENTS JNZ ADDTOFREE J SEARCH_REDRIVE ********************************************************************** * COME HERE IF ELEMENT FOUND - PROCESS IS DONE FOUND DS 0H * R3 HAS FOUND ELEMENT ... *********************************************************************** * ERROR ROUTINE FOR OUT OF SPACE WEREOUTOFSPACE DS 0H ... HOPEFULLY, I DIDN'T TRANSLATE SOMETHING INCORRECTLY OR MISTYPED IT BUT THIS IS A WORKING ALGORITHM THAT GETS CALLED THE FIRST TIME ANY DU REQUESTS ANY SERVICE FROM THIS SERVER. IT'S USED BY TERMINATION TO INSURE ALL RESOURCES ARE RETURNED WHEN A DU ENDS. -----Original Message----- From: IBM Mainframe Discussion List [mailto:IBM-MAIN@LISTSERV.UA.EDU] On Behalf Of esst...@juno.com Sent: Saturday, November 09, 2013 1:48 PM To: IBM-MAIN@LISTSERV.UA.EDU Subject: Serialization without Enque I have been reading and following this thread sine PLO is not an instruction I use every day. It would be nice if someone would actually post some working code using a PLO instruction, to illustrate how one would add an element to a queue and remove an element from a queue. Paul D'Angelo ---------------------------------------------------------------------- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN ---------------------------------------------------------------------- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN