home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / comp / programm / 3341 < prev    next >
Encoding:
Internet Message Format  |  1992-12-21  |  5.3 KB

  1. Path: sparky!uunet!zaphod.mps.ohio-state.edu!magnus.acs.ohio-state.edu!usenet.ins.cwru.edu!slc6!trier
  2. From: trier@slc6.ins.cwru.edu (Stephen C. Trier)
  3. Newsgroups: comp.programming
  4. Subject: Re: Semaphores, Swap, or Test_And_Set
  5. Date: 21 Dec 1992 18:45:13 GMT
  6. Organization: Case Western Reserve University, Cleveland OH (USA)
  7. Lines: 133
  8. Message-ID: <1h53bpINNabh@usenet.INS.CWRU.Edu>
  9. References: <1992Dec18.045022.15255@umbc3.umbc.edu> <1gsscvINNa2r@usenet.INS.CWRU.Edu> <1992Dec18.195139.15322@umbc3.umbc.edu>
  10. NNTP-Posting-Host: slc6.ins.cwru.edu
  11.  
  12. In article <1992Dec18.195139.15322@umbc3.umbc.edu> reagle@umbc8.umbc.edu (Mr. Joseph Reagle; MEYERHOFF (U)) writes:
  13. >    Sounds like a pain, I'm not familiar with how DOS deals with
  14. >deals with interupts whether priority based, FCFS, interupts could
  15. >occur but only queued ...
  16.  
  17. Yes, they are priority based and there is a mechanism for merely delaying
  18. them until after interrupts are unmasked, rather than dropping them
  19. entirely.  However, if a second interrupt comes in at the same priority
  20. level, the record that there was a first interrupt gets lost.
  21.  
  22. This was pounded into my head when I was investigating (1) why my network
  23. code was sometimes dropping packets, and (2) why my system clock ran slow
  24. when I used a SLIP (Serial-Line IP) driver.  In both cases, the interrupts
  25. were getting masked and in certain rare cases, this caused a critical
  26. interrupt to get lost.
  27.  
  28. >    Don't know what xchg does and I am not quite sure how to
  29. >implement test_and_set using inc or dec.
  30.  
  31. XCHG is "exchange", the classic test-and-set instruction.  Here's some
  32. minimal assembly code.  It wouldn't be hard to turn this into properly
  33. C-callable code.
  34.  
  35. ; Test and set the word "flag"
  36. test_and_set:
  37.       mov ax, 1      ; Put a 1 in the AX register
  38.       xchg ax, flag  ; Exchange with flag variable
  39.       ret            ; Return a 1 in AX if we did NOT get the flag.
  40.                      ; Return a 0 if we DID get the flag.
  41.                      ; Note that ZF is not set.  Must look in AX directly.
  42.  
  43. clear_flag:
  44.       xor ax, ax     ; Get a 0 into AX.
  45.       mov flag, ax   ; Clear the flag, saying we're done.
  46.       ret
  47.  
  48. You could use this basic pair of primitives to build and sort of mutual
  49. exclusion mechanism you would like.  Making them more sophisticated
  50. requires at least a busy-loop; if you want to guarantee fairness, you
  51. need some slick algorithms or interaction with the process scheduler.
  52.  
  53. The INC/DEC approach does the same thing, just a little differently.
  54. Here's some code I wrote to do it:
  55.  
  56. /*
  57.  *  C function to initialize a semaphore.
  58.  */
  59.  
  60. void sem_init(int *p)
  61. {
  62.     *p = -1;
  63. }
  64.  
  65. ; Assembly code to manipulate semaphores.
  66.  
  67. ; int sem_set(int *p)    Set a semaphore.  Return 1 if semaphore OK, 0 if not.
  68.  
  69. _sem_set proc near
  70.     push    bp            ; Set up a standard stack frame
  71.     mov    bp, sp            ;       "              "
  72.     mov    bx, word ptr [bx+4]    ; Get the address of the semaphore
  73.     lock inc word ptr [bx]        ; Increment it and maybe set Zero Flag
  74.     jz    success            ; Success if ZF is set.
  75. failure:
  76.     lock dec word ptr [bx]        ; ZF not set; remove our increment
  77.     xor    ax,ax            ; Return 0 (false) to C
  78.     pop    bp            ; Clean up stack frame and return
  79.     ret
  80. success:
  81.     mov    ax,1            ; Return 1 (true) to C
  82.     pop    bp            ; Clean up and return
  83.     ret
  84. _sem_set endp
  85.  
  86. ; void sem_clear(int *p)   Clear a semaphore
  87.  
  88. _sem_clear proc near
  89.     push    bp            ; Set up standard stack frame
  90.     mov    bp, sp
  91.     mov    bx, word ptr [bp+4]    ; Get address of the semaphore
  92.     lock dec word ptr [bx]        ; Decrement it
  93.     pop    bp            ; Clean up stack frame and return
  94.     ret
  95. _sem_clear endp
  96.  
  97. Please excuse any ugliness in my 8086 style.  Most of my assembly
  98. programming has been in the 680X/680X0 families and I still feel a little
  99. awkward on the 8086.  Everything is so _backwards_!  ;-)
  100.  
  101. This approach uses the a lock prefix to make INC and DEC atomic, even
  102. on multiprocessors.  It depends on the flag-setting behavior of INC and
  103. DEC, in that ZF, the Zero Flag, will be set if the result of the increment
  104. is 0.  It will not be set to 0 at any other time.
  105.  
  106. You could regard the assembly as being somewhat like the following C code:
  107.  
  108. int sem_set(int *p)
  109. {
  110.     if ((*p)++ == 0)
  111.         return 1;
  112.     else  {
  113.         (*p)--;
  114.         return 0;
  115.     }
  116. }
  117.  
  118. void sem_clear(int *p)
  119. {
  120.     (*p)--;
  121. }
  122.  
  123. The difference between this and the assembly is that instruction selection
  124. (and the LOCK prefix) is essential for this to work right, so it is best
  125. not to trust that the compiler will get it right.  The only way to guarantee
  126. that it's done right is to do it yourself.
  127.  
  128. There are some who might disagree with my referring to these as semaphores,
  129. since they are non-blocking and cannot be used as counting semaphores.  If
  130. it makes you feel better, think of them as semaphore building blocks, around
  131. which you can build whatever sort of fancy setup you want.
  132.  
  133. BTW, it should be trivial to turn these into counting semaphores.  I'm just
  134. using them for simple mutual exclusion, so I do not need anything that fancy.
  135.  
  136. I'd eventually like to rewrite this in inline assembly in C, and perhaps
  137. to switch to the shorter and simpler xchg sequence.  This works, though,
  138. and right now, that's what I need in order to get this software out the door.
  139.  
  140. -- 
  141. Stephen Trier                      "We want to offer you a price that you
  142. Network software type               just can't afford to take advantage of."
  143. Case Western Reserve University         - Sales blurb from HSC Software
  144. trier@ins.cwru.edu
  145.