LOCKTRY instruction problem?

I'm having a problem getting the LOCKTRY instruction to work. No matter what I do, I can never get it to return with the carry set, indicating a lock has been acquired.
'test locktry instruction

DAT		org 0

i1		drvh	#56
        	locktry	#$0 wc
		outc	#56
inf    		jmp	#inf

I am running in Pnut, which is compiling the instruction correctly, and downloading to a P2ES board, rev-B cpu, with the onboard pin 56 LED being used to display the carry bit.

The LOCKNEW instruction, however, does work. I can acquire any lock from $0 to $F with no problem. And, when I check out all 16 locks, then try a 17th, it returns with
the carry set, like it's supposed to.

What am I doing wrong?


Comments

  • I think locktry is inverted in pnut compared to fastspin.

    try for carry NOT set

    Mike
  • Have you tried performing a LOCKREL before the LOCKTRY to confirm the status of the lock?

    LOCKREL D WC will put the current owner in D and the captured state into C.

  • Hmm,
    It looks like LOCKTRY only returns C=1 when the cog already has the lock.
    Running this test code through my debugger
    		locknew	x9 wc	'get 3 locks
    		locknew	y9 wc
    		locknew	z9 wc
    
    		nop
    		locktry	x9 wc	'try the same 3 locks
    		locktry	y9 wc
    		locktry	z9 wc
    		locktry	#$e wc	'try a user defined lock
    
    		nop
    		lockrel	x9 wc	'release the 3 locks
    		lockrel	y9 wc
    		lockrel	z9 wc
    
    		mov	pa,#$e	'release user lock
    		lockrel	pa wc
    		mov	pb,#7	'release different lock
    		lockrel	pb wc
    		nop
    
    gave the following results.
    Cog1: "locktest" Halt>>stat
    nc:nz 00000: 00000000                  NOP
    Cog1: "locktest" Halt>>step 4
    nc:nz 00001: fd708004                  LOCKNEW $40 WC
    nc:nz 00002: fd708204                  LOCKNEW $41 WC
    nc:nz 00003: fd708404                  LOCKNEW $42 WC
    nc:nz 00004: 00000000                  NOP
    Cog1: "locktest" Halt>>rdcog 40 42
    COGRAM 040: $00000000 %00000000_00000000_00000000_00000000
    COGRAM 041: $00000001 %00000000_00000000_00000000_00000001
    COGRAM 042: $00000002 %00000000_00000000_00000000_00000010
    Cog1: "locktest" Halt>>stat
    nc:nz 00004: 00000000                  NOP
    Cog1: "locktest" Halt>>step 5
    nc:nz 00005: fd708006                  LOCKTRY $40 WC
     C:nz 00006: fd708206                  LOCKTRY $41 WC
     C:nz 00007: fd708406                  LOCKTRY $42 WC
     C:nz 00008: fd741c06                  LOCKTRY #$e WC
    nc:nz 00009: 00000000                  NOP
    Cog1: "locktest" Halt>>rdcog 40 42
    COGRAM 040: $00000000 %00000000_00000000_00000000_00000000
    COGRAM 041: $00000001 %00000000_00000000_00000000_00000001
    COGRAM 042: $00000002 %00000000_00000000_00000000_00000010
    Cog1: "locktest" Halt>>stat
    nc:nz 00009: 00000000                  NOP
    Cog1: "locktest" Halt>>step 8
    nc:nz 0000a: fd708007                  LOCKREL $40 WC
    nc:nz 0000b: fd708207                  LOCKREL $41 WC
    nc:nz 0000c: fd708407                  LOCKREL $42 WC
    nc:nz 0000d: f607ec0e                  MOV     PA,#$e
    nc:nz 0000e: fd73ec07                  LOCKREL PA WC
    nc:nz 0000f: f607ee07                  MOV     PB,#$7
    nc:nz 00010: fd73ee07                  LOCKREL PB WC
    nc:nz 00011: 00000000                  NOP
    Cog1: "locktest" Halt>>rdcog 40 42
    COGRAM 040: $00000001 %00000000_00000000_00000000_00000001
    COGRAM 041: $00000001 %00000000_00000000_00000000_00000001
    COGRAM 042: $00000001 %00000000_00000000_00000000_00000001
    Cog1: "locktest" Halt>>pa
    PA    1f6: 00000000 %00000000_00000000_00000000_00000000
    Cog1: "locktest" Halt>>pb
    PB    1f7: 00000000 %00000000_00000000_00000000_00000000
    Cog1: "locktest" Halt>>
    
    Need to dig a bit deeper....
  • @cgracey
    After further test it appears that LOCKTRY won't grab a free lock but can STEAL an already captured lock from other cogs!
  • @cgracey
    The LOCKREL instruction is not working properly also.
    It only returns the owner and state of a lock captured with LOCKTRY not LOCKNEW.
  • SeairthSeairth Posts: 2,419
    edited 2020-04-29 - 11:36:58
    (Edit: docs corrected. Ignore this to avoid confusion.)

    if the locks work similar to P1, I think it works as follows: locks are actually two 16-bit registers. One register manages "ownership" and one manages "held locks". LOCKNEW and LOCKNEW and LOCKRET work on the first register, while LOCKTRY and LOCKREL work on the second register. The idea goes something like this:

    Cog A calls LOCKNEW to get an "available lock" (from the first register)
    Cog A then shares that index with Cog B that it wants to use the locks with.
    Cog A and Cog B use LOCKTRY and LOCKREL to coordinate (via the second register)
    Optionally, Cog A may call LOCKRET to free up a lock for others to use.

    In this scheme, everything is strictly cooperative. In other words, there is nothing stopping cogs from using LOCKTRY and LOCKREL for any of the locks, except by a priori agreement (either hardcoded lock indexes or the use of LOCKNEW/LOCKRET to dynamically get an index). Similarly, there's nothing stopping from Cog B calling LOCKRET for a lock that was assigned to Cog A by LOCKNEW. The presumption is that the software is written "correctly" and follows the LOCKNEW->repeat(LOCKTRY->LOCKREL)->LOCKRET pattern.

    Given this, LOCKTRY should not be able to steal from the same index where another LOCKTRY has already succeeded (but LOCKREL has not yet been called). But it can definitely grab the lock for any other lock, regardless of calls to LOCKNEW.

    Does this match what you are seeing?
  • On the P2, the LOCKs work differently than they did on the P1. I documented it in the big Google Doc file.

    Under this new scheme, any cog that shuts down or restarts automatically releases any lock it has. This was all done with future debugging in mind.
  • I've done some more experimenting and found that a lock does indeed need to be checked out before LOCKTRY and LOCKREL will work,
    contrary to what the doc's say: "LOCKs can be used directly, without the hub allocating them..."
    I've also found that any cog can issue a LOCKNEW or LOCKRET for any lock at any time-- there is no exclusion to which cog can do a LOCKRET.
    Once a LOCKNEW is issued and the lock number attained, LOCKTRY and LOCKREL do work as expected.

    Here is the code I used to experiment with:
    (I have LEDS connected to the P31-P0 port pins- great for debugging)

    'test locktry instruction
    
    DAT		
    			orgh 0
    
    			coginit #1,#@testlock
    
    			mov	dira,#$F
    			drvh	#56
    			locknew	temp wc
    			nop			'nop needed or both locknew's do not work
    			locknew temp wc
    			locktry #0 wc
    			locktry	#1 wc
    			'lockrel	#0
    			'lockrel	#1
    			outnc	#56
    			mov	outa,temp	'output last lock number to LEDs on P3-P0
    
    inf    			jmp	#inf
    
    temp			long	0
    
    
    			org 0                        'find out which locks we can attain after a brief delay
    testlock		mov	dira,##$FFFF0000
    			waitx	##40000000	'delay a couple seconds
    			mov	a3,#0		'locktry all locks	
    			mov	a1,#$F
    .L1			locktry a1 wc
    			rcl	a3,#1		'keep track
    			djnf	a1,#.L1
    			shl	a3,#16
    			mov	outa,a3		'send to LEDs on P31-P16
    inf1			jmp	#inf1
    
    a1			res
    a2			res
    a3			res
    a4			res
    

    So, I guess the only way to use the locks directly is just to LOCKNEW all the locks you need and leave them checked out.
  • Seairth wrote: »
    In other words, there is nothing stopping cogs from using LOCKTRY and LOCKREL for any of the locks, except by a priori agreement (either hardcoded lock indexes or the use of LOCKNEW/LOCKRET to dynamically get an index).
    from the docs.
    "LOCKs can be used directly, without the hub allocating them..."

    I interpreted this quote in the docs to mean that I can nominate my own hardcoded indexes using LOCKTRY.
    My use of the word "STEAL" was probably misleading to indicate the use of LOCKNEW first to allocate a lock.


  • Sorry about this, Guys. Yes, it IS necessary for a LOCK to be allocated via LOCKNEW before it can be set. I don't know why I write the Doc to say otherwise. I think it was carryover from P1 thinking.

    I just got rid of the offending sentence in the Doc file.
  • cgracey wrote: »
    Sorry about this, Guys. Yes, it IS necessary for a LOCK to be allocated via LOCKNEW before it can be set. I don't know why I write the Doc to say otherwise. I think it was carryover from P1 thinking.

    I just got rid of the offending sentence in the Doc file.

    No worries Chip.
    Docs are cheaper to fix than silicon! :smiley:
  • I have updated the Google Doc based on the information above, as well as to make the usage language more consistent. Please make comments if you see mistakes.

    https://docs.google.com/document/d/1gn6oaT5Ib7CytvlZHacmrSbVBJsD9t_-kmvjd7nUR6o/edit#heading=h.g9zh968b50bv
  • Cluso99Cluso99 Posts: 16,147
    edited 2020-05-17 - 10:59:45
    Spin v Spin2: LOCKSET v LOCKTRY

    In spin we did
    repeat while(lockset(LockID))
    
    whereas in spin2
    repeat while not (locktry(LockID))
    
    I've put this in the P2 Tricks and Traps thread too.

    Postedit: Fixed as per Eric's suggestion
  • Cluso99 wrote: »
    Spin v Spin2: LOCKSET v LOCKTRY

    In spin we did
    repeat while(lockset(LockID))
    
    whereas in spin2
    repeat while not (locktry(cardLockID - 1))
    
    I've put this in the P2 Tricks and Traps thread too.

    Is there some significance to using "cardLockID - 1" instead of "LockID"? I assume not, but this could very well become a source of confusion to new users who think that besides the NOT difference one must also subtract one from the lock ID in Spin2.
  • Thanks Eric.
    I changed the first but forgot to change the second :(
Sign In or Register to comment.